kibana-sinatra 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/kibana-sinatra.gemspec +24 -0
- data/lib/kibana/assets/app/app.js +140 -0
- data/lib/kibana/assets/app/components/extend-jquery.js +46 -0
- data/lib/kibana/assets/app/components/kbn.js +332 -0
- data/lib/kibana/assets/app/components/require.config.js +90 -0
- data/lib/kibana/assets/app/components/settings.js +27 -0
- data/lib/kibana/assets/app/components/underscore.extended.js +32 -0
- data/lib/kibana/assets/app/controllers/all.js +5 -0
- data/lib/kibana/assets/app/controllers/dash.js +91 -0
- data/lib/kibana/assets/app/controllers/dashLoader.js +123 -0
- data/lib/kibana/assets/app/controllers/row.js +76 -0
- data/lib/kibana/assets/app/dashboards/blank.json +42 -0
- data/lib/kibana/assets/app/dashboards/default.json +89 -0
- data/lib/kibana/assets/app/dashboards/guided.json +274 -0
- data/lib/kibana/assets/app/dashboards/logstash.js +181 -0
- data/lib/kibana/assets/app/dashboards/logstash.json +222 -0
- data/lib/kibana/assets/app/dashboards/noted.json +202 -0
- data/lib/kibana/assets/app/directives/addPanel.js +30 -0
- data/lib/kibana/assets/app/directives/all.js +10 -0
- data/lib/kibana/assets/app/directives/arrayJoin.js +34 -0
- data/lib/kibana/assets/app/directives/confirmClick.js +26 -0
- data/lib/kibana/assets/app/directives/dashUpload.js +37 -0
- data/lib/kibana/assets/app/directives/kibanaPanel.js +103 -0
- data/lib/kibana/assets/app/directives/ngBlur.js +20 -0
- data/lib/kibana/assets/app/directives/ngModelOnBlur.js +25 -0
- data/lib/kibana/assets/app/directives/tip.js +20 -0
- data/lib/kibana/assets/app/filters/all.js +110 -0
- data/lib/kibana/assets/app/panels/bettermap/editor.html +17 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/images/layers-2x.png +0 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/images/layers.png +0 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/images/marker-icon-2x.png +0 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/images/marker-icon.png +0 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/images/marker-shadow.png +0 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/leaflet-src.js +8724 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/leaflet.css +463 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/leaflet.ie.css +51 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/leaflet.js +8 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/plugins.css +75 -0
- data/lib/kibana/assets/app/panels/bettermap/leaflet/plugins.js +16 -0
- data/lib/kibana/assets/app/panels/bettermap/module.css +4 -0
- data/lib/kibana/assets/app/panels/bettermap/module.html +6 -0
- data/lib/kibana/assets/app/panels/bettermap/module.js +232 -0
- data/lib/kibana/assets/app/panels/column/editor.html +36 -0
- data/lib/kibana/assets/app/panels/column/module.html +16 -0
- data/lib/kibana/assets/app/panels/column/module.js +105 -0
- data/lib/kibana/assets/app/panels/column/panelgeneral.html +11 -0
- data/lib/kibana/assets/app/panels/dashcontrol/editor.html +44 -0
- data/lib/kibana/assets/app/panels/dashcontrol/load.html +40 -0
- data/lib/kibana/assets/app/panels/dashcontrol/module.html +6 -0
- data/lib/kibana/assets/app/panels/dashcontrol/module.js +198 -0
- data/lib/kibana/assets/app/panels/dashcontrol/save.html +30 -0
- data/lib/kibana/assets/app/panels/dashcontrol/share.html +11 -0
- data/lib/kibana/assets/app/panels/derivequeries/editor.html +23 -0
- data/lib/kibana/assets/app/panels/derivequeries/module.html +33 -0
- data/lib/kibana/assets/app/panels/derivequeries/module.js +160 -0
- data/lib/kibana/assets/app/panels/fields/editor.html +10 -0
- data/lib/kibana/assets/app/panels/fields/micropanel.html +25 -0
- data/lib/kibana/assets/app/panels/fields/module.html +3 -0
- data/lib/kibana/assets/app/panels/fields/module.js +37 -0
- data/lib/kibana/assets/app/panels/filtering/editor.html +7 -0
- data/lib/kibana/assets/app/panels/filtering/meta.html +15 -0
- data/lib/kibana/assets/app/panels/filtering/module.html +78 -0
- data/lib/kibana/assets/app/panels/filtering/module.js +66 -0
- data/lib/kibana/assets/app/panels/histogram/editor.html +74 -0
- data/lib/kibana/assets/app/panels/histogram/interval.js +57 -0
- data/lib/kibana/assets/app/panels/histogram/module.html +91 -0
- data/lib/kibana/assets/app/panels/histogram/module.js +511 -0
- data/lib/kibana/assets/app/panels/histogram/timeSeries.js +179 -0
- data/lib/kibana/assets/app/panels/hits/editor.html +29 -0
- data/lib/kibana/assets/app/panels/hits/module.html +44 -0
- data/lib/kibana/assets/app/panels/hits/module.js +270 -0
- data/lib/kibana/assets/app/panels/map/editor.html +15 -0
- data/lib/kibana/assets/app/panels/map/lib/jquery.jvectormap.min.js +8 -0
- data/lib/kibana/assets/app/panels/map/lib/map.europe.js +1 -0
- data/lib/kibana/assets/app/panels/map/lib/map.usa.js +1 -0
- data/lib/kibana/assets/app/panels/map/lib/map.world.js +1 -0
- data/lib/kibana/assets/app/panels/map/module.html +63 -0
- data/lib/kibana/assets/app/panels/map/module.js +185 -0
- data/lib/kibana/assets/app/panels/pie/editor.html +49 -0
- data/lib/kibana/assets/app/panels/pie/module.html +12 -0
- data/lib/kibana/assets/app/panels/pie/module.js +297 -0
- data/lib/kibana/assets/app/panels/query/editor.html +7 -0
- data/lib/kibana/assets/app/panels/query/meta.html +21 -0
- data/lib/kibana/assets/app/panels/query/module.html +25 -0
- data/lib/kibana/assets/app/panels/query/module.js +69 -0
- data/lib/kibana/assets/app/panels/query/query.css +39 -0
- data/lib/kibana/assets/app/panels/table/editor.html +48 -0
- data/lib/kibana/assets/app/panels/table/micropanel.html +44 -0
- data/lib/kibana/assets/app/panels/table/module.html +104 -0
- data/lib/kibana/assets/app/panels/table/module.js +389 -0
- data/lib/kibana/assets/app/panels/table/pagination.html +27 -0
- data/lib/kibana/assets/app/panels/terms/editor.html +51 -0
- data/lib/kibana/assets/app/panels/terms/module.html +55 -0
- data/lib/kibana/assets/app/panels/terms/module.js +307 -0
- data/lib/kibana/assets/app/panels/text/editor.html +16 -0
- data/lib/kibana/assets/app/panels/text/lib/showdown.js +1454 -0
- data/lib/kibana/assets/app/panels/text/module.html +10 -0
- data/lib/kibana/assets/app/panels/text/module.js +85 -0
- data/lib/kibana/assets/app/panels/timepicker/editor.html +34 -0
- data/lib/kibana/assets/app/panels/timepicker/module.html +73 -0
- data/lib/kibana/assets/app/panels/timepicker/module.js +268 -0
- data/lib/kibana/assets/app/panels/timepicker/refreshctrl.html +5 -0
- data/lib/kibana/assets/app/panels/trends/editor.html +20 -0
- data/lib/kibana/assets/app/panels/trends/module.html +11 -0
- data/lib/kibana/assets/app/panels/trends/module.js +232 -0
- data/lib/kibana/assets/app/partials/dashLoader.html +78 -0
- data/lib/kibana/assets/app/partials/dashLoaderShare.html +11 -0
- data/lib/kibana/assets/app/partials/dashboard.html +77 -0
- data/lib/kibana/assets/app/partials/dasheditor.html +151 -0
- data/lib/kibana/assets/app/partials/inspector.html +15 -0
- data/lib/kibana/assets/app/partials/load.html +4 -0
- data/lib/kibana/assets/app/partials/modal.html +12 -0
- data/lib/kibana/assets/app/partials/paneladd.html +6 -0
- data/lib/kibana/assets/app/partials/paneleditor.html +23 -0
- data/lib/kibana/assets/app/partials/panelgeneral.html +22 -0
- data/lib/kibana/assets/app/partials/querySelect.html +24 -0
- data/lib/kibana/assets/app/partials/roweditor.html +65 -0
- data/lib/kibana/assets/app/services/alertSrv.js +49 -0
- data/lib/kibana/assets/app/services/all.js +11 -0
- data/lib/kibana/assets/app/services/dashboard.js +417 -0
- data/lib/kibana/assets/app/services/fields.js +96 -0
- data/lib/kibana/assets/app/services/filterSrv.js +200 -0
- data/lib/kibana/assets/app/services/kbnIndex.js +101 -0
- data/lib/kibana/assets/app/services/panelMove.js +83 -0
- data/lib/kibana/assets/app/services/querySrv.js +147 -0
- data/lib/kibana/assets/app/services/timer.js +34 -0
- data/lib/kibana/assets/css/animate.min.css +3270 -0
- data/lib/kibana/assets/css/bootstrap-responsive.min.css +9 -0
- data/lib/kibana/assets/css/bootstrap.dark.min.css +9 -0
- data/lib/kibana/assets/css/bootstrap.light.min.css +9 -0
- data/lib/kibana/assets/css/font-awesome.min.css +403 -0
- data/lib/kibana/assets/css/main.css +193 -0
- data/lib/kibana/assets/css/normalize.min.css +1 -0
- data/lib/kibana/assets/css/timepicker.css +423 -0
- data/lib/kibana/assets/font/FontAwesome.otf +0 -0
- data/lib/kibana/assets/font/fontawesome-webfont.eot +0 -0
- data/lib/kibana/assets/font/fontawesome-webfont.svg +399 -0
- data/lib/kibana/assets/font/fontawesome-webfont.ttf +0 -0
- data/lib/kibana/assets/font/fontawesome-webfont.woff +0 -0
- data/lib/kibana/assets/img/glyphicons-halflings-white.png +0 -0
- data/lib/kibana/assets/img/glyphicons-halflings.png +0 -0
- data/lib/kibana/assets/img/kibana.png +0 -0
- data/lib/kibana/assets/img/load.gif +0 -0
- data/lib/kibana/assets/img/load_big.gif +0 -0
- data/lib/kibana/assets/index.html +49 -0
- data/lib/kibana/assets/vendor/angular/angular-dragdrop.js +304 -0
- data/lib/kibana/assets/vendor/angular/angular-sanitize.js +556 -0
- data/lib/kibana/assets/vendor/angular/angular-strap.js +875 -0
- data/lib/kibana/assets/vendor/angular/angular.js +15158 -0
- data/lib/kibana/assets/vendor/angular/datepicker.js +1046 -0
- data/lib/kibana/assets/vendor/angular/timepicker.js +888 -0
- data/lib/kibana/assets/vendor/bootstrap/bootstrap.js +2280 -0
- data/lib/kibana/assets/vendor/bootstrap/less/accordion.less +34 -0
- data/lib/kibana/assets/vendor/bootstrap/less/alerts.less +79 -0
- data/lib/kibana/assets/vendor/bootstrap/less/bootstrap.dark.less +4 -0
- data/lib/kibana/assets/vendor/bootstrap/less/bootstrap.less +63 -0
- data/lib/kibana/assets/vendor/bootstrap/less/bootstrap.light.less +4 -0
- data/lib/kibana/assets/vendor/bootstrap/less/bootswatch.dark.less +554 -0
- data/lib/kibana/assets/vendor/bootstrap/less/bootswatch.light.less +9 -0
- data/lib/kibana/assets/vendor/bootstrap/less/breadcrumbs.less +24 -0
- data/lib/kibana/assets/vendor/bootstrap/less/button-groups.less +229 -0
- data/lib/kibana/assets/vendor/bootstrap/less/buttons.less +228 -0
- data/lib/kibana/assets/vendor/bootstrap/less/carousel.less +158 -0
- data/lib/kibana/assets/vendor/bootstrap/less/close.less +32 -0
- data/lib/kibana/assets/vendor/bootstrap/less/code.less +61 -0
- data/lib/kibana/assets/vendor/bootstrap/less/component-animations.less +22 -0
- data/lib/kibana/assets/vendor/bootstrap/less/dropdowns.less +248 -0
- data/lib/kibana/assets/vendor/bootstrap/less/forms.less +690 -0
- data/lib/kibana/assets/vendor/bootstrap/less/grid.less +21 -0
- data/lib/kibana/assets/vendor/bootstrap/less/hero-unit.less +25 -0
- data/lib/kibana/assets/vendor/bootstrap/less/labels-badges.less +84 -0
- data/lib/kibana/assets/vendor/bootstrap/less/layouts.less +16 -0
- data/lib/kibana/assets/vendor/bootstrap/less/media.less +55 -0
- data/lib/kibana/assets/vendor/bootstrap/less/mixins.less +702 -0
- data/lib/kibana/assets/vendor/bootstrap/less/modals.less +95 -0
- data/lib/kibana/assets/vendor/bootstrap/less/navbar.less +497 -0
- data/lib/kibana/assets/vendor/bootstrap/less/navs.less +409 -0
- data/lib/kibana/assets/vendor/bootstrap/less/overrides.less +237 -0
- data/lib/kibana/assets/vendor/bootstrap/less/pager.less +43 -0
- data/lib/kibana/assets/vendor/bootstrap/less/pagination.less +123 -0
- data/lib/kibana/assets/vendor/bootstrap/less/popovers.less +133 -0
- data/lib/kibana/assets/vendor/bootstrap/less/progress-bars.less +122 -0
- data/lib/kibana/assets/vendor/bootstrap/less/reset.less +216 -0
- data/lib/kibana/assets/vendor/bootstrap/less/responsive-1200px-min.less +28 -0
- data/lib/kibana/assets/vendor/bootstrap/less/responsive-767px-max.less +193 -0
- data/lib/kibana/assets/vendor/bootstrap/less/responsive-768px-979px.less +19 -0
- data/lib/kibana/assets/vendor/bootstrap/less/responsive-navbar.less +189 -0
- data/lib/kibana/assets/vendor/bootstrap/less/responsive-utilities.less +59 -0
- data/lib/kibana/assets/vendor/bootstrap/less/responsive.less +48 -0
- data/lib/kibana/assets/vendor/bootstrap/less/scaffolding.less +53 -0
- data/lib/kibana/assets/vendor/bootstrap/less/sprites.less +197 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tables.less +244 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/buttons.html +139 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/css-tests.css +150 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/css-tests.html +1399 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/forms-responsive.html +71 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/forms.html +179 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/navbar-fixed-top.html +104 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/navbar-static-top.html +107 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tests/navbar.html +107 -0
- data/lib/kibana/assets/vendor/bootstrap/less/thumbnails.less +53 -0
- data/lib/kibana/assets/vendor/bootstrap/less/tooltip.less +70 -0
- data/lib/kibana/assets/vendor/bootstrap/less/type.less +247 -0
- data/lib/kibana/assets/vendor/bootstrap/less/utilities.less +30 -0
- data/lib/kibana/assets/vendor/bootstrap/less/variables.dark.less +304 -0
- data/lib/kibana/assets/vendor/bootstrap/less/variables.less +301 -0
- data/lib/kibana/assets/vendor/bootstrap/less/variables.light.less +301 -0
- data/lib/kibana/assets/vendor/bootstrap/less/wells.less +29 -0
- data/lib/kibana/assets/vendor/elasticjs/elastic-angular-client.js +81 -0
- data/lib/kibana/assets/vendor/elasticjs/elastic.js +19993 -0
- data/lib/kibana/assets/vendor/filesaver.js +216 -0
- data/lib/kibana/assets/vendor/jquery/jquery-1.8.0.js +2 -0
- data/lib/kibana/assets/vendor/jquery/jquery-ui-1.10.3.js +5253 -0
- data/lib/kibana/assets/vendor/jquery/jquery.flot.js +3060 -0
- data/lib/kibana/assets/vendor/jquery/jquery.flot.pie.js +817 -0
- data/lib/kibana/assets/vendor/jquery/jquery.flot.selection.js +360 -0
- data/lib/kibana/assets/vendor/jquery/jquery.flot.stack.js +188 -0
- data/lib/kibana/assets/vendor/jquery/jquery.flot.stackpercent.js +126 -0
- data/lib/kibana/assets/vendor/jquery/jquery.flot.time.js +431 -0
- data/lib/kibana/assets/vendor/modernizr-2.6.1.js +4 -0
- data/lib/kibana/assets/vendor/moment.js +1662 -0
- data/lib/kibana/assets/vendor/require/css-build.js +78 -0
- data/lib/kibana/assets/vendor/require/css.js +23 -0
- data/lib/kibana/assets/vendor/require/require.js +2024 -0
- data/lib/kibana/assets/vendor/require/text.js +386 -0
- data/lib/kibana/assets/vendor/require/tmpl.js +17 -0
- data/lib/kibana/assets/vendor/timezone.js +993 -0
- data/lib/kibana/assets/vendor/underscore.js +1246 -0
- data/lib/kibana/sinatra.rb +3 -0
- data/lib/kibana/sinatra/version.rb +5 -0
- data/lib/kibana/sinatra/web.rb +28 -0
- data/lib/kibana/views/config.erb +54 -0
- metadata +325 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
<div class="row-fluid">
|
2
|
+
<div class="span2">
|
3
|
+
<label class="small">Mode</label>
|
4
|
+
<select ng-change="set_refresh(true)" class="input-small" ng-model="panel.mode" ng-options="f for f in ['count','min','mean','max','total']"></select>
|
5
|
+
</div>
|
6
|
+
<div class="span2">
|
7
|
+
<label class="small">Time Field</label>
|
8
|
+
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.time_field">
|
9
|
+
</div>
|
10
|
+
<div class="span2" ng-show="panel.mode != 'count'">
|
11
|
+
<label class="small">Value Field</label>
|
12
|
+
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.value_field">
|
13
|
+
</div>
|
14
|
+
<div class="span3" ng-show="panel.mode != 'count'">
|
15
|
+
<label class="small">Note</label><small> In <strong>{{panel.mode}}</strong> mode the configured field <strong>must</strong> be a numeric type</small>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
<h5>Chart Settings</h5>
|
19
|
+
<div class="row-fluid" style="text-align:center;margin-bottom:10px;">
|
20
|
+
<div class="span1"> <label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars"></div>
|
21
|
+
<div class="span1"> <label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines"></div>
|
22
|
+
<div class="span1"> <label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points"></div>
|
23
|
+
<div class="span1"> <label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack"></div>
|
24
|
+
<div class="span1" ng-show="panel.stack">
|
25
|
+
<label style="white-space:nowrap" class="small">Percent <tip>Stack as a percentage of total</tip></label>
|
26
|
+
<input type="checkbox" ng-model="panel.percentage" ng-checked="panel.percentage">
|
27
|
+
</div>
|
28
|
+
<div class="span1"> <label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend"></div>
|
29
|
+
<div class="span1"> <label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
|
30
|
+
<div class="span1"> <label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
|
31
|
+
<div class="span2" ng-show="panel.lines">
|
32
|
+
<label class="small">Line Fill</label>
|
33
|
+
<select class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
|
34
|
+
</div>
|
35
|
+
<div class="span2" ng-show="panel.lines">
|
36
|
+
<label class="small">Line Width</label>
|
37
|
+
<select class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"></select>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
<div class="row-fluid">
|
41
|
+
<div class="span2">
|
42
|
+
<label class="small">Time correction</label>
|
43
|
+
<select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
|
44
|
+
</div>
|
45
|
+
<div class="span1"> <label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive"></div>
|
46
|
+
<div class="span2">
|
47
|
+
<label class="small">Zoom Links</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
|
48
|
+
</div>
|
49
|
+
<div class="span2">
|
50
|
+
<label class="small">View Options</label><input type="checkbox" ng-model="panel.options" ng-checked="panel.options" />
|
51
|
+
</div>
|
52
|
+
<div class="span2">
|
53
|
+
<label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
|
54
|
+
</div>
|
55
|
+
<div class="span2" ng-show='panel.auto_int'>
|
56
|
+
<label class="small">Resolution <tip>Shoot for this many data points, rounding to sane intervals</tip></label>
|
57
|
+
<input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
|
58
|
+
</div>
|
59
|
+
<div class="span2" ng-hide='panel.auto_int'>
|
60
|
+
<label class="small">Interval <tip>Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</tip></label>
|
61
|
+
<input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
|
62
|
+
</div>
|
63
|
+
</div>
|
64
|
+
<h5>Tooltip Settings</h5>
|
65
|
+
<div class="row-fluid" style="margin-bottom:10px;">
|
66
|
+
<div class="span3">
|
67
|
+
<label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
|
68
|
+
<select class="input-medium" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
|
69
|
+
</div>
|
70
|
+
<div class="span3">
|
71
|
+
<label class="small">Display Query <tip>If an alias is set, it will be shown in the tooltip. If not, should it show the query?</tip></label>
|
72
|
+
<input type="checkbox" ng-model="panel.tooltip.query_as_alias" />
|
73
|
+
</div>
|
74
|
+
</div>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
define([
|
2
|
+
'kbn'
|
3
|
+
],
|
4
|
+
function (kbn) {
|
5
|
+
'use strict';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* manages the interval logic
|
9
|
+
* @param {[type]} interval_string An interval string in the format '1m', '1y', etc
|
10
|
+
*/
|
11
|
+
function Interval(interval_string) {
|
12
|
+
this.string = interval_string;
|
13
|
+
|
14
|
+
var info = kbn.describe_interval(interval_string);
|
15
|
+
this.type = info.type;
|
16
|
+
this.ms = info.sec * 1000 * info.count;
|
17
|
+
|
18
|
+
// does the length of the interval change based on the current time?
|
19
|
+
if (this.type === 'y' || this.type === 'M') {
|
20
|
+
// we will just modify this time object rather that create a new one constantly
|
21
|
+
this.get = this.get_complex;
|
22
|
+
this.date = new Date(0);
|
23
|
+
} else {
|
24
|
+
this.get = this.get_simple;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
Interval.prototype = {
|
29
|
+
toString: function () {
|
30
|
+
return this.string;
|
31
|
+
},
|
32
|
+
after: function(current_ms) {
|
33
|
+
return this.get(current_ms, 1);
|
34
|
+
},
|
35
|
+
before: function (current_ms) {
|
36
|
+
return this.get(current_ms, -1);
|
37
|
+
},
|
38
|
+
get_complex: function (current, delta) {
|
39
|
+
this.date.setTime(current);
|
40
|
+
switch(this.type) {
|
41
|
+
case 'M':
|
42
|
+
this.date.setUTCMonth(this.date.getUTCMonth() + delta);
|
43
|
+
break;
|
44
|
+
case 'y':
|
45
|
+
this.date.setUTCFullYear(this.date.getUTCFullYear() + delta);
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
return this.date.getTime();
|
49
|
+
},
|
50
|
+
get_simple: function (current, delta) {
|
51
|
+
return current + (delta * this.ms);
|
52
|
+
}
|
53
|
+
};
|
54
|
+
|
55
|
+
return Interval;
|
56
|
+
|
57
|
+
});
|
@@ -0,0 +1,91 @@
|
|
1
|
+
<div ng-controller='histogram' ng-init="init()" style="min-height:{{panel.height || row.height}}">
|
2
|
+
<style>
|
3
|
+
.histogram-legend {
|
4
|
+
display:inline-block;
|
5
|
+
padding-right:5px
|
6
|
+
}
|
7
|
+
.histogram-legend-dot {
|
8
|
+
display:inline-block;
|
9
|
+
height:10px;
|
10
|
+
width:10px;
|
11
|
+
border-radius:5px;
|
12
|
+
}
|
13
|
+
.histogram-legend-item {
|
14
|
+
display:inline-block;
|
15
|
+
}
|
16
|
+
.histogram-chart {
|
17
|
+
position:relative;
|
18
|
+
}
|
19
|
+
.histogram-options {
|
20
|
+
padding: 5px;
|
21
|
+
margin-right: 15px;
|
22
|
+
margin-bottom: 0px;
|
23
|
+
}
|
24
|
+
.histogram-options label {
|
25
|
+
margin: 0px 0px 0px 10px !important;
|
26
|
+
}
|
27
|
+
.histogram-options span {
|
28
|
+
white-space: nowrap;
|
29
|
+
}
|
30
|
+
|
31
|
+
/* this is actually should be in bootstrap */
|
32
|
+
.form-inline .checkbox {
|
33
|
+
display: inline-block;
|
34
|
+
}
|
35
|
+
</style>
|
36
|
+
<div>
|
37
|
+
<span ng-show='panel.options'>
|
38
|
+
<a class="link underline small" ng-show='panel.options' ng-click="options=!options">
|
39
|
+
<i ng-show="!options" class="icon-caret-right"></i><i ng-show="options" class="icon-caret-down"></i> View
|
40
|
+
</a> | 
|
41
|
+
</span>
|
42
|
+
<span ng-show='panel.zoomlinks && data'>
|
43
|
+
<!--<a class='small' ng-click='zoom(0.5)'><i class='icon-zoom-in'></i> Zoom In</a>-->
|
44
|
+
<a class='small' ng-click='zoom(2)'><i class='icon-zoom-out'></i> Zoom Out</a> | 
|
45
|
+
</span>
|
46
|
+
<span ng-show="panel.legend" ng-repeat='series in data' class="histogram-legend">
|
47
|
+
<i class='icon-circle' ng-style="{color: series.info.color}"></i>
|
48
|
+
<span class='small histogram-legend-item'>{{series.info.alias}} ({{series.hits}})</span>
|
49
|
+
</span>
|
50
|
+
<span ng-show="panel.legend" class="small"><span ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong>{{panel.interval}}</strong> | (<strong>{{hits}}</strong> hits)</span>
|
51
|
+
</div>
|
52
|
+
<form class="form-inline bordered histogram-options" ng-show="options">
|
53
|
+
<div class="checkbox">
|
54
|
+
<label class="small">
|
55
|
+
<input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars" ng-change="render()">
|
56
|
+
Bars
|
57
|
+
</label>
|
58
|
+
</div>
|
59
|
+
<div class="checkbox">
|
60
|
+
<label class="small">
|
61
|
+
<input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines" ng-change="render()">
|
62
|
+
Lines
|
63
|
+
</label>
|
64
|
+
</div>
|
65
|
+
<div class="checkbox">
|
66
|
+
<label class="small">
|
67
|
+
<input type="checkbox" ng-model="panel.points" ng-checked="panel.points" ng-change="render()">
|
68
|
+
Points
|
69
|
+
</label>
|
70
|
+
</div>
|
71
|
+
<div class="checkbox">
|
72
|
+
<label class="small">
|
73
|
+
<input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack" ng-change="render()">
|
74
|
+
Stack
|
75
|
+
</label>
|
76
|
+
</div>
|
77
|
+
<span ng-show="panel.stack">
|
78
|
+
<div class="checkbox">
|
79
|
+
<label style="white-space:nowrap" class="small">
|
80
|
+
<input type="checkbox" ng-model="panel.percentage" ng-checked="panel.percentage" ng-change="render()">
|
81
|
+
Percent
|
82
|
+
</label>
|
83
|
+
</div>
|
84
|
+
</span>
|
85
|
+
<span>
|
86
|
+
<label class="small">Interval</label> <select ng-change="set_interval(panel.interval);get_data();" class="input-small" ng-model="panel.interval" ng-options="interval_label(time) for time in _.union([panel.interval],panel.intervals)"></select>
|
87
|
+
</span>
|
88
|
+
</form>
|
89
|
+
<center><img ng-show='panel.loading && _.isUndefined(data)' src="img/load_big.gif"></center>
|
90
|
+
<div histogram-chart class="pointer histogram-chart" params="{{panel}}"></div>
|
91
|
+
</div>
|
@@ -0,0 +1,511 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
## Histogram
|
4
|
+
|
5
|
+
### Parameters
|
6
|
+
* auto_int :: Auto calculate data point interval?
|
7
|
+
* resolution :: If auto_int is enables, shoot for this many data points, rounding to
|
8
|
+
sane intervals
|
9
|
+
* interval :: Datapoint interval in elasticsearch date math format (eg 1d, 1w, 1y, 5y)
|
10
|
+
* fill :: Only applies to line charts. Level of area shading from 0-10
|
11
|
+
* linewidth :: Only applies to line charts. How thick the line should be in pixels
|
12
|
+
While the editor only exposes 0-10, this can be any numeric value.
|
13
|
+
Set to 0 and you'll get something like a scatter plot
|
14
|
+
* timezone :: This isn't totally functional yet. Currently only supports browser and utc.
|
15
|
+
browser will adjust the x-axis labels to match the timezone of the user's
|
16
|
+
browser
|
17
|
+
* spyable :: Dislay the 'eye' icon that show the last elasticsearch query
|
18
|
+
* zoomlinks :: Show the zoom links?
|
19
|
+
* bars :: Show bars in the chart
|
20
|
+
* stack :: Stack multiple queries. This generally a crappy way to represent things.
|
21
|
+
You probably should just use a line chart without stacking
|
22
|
+
* points :: Should circles at the data points on the chart
|
23
|
+
* lines :: Line chart? Sweet.
|
24
|
+
* legend :: Show the legend?
|
25
|
+
* x-axis :: Show x-axis labels and grid lines
|
26
|
+
* y-axis :: Show y-axis labels and grid lines
|
27
|
+
* interactive :: Allow drag to select time range
|
28
|
+
|
29
|
+
*/
|
30
|
+
define([
|
31
|
+
'angular',
|
32
|
+
'app',
|
33
|
+
'jquery',
|
34
|
+
'underscore',
|
35
|
+
'kbn',
|
36
|
+
'moment',
|
37
|
+
'./timeSeries',
|
38
|
+
|
39
|
+
'jquery.flot',
|
40
|
+
'jquery.flot.pie',
|
41
|
+
'jquery.flot.selection',
|
42
|
+
'jquery.flot.time',
|
43
|
+
'jquery.flot.stack',
|
44
|
+
'jquery.flot.stackpercent'
|
45
|
+
],
|
46
|
+
function (angular, app, $, _, kbn, moment, timeSeries) {
|
47
|
+
|
48
|
+
'use strict';
|
49
|
+
|
50
|
+
var module = angular.module('kibana.panels.histogram', []);
|
51
|
+
app.useModule(module);
|
52
|
+
|
53
|
+
module.controller('histogram', function($scope, querySrv, dashboard, filterSrv) {
|
54
|
+
$scope.panelMeta = {
|
55
|
+
modals : [
|
56
|
+
{
|
57
|
+
description: "Inspect",
|
58
|
+
icon: "icon-info-sign",
|
59
|
+
partial: "app/partials/inspector.html",
|
60
|
+
show: $scope.panel.spyable
|
61
|
+
}
|
62
|
+
],
|
63
|
+
editorTabs : [
|
64
|
+
{
|
65
|
+
title:'Queries',
|
66
|
+
src:'app/partials/querySelect.html'
|
67
|
+
}
|
68
|
+
],
|
69
|
+
status : "Stable",
|
70
|
+
description : "A bucketed time series chart of the current query or queries. Uses the "+
|
71
|
+
"Elasticsearch date_histogram facet. If using time stamped indices this panel will query"+
|
72
|
+
" them sequentially to attempt to apply the lighest possible load to your Elasticsearch cluster"
|
73
|
+
};
|
74
|
+
|
75
|
+
// Set and populate defaults
|
76
|
+
var _d = {
|
77
|
+
mode : 'count',
|
78
|
+
time_field : '@timestamp',
|
79
|
+
queries : {
|
80
|
+
mode : 'all',
|
81
|
+
ids : []
|
82
|
+
},
|
83
|
+
value_field : null,
|
84
|
+
auto_int : true,
|
85
|
+
resolution : 100,
|
86
|
+
interval : '5m',
|
87
|
+
intervals : ['auto','1s','1m','5m','10m','30m','1h','3h','12h','1d','1w','1M','1y'],
|
88
|
+
fill : 0,
|
89
|
+
linewidth : 3,
|
90
|
+
timezone : 'browser', // browser, utc or a standard timezone
|
91
|
+
spyable : true,
|
92
|
+
zoomlinks : true,
|
93
|
+
bars : true,
|
94
|
+
stack : true,
|
95
|
+
points : false,
|
96
|
+
lines : false,
|
97
|
+
legend : true,
|
98
|
+
'x-axis' : true,
|
99
|
+
'y-axis' : true,
|
100
|
+
percentage : false,
|
101
|
+
interactive : true,
|
102
|
+
options : true,
|
103
|
+
tooltip : {
|
104
|
+
value_type: 'cumulative',
|
105
|
+
query_as_alias: false
|
106
|
+
}
|
107
|
+
};
|
108
|
+
|
109
|
+
_.defaults($scope.panel,_d);
|
110
|
+
|
111
|
+
$scope.init = function() {
|
112
|
+
// Hide view options by default
|
113
|
+
$scope.options = false;
|
114
|
+
$scope.$on('refresh',function(){
|
115
|
+
$scope.get_data();
|
116
|
+
});
|
117
|
+
|
118
|
+
$scope.get_data();
|
119
|
+
|
120
|
+
};
|
121
|
+
|
122
|
+
$scope.set_interval = function(interval) {
|
123
|
+
if(interval !== 'auto') {
|
124
|
+
$scope.panel.auto_int = false;
|
125
|
+
$scope.panel.interval = interval;
|
126
|
+
} else {
|
127
|
+
$scope.panel.auto_int = true;
|
128
|
+
}
|
129
|
+
};
|
130
|
+
|
131
|
+
$scope.interval_label = function(interval) {
|
132
|
+
return $scope.panel.auto_int && interval === $scope.panel.interval ? interval+" (auto)" : interval;
|
133
|
+
};
|
134
|
+
|
135
|
+
/**
|
136
|
+
* The time range effecting the panel
|
137
|
+
* @return {[type]} [description]
|
138
|
+
*/
|
139
|
+
$scope.get_time_range = function () {
|
140
|
+
var range = $scope.range = filterSrv.timeRange('min');
|
141
|
+
return range;
|
142
|
+
};
|
143
|
+
|
144
|
+
$scope.get_interval = function () {
|
145
|
+
var interval = $scope.panel.interval,
|
146
|
+
range;
|
147
|
+
if ($scope.panel.auto_int) {
|
148
|
+
range = $scope.get_time_range();
|
149
|
+
if (range) {
|
150
|
+
interval = kbn.secondsToHms(
|
151
|
+
kbn.calculate_interval(range.from, range.to, $scope.panel.resolution, 0) / 1000
|
152
|
+
);
|
153
|
+
}
|
154
|
+
}
|
155
|
+
$scope.panel.interval = interval || '10m';
|
156
|
+
return $scope.panel.interval;
|
157
|
+
};
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Fetch the data for a chunk of a queries results. Multiple segments occur when several indicies
|
161
|
+
* need to be consulted (like timestamped logstash indicies)
|
162
|
+
*
|
163
|
+
* The results of this function are stored on the scope's data property. This property will be an
|
164
|
+
* array of objects with the properties info, time_series, and hits. These objects are used in the
|
165
|
+
* render_panel function to create the historgram.
|
166
|
+
*
|
167
|
+
* @param {number} segment The segment count, (0 based)
|
168
|
+
* @param {number} query_id The id of the query, generated on the first run and passed back when
|
169
|
+
* this call is made recursively for more segments
|
170
|
+
*/
|
171
|
+
$scope.get_data = function(segment, query_id) {
|
172
|
+
if (_.isUndefined(segment)) {
|
173
|
+
segment = 0;
|
174
|
+
}
|
175
|
+
delete $scope.panel.error;
|
176
|
+
|
177
|
+
// Make sure we have everything for the request to complete
|
178
|
+
if(dashboard.indices.length === 0) {
|
179
|
+
return;
|
180
|
+
}
|
181
|
+
var _range = $scope.get_time_range();
|
182
|
+
var _interval = $scope.get_interval(_range);
|
183
|
+
|
184
|
+
if ($scope.panel.auto_int) {
|
185
|
+
$scope.panel.interval = kbn.secondsToHms(
|
186
|
+
kbn.calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000);
|
187
|
+
}
|
188
|
+
|
189
|
+
$scope.panelMeta.loading = true;
|
190
|
+
var request = $scope.ejs.Request().indices(dashboard.indices[segment]);
|
191
|
+
|
192
|
+
$scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
|
193
|
+
// Build the query
|
194
|
+
_.each($scope.panel.queries.ids, function(id) {
|
195
|
+
var query = $scope.ejs.FilteredQuery(
|
196
|
+
querySrv.getEjsObj(id),
|
197
|
+
filterSrv.getBoolFilter(filterSrv.ids)
|
198
|
+
);
|
199
|
+
|
200
|
+
var facet = $scope.ejs.DateHistogramFacet(id);
|
201
|
+
|
202
|
+
if($scope.panel.mode === 'count') {
|
203
|
+
facet = facet.field($scope.panel.time_field);
|
204
|
+
} else {
|
205
|
+
if(_.isNull($scope.panel.value_field)) {
|
206
|
+
$scope.panel.error = "In " + $scope.panel.mode + " mode a field must be specified";
|
207
|
+
return;
|
208
|
+
}
|
209
|
+
facet = facet.keyField($scope.panel.time_field).valueField($scope.panel.value_field);
|
210
|
+
}
|
211
|
+
facet = facet.interval(_interval).facetFilter($scope.ejs.QueryFilter(query));
|
212
|
+
request = request.facet(facet).size(0);
|
213
|
+
});
|
214
|
+
|
215
|
+
// Populate the inspector panel
|
216
|
+
$scope.populate_modal(request);
|
217
|
+
|
218
|
+
// Then run it
|
219
|
+
var results = request.doSearch();
|
220
|
+
|
221
|
+
// Populate scope when we have results
|
222
|
+
results.then(function(results) {
|
223
|
+
$scope.panelMeta.loading = false;
|
224
|
+
if(segment === 0) {
|
225
|
+
$scope.hits = 0;
|
226
|
+
$scope.data = [];
|
227
|
+
query_id = $scope.query_id = new Date().getTime();
|
228
|
+
}
|
229
|
+
|
230
|
+
// Check for error and abort if found
|
231
|
+
if(!(_.isUndefined(results.error))) {
|
232
|
+
$scope.panel.error = $scope.parse_error(results.error);
|
233
|
+
return;
|
234
|
+
}
|
235
|
+
|
236
|
+
// Convert facet ids to numbers
|
237
|
+
var facetIds = _.map(_.keys(results.facets),function(k){return parseInt(k, 10);});
|
238
|
+
|
239
|
+
// Make sure we're still on the same query/queries
|
240
|
+
if($scope.query_id === query_id && _.difference(facetIds, $scope.panel.queries.ids).length === 0) {
|
241
|
+
|
242
|
+
var i = 0,
|
243
|
+
time_series,
|
244
|
+
hits;
|
245
|
+
|
246
|
+
_.each($scope.panel.queries.ids, function(id) {
|
247
|
+
var query_results = results.facets[id];
|
248
|
+
// we need to initialize the data variable on the first run,
|
249
|
+
// and when we are working on the first segment of the data.
|
250
|
+
if(_.isUndefined($scope.data[i]) || segment === 0) {
|
251
|
+
time_series = new timeSeries.ZeroFilled({
|
252
|
+
interval: _interval,
|
253
|
+
start_date: _range && _range.from,
|
254
|
+
end_date: _range && _range.to,
|
255
|
+
fill_style: 'minimal'
|
256
|
+
});
|
257
|
+
hits = 0;
|
258
|
+
} else {
|
259
|
+
time_series = $scope.data[i].time_series;
|
260
|
+
hits = $scope.data[i].hits;
|
261
|
+
}
|
262
|
+
|
263
|
+
// push each entry into the time series, while incrementing counters
|
264
|
+
_.each(query_results.entries, function(entry) {
|
265
|
+
time_series.addValue(entry.time, entry[$scope.panel.mode]);
|
266
|
+
hits += entry.count; // The series level hits counter
|
267
|
+
$scope.hits += entry.count; // Entire dataset level hits counter
|
268
|
+
});
|
269
|
+
$scope.data[i] = {
|
270
|
+
info: querySrv.list[id],
|
271
|
+
time_series: time_series,
|
272
|
+
hits: hits
|
273
|
+
};
|
274
|
+
|
275
|
+
i++;
|
276
|
+
});
|
277
|
+
|
278
|
+
// Tell the histogram directive to render.
|
279
|
+
$scope.$emit('render');
|
280
|
+
|
281
|
+
// If we still have segments left, get them
|
282
|
+
if(segment < dashboard.indices.length-1) {
|
283
|
+
$scope.get_data(segment+1,query_id);
|
284
|
+
}
|
285
|
+
}
|
286
|
+
});
|
287
|
+
};
|
288
|
+
|
289
|
+
// function $scope.zoom
|
290
|
+
// factor :: Zoom factor, so 0.5 = cuts timespan in half, 2 doubles timespan
|
291
|
+
$scope.zoom = function(factor) {
|
292
|
+
var _range = filterSrv.timeRange('min');
|
293
|
+
var _timespan = (_range.to.valueOf() - _range.from.valueOf());
|
294
|
+
var _center = _range.to.valueOf() - _timespan/2;
|
295
|
+
|
296
|
+
var _to = (_center + (_timespan*factor)/2);
|
297
|
+
var _from = (_center - (_timespan*factor)/2);
|
298
|
+
|
299
|
+
// If we're not already looking into the future, don't.
|
300
|
+
if(_to > Date.now() && _range.to < Date.now()) {
|
301
|
+
var _offset = _to - Date.now();
|
302
|
+
_from = _from - _offset;
|
303
|
+
_to = Date.now();
|
304
|
+
}
|
305
|
+
|
306
|
+
if(factor > 1) {
|
307
|
+
filterSrv.removeByType('time');
|
308
|
+
}
|
309
|
+
filterSrv.set({
|
310
|
+
type:'time',
|
311
|
+
from:moment.utc(_from),
|
312
|
+
to:moment.utc(_to),
|
313
|
+
field:$scope.panel.time_field
|
314
|
+
});
|
315
|
+
|
316
|
+
dashboard.refresh();
|
317
|
+
|
318
|
+
};
|
319
|
+
|
320
|
+
// I really don't like this function, too much dom manip. Break out into directive?
|
321
|
+
$scope.populate_modal = function(request) {
|
322
|
+
$scope.inspector = angular.toJson(JSON.parse(request.toString()),true);
|
323
|
+
};
|
324
|
+
|
325
|
+
$scope.set_refresh = function (state) {
|
326
|
+
$scope.refresh = state;
|
327
|
+
};
|
328
|
+
|
329
|
+
$scope.close_edit = function() {
|
330
|
+
if($scope.refresh) {
|
331
|
+
$scope.get_data();
|
332
|
+
}
|
333
|
+
$scope.refresh = false;
|
334
|
+
$scope.$emit('render');
|
335
|
+
};
|
336
|
+
|
337
|
+
$scope.render = function() {
|
338
|
+
$scope.$emit('render');
|
339
|
+
};
|
340
|
+
|
341
|
+
});
|
342
|
+
|
343
|
+
module.directive('histogramChart', function(dashboard, filterSrv) {
|
344
|
+
return {
|
345
|
+
restrict: 'A',
|
346
|
+
template: '<div></div>',
|
347
|
+
link: function(scope, elem) {
|
348
|
+
|
349
|
+
// Receive render events
|
350
|
+
scope.$on('render',function(){
|
351
|
+
render_panel();
|
352
|
+
});
|
353
|
+
|
354
|
+
// Re-render if the window is resized
|
355
|
+
angular.element(window).bind('resize', function(){
|
356
|
+
render_panel();
|
357
|
+
});
|
358
|
+
|
359
|
+
// Function for rendering panel
|
360
|
+
function render_panel() {
|
361
|
+
// IE doesn't work without this
|
362
|
+
elem.css({height:scope.panel.height || scope.row.height});
|
363
|
+
|
364
|
+
// Populate from the query service
|
365
|
+
try {
|
366
|
+
_.each(scope.data, function(series) {
|
367
|
+
series.label = series.info.alias;
|
368
|
+
series.color = series.info.color;
|
369
|
+
});
|
370
|
+
} catch(e) {return;}
|
371
|
+
|
372
|
+
// Set barwidth based on specified interval
|
373
|
+
var barwidth = kbn.interval_to_ms(scope.panel.interval);
|
374
|
+
|
375
|
+
var stack = scope.panel.stack ? true : null;
|
376
|
+
|
377
|
+
// Populate element
|
378
|
+
try {
|
379
|
+
var options = {
|
380
|
+
legend: { show: false },
|
381
|
+
series: {
|
382
|
+
stackpercent: scope.panel.stack ? scope.panel.percentage : false,
|
383
|
+
stack: scope.panel.percentage ? null : stack,
|
384
|
+
lines: {
|
385
|
+
show: scope.panel.lines,
|
386
|
+
// Silly, but fixes bug in stacked percentages
|
387
|
+
fill: scope.panel.fill === 0 ? 0.001 : scope.panel.fill/10,
|
388
|
+
lineWidth: scope.panel.linewidth,
|
389
|
+
steps: false
|
390
|
+
},
|
391
|
+
bars: {
|
392
|
+
show: scope.panel.bars,
|
393
|
+
fill: 1,
|
394
|
+
barWidth: barwidth/1.8,
|
395
|
+
zero: false,
|
396
|
+
lineWidth: 0
|
397
|
+
},
|
398
|
+
points: {
|
399
|
+
show: scope.panel.points,
|
400
|
+
fill: 1,
|
401
|
+
fillColor: false,
|
402
|
+
radius: 5
|
403
|
+
},
|
404
|
+
shadowSize: 1
|
405
|
+
},
|
406
|
+
yaxis: {
|
407
|
+
show: scope.panel['y-axis'],
|
408
|
+
min: 0,
|
409
|
+
max: scope.panel.percentage && scope.panel.stack ? 100 : null,
|
410
|
+
},
|
411
|
+
xaxis: {
|
412
|
+
timezone: scope.panel.timezone,
|
413
|
+
show: scope.panel['x-axis'],
|
414
|
+
mode: "time",
|
415
|
+
min: _.isUndefined(scope.range.from) ? null : scope.range.from.getTime(),
|
416
|
+
max: _.isUndefined(scope.range.to) ? null : scope.range.to.getTime(),
|
417
|
+
timeformat: time_format(scope.panel.interval),
|
418
|
+
label: "Datetime",
|
419
|
+
},
|
420
|
+
grid: {
|
421
|
+
backgroundColor: null,
|
422
|
+
borderWidth: 0,
|
423
|
+
hoverable: true,
|
424
|
+
color: '#c8c8c8'
|
425
|
+
}
|
426
|
+
};
|
427
|
+
|
428
|
+
if(scope.panel.interactive) {
|
429
|
+
options.selection = { mode: "x", color: '#666' };
|
430
|
+
}
|
431
|
+
|
432
|
+
// when rendering stacked bars, we need to ensure each point that has data is zero-filled
|
433
|
+
// so that the stacking happens in the proper order
|
434
|
+
var required_times = [];
|
435
|
+
if (scope.data.length > 1) {
|
436
|
+
required_times = Array.prototype.concat.apply([], _.map(scope.data, function (query) {
|
437
|
+
return query.time_series.getOrderedTimes();
|
438
|
+
}));
|
439
|
+
required_times = _.uniq(required_times.sort(function (a, b) {
|
440
|
+
// decending numeric sort
|
441
|
+
return a-b;
|
442
|
+
}), true);
|
443
|
+
}
|
444
|
+
|
445
|
+
for (var i = 0; i < scope.data.length; i++) {
|
446
|
+
scope.data[i].data = scope.data[i].time_series.getFlotPairs(required_times);
|
447
|
+
}
|
448
|
+
|
449
|
+
scope.plot = $.plot(elem, scope.data, options);
|
450
|
+
|
451
|
+
} catch(e) {
|
452
|
+
console.log(e);
|
453
|
+
}
|
454
|
+
}
|
455
|
+
|
456
|
+
function time_format(interval) {
|
457
|
+
var _int = kbn.interval_to_seconds(interval);
|
458
|
+
if(_int >= 2628000) {
|
459
|
+
return "%m/%y";
|
460
|
+
}
|
461
|
+
if(_int >= 86400) {
|
462
|
+
return "%m/%d/%y";
|
463
|
+
}
|
464
|
+
if(_int >= 60) {
|
465
|
+
return "%H:%M<br>%m/%d";
|
466
|
+
}
|
467
|
+
|
468
|
+
return "%H:%M:%S";
|
469
|
+
}
|
470
|
+
|
471
|
+
var $tooltip = $('<div>');
|
472
|
+
elem.bind("plothover", function (event, pos, item) {
|
473
|
+
var group, value;
|
474
|
+
if (item) {
|
475
|
+
if (item.series.info.alias || scope.panel.tooltip.query_as_alias) {
|
476
|
+
group = '<small style="font-size:0.9em;">' +
|
477
|
+
'<i class="icon-circle" style="color:'+item.series.color+';"></i>' + ' ' +
|
478
|
+
(item.series.info.alias || item.series.info.query)+
|
479
|
+
'</small><br>';
|
480
|
+
} else {
|
481
|
+
group = kbn.query_color_dot(item.series.color, 15) + ' ';
|
482
|
+
}
|
483
|
+
if (scope.panel.stack && scope.panel.tooltip.value_type === 'individual') {
|
484
|
+
value = item.datapoint[1] - item.datapoint[2];
|
485
|
+
} else {
|
486
|
+
value = item.datapoint[1];
|
487
|
+
}
|
488
|
+
$tooltip
|
489
|
+
.html(
|
490
|
+
group + value + " @ " + moment(item.datapoint[0]).format('MM/DD HH:mm:ss')
|
491
|
+
)
|
492
|
+
.place_tt(pos.pageX, pos.pageY);
|
493
|
+
} else {
|
494
|
+
$tooltip.detach();
|
495
|
+
}
|
496
|
+
});
|
497
|
+
|
498
|
+
elem.bind("plotselected", function (event, ranges) {
|
499
|
+
filterSrv.set({
|
500
|
+
type : 'time',
|
501
|
+
from : moment.utc(ranges.xaxis.from),
|
502
|
+
to : moment.utc(ranges.xaxis.to),
|
503
|
+
field : scope.panel.time_field
|
504
|
+
});
|
505
|
+
dashboard.refresh();
|
506
|
+
});
|
507
|
+
}
|
508
|
+
};
|
509
|
+
});
|
510
|
+
|
511
|
+
});
|