Commit 9d2ce987 by Torkel Odegaard

removed histogram panel

parent 26c115f2
......@@ -2,4 +2,5 @@ node_modules
.aws-config.json
dist
web.config
config.dev.js
\ No newline at end of file
config.dev.js
*.sublime-workspace
\ No newline at end of file
{
"auto_complete":
{
"selected_items":
[
[
"grap",
"graphiteSrv"
],
[
"pul",
"pulldown"
],
[
"pull",
"pulldowns"
],
[
"ser",
"seriesInfo"
],
[
"max",
"maxDataPoints"
],
[
"gra",
"graphiteParameters"
],
[
"build",
"build_graphite_url"
],
[
"cookie",
"cookieUtil"
],
[
"re",
"requesition"
],
[
"req",
"requesition"
],
[
"res",
"requesition"
],
[
"serve",
"serverStatus"
],
[
"fet",
"fetchServerStatus"
],
[
"conn",
"connectToMongoDb"
],
[
"mongo",
"mongoDbUrl"
],
[
"fetc",
"fetchDataForInstance"
]
]
},
"buffers":
[
{
"file": "src/app/components/require.config.js",
"settings":
{
"buffer_size": 3549,
"line_ending": "Windows"
}
},
{
"file": "src/config.dev.js",
"settings":
{
"buffer_size": 1492,
"line_ending": "Windows"
}
},
{
"contents": "Searching 228 files for \"pulldowns\"\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\default.json:\n 73 \"failover\": false,\n 74 \"panel_hints\": true,\n 75: \"pulldowns\": [],\n 76 \"nav\": [\n 77 {\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\guided.json:\n 221 \"hide\": false\n 222 },\n 223: \"pulldowns\": [\n 224 {\n 225 \"type\": \"query\",\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\logstash.json:\n 160 \"style\": \"dark\",\n 161 \"panel_hints\": true,\n 162: \"pulldowns\": [\n 163 {\n 164 \"type\": \"query\",\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\noted.json:\n 110 \"hide\": false\n 111 },\n 112: \"pulldowns\": [\n 113 {\n 114 \"type\": \"query\",\n\nC:\\Dev\\oss\\grafana\\src\\app\\partials\\dashboard.html:\n 1 <!-- is there a better way to repeat without actually affecting the page? -->\n 2: <nil ng-repeat=\"pulldown in dashboard.current.pulldowns\" ng-controller=\"PulldownCtrl\" ng-show=\"pulldown.enable\">\n 3 <div class=\"top-row-open\" ng-hide=\"pulldown.collapse\">\n 4 <kibana-simple-panel type=\"pulldown.type\" ng-cloak></kibana-simple-panel>\n\nC:\\Dev\\oss\\grafana\\src\\app\\partials\\dasheditor.html:\n 114 <div class=\"editor-row\">\n 115 <div class=\"section\">\n 116: <h5>Pulldowns</h5>\n 117: <div class=\"editor-option\" ng-repeat=\"pulldown in dashboard.current.pulldowns\">\n 118 <label class=\"small\" style=\"text-transform:capitalize;\">{{pulldown.type}}</label><input type=\"checkbox\" ng-model=\"pulldown.enable\" ng-checked=\"pulldown.enable\">\n 119 </div>\n\nC:\\Dev\\oss\\grafana\\src\\app\\services\\dashboard.js:\n 27 panel_hints: true,\n 28 rows: [],\n 29: pulldowns: [\n 30 {\n 31 type: 'query',\n ..\n 176 // Set the available panels for the \"Add Panel\" drop down\n 177 self.availablePanels = _.difference(config.panel_names,\n 178: _.pluck(_.union(self.current.nav,self.current.pulldowns),'type'));\n 179 \n 180 // Take out any that we're not allowed to add from the gui.\n\n9 matches across 7 files\n\n\nSearching 226 files for \"'filter'\"\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\filtering\\module.js:\n 27 _.defaults($scope.panel,_d);\n 28 \n 29: $scope.$on('filter', function() {\n 30 $scope.row.notice = true;\n 31 });\n\nC:\\Dev\\oss\\grafana\\src\\app\\services\\filterSrv.js:\n 89 },0);\n 90 }\n 91: $rootScope.$broadcast('filter');\n 92 return _r;\n 93 };\n ..\n 111 },0);\n 112 }\n 113: $rootScope.$broadcast('filter');\n 114 return _r;\n 115 };\n\nC:\\Dev\\oss\\grafana\\src\\vendor\\underscore.js:\n 241 _.where = function(obj, attrs, first) {\n 242 if (_.isEmpty(attrs)) return first ? void 0 : [];\n 243: return _[first ? 'find' : 'filter'](obj, function(value) {\n 244 for (var key in attrs) {\n 245 if (attrs[key] !== value[key]) return false;\n\nC:\\Dev\\oss\\grafana\\src\\vendor\\angular\\angular.js:\n 10727 $FilterProvider.$inject = ['$provide'];\n 10728 function $FilterProvider($provide) {\n 10729: var suffix = 'Filter';\n 10730 \n 10731 function register(name, factory) {\n .....\n 10744 register('currency', currencyFilter);\n 10745 register('date', dateFilter);\n 10746: register('filter', filterFilter);\n 10747 register('json', jsonFilter);\n 10748 register('limitTo', limitToFilter);\n\nC:\\Dev\\oss\\grafana\\src\\vendor\\elasticjs\\elastic.js:\n 237 \n 238 isFilter = function (obj) {\n 239: return (isEJSObject(obj) && obj._type() === 'filter');\n 240 };\n 241 \n ...\n 3550 */\n 3551 _type: function () {\n 3552: return 'filter';\n 3553 },\n 3554 \n ....\n 3777 */\n 3778 _type: function () {\n 3779: return 'filter';\n 3780 },\n 3781 \n ....\n 3870 */\n 3871 _type: function () {\n 3872: return 'filter';\n 3873 },\n 3874 \n ....\n 4084 */\n 4085 _type: function () {\n 4086: return 'filter';\n 4087 },\n 4088 \n ....\n 4345 */\n 4346 _type: function () {\n 4347: return 'filter';\n 4348 },\n 4349 \n ....\n 4739 */\n 4740 _type: function () {\n 4741: return 'filter';\n 4742 },\n 4743 \n ....\n 4926 */\n 4927 _type: function () {\n 4928: return 'filter';\n 4929 },\n 4930 \n ....\n 5156 */\n 5157 _type: function () {\n 5158: return 'filter';\n 5159 },\n 5160 \n ....\n 5356 */\n 5357 _type: function () {\n 5358: return 'filter';\n 5359 },\n 5360 \n ....\n 5540 */\n 5541 _type: function () {\n 5542: return 'filter';\n 5543 },\n 5544 \n ....\n 5678 */\n 5679 _type: function () {\n 5680: return 'filter';\n 5681 },\n 5682 \n ....\n 5828 */\n 5829 _type: function () {\n 5830: return 'filter';\n 5831 },\n 5832 \n ....\n 5907 */\n 5908 _type: function () {\n 5909: return 'filter';\n 5910 },\n 5911 \n ....\n 5963 */\n 5964 _type: function () {\n 5965: return 'filter';\n 5966 },\n 5967 \n ....\n 6086 */\n 6087 _type: function () {\n 6088: return 'filter';\n 6089 },\n 6090 \n ....\n 6300 */\n 6301 _type: function () {\n 6302: return 'filter';\n 6303 },\n 6304 \n ....\n 6431 */\n 6432 _type: function () {\n 6433: return 'filter';\n 6434 },\n 6435 \n ....\n 6728 */\n 6729 _type: function () {\n 6730: return 'filter';\n 6731 },\n 6732 \n ....\n 6885 */\n 6886 _type: function () {\n 6887: return 'filter';\n 6888 },\n 6889 \n ....\n 7032 */\n 7033 _type: function () {\n 7034: return 'filter';\n 7035 },\n 7036 \n ....\n 7170 */\n 7171 _type: function () {\n 7172: return 'filter';\n 7173 },\n 7174 \n ....\n 7431 */\n 7432 _type: function () {\n 7433: return 'filter';\n 7434 },\n 7435 \n ....\n 7625 */\n 7626 _type: function () {\n 7627: return 'filter';\n 7628 },\n 7629 \n ....\n 7782 */\n 7783 _type: function () {\n 7784: return 'filter';\n 7785 },\n 7786 \n ....\n 7934 */\n 7935 _type: function () {\n 7936: return 'filter';\n 7937 },\n 7938 \n ....\n 8243 */\n 8244 _type: function () {\n 8245: return 'filter';\n 8246 },\n 8247 \n ....\n 8319 */\n 8320 _type: function () {\n 8321: return 'filter';\n 8322 },\n 8323 \n ....\n 10104 @param {Object} qry A valid query object.\n 10105 @param {Object || Array} filters A single object or array of objects. Each\n 10106: object must have a 'filter' property and either a 'boost' or 'script'\n 10107 property.\n 10108 */\n .....\n 10180 <p>Sets the filters and their related boost or script scoring method.</p>\n 10181 \n 10182: <p>Takes an array of objects where each object has a 'filter' property\n 10183 and either a 'boost' or 'script' property. Pass a single object to\n 10184 add to the current list of filters or pass a list of objects to\n\n36 matches across 5 files\n\n\nSearching 227 files for \"timeField\"\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\default.json:\n 103 \"1d\"\n 104 ],\n 105: \"timefield\": \"@timestamp\",\n 106 \"enable\": true,\n 107 \"now\": true,\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\guided.json:\n 266 \"1d\"\n 267 ],\n 268: \"timefield\": \"@timestamp\"\n 269 }\n 270 ],\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\logstash.js:\n 14 *\n 15 * from :: Search this amount of time back, eg 15m, 1h, 2d. Default: 15m\n 16: * timefield :: The field containing the time to filter on, Default: @timestamp\n 17 *\n 18 * fields :: comma seperated list of fields to show in the table\n ..\n 91 from: \"now-\"+(ARGS.from||_d_timespan),\n 92 to: \"now\",\n 93: field: ARGS.timefield||\"@timestamp\",\n 94 type: \"time\",\n 95 active: true,\n ..\n 117 title: 'events over time',\n 118 type: 'histogram',\n 119: time_field: ARGS.timefield||\"@timestamp\",\n 120 auto_int: true,\n 121 span: 12\n ...\n 129 type: 'table',\n 130 fields: !_.isUndefined(ARGS.fields) ? ARGS.fields.split(',') : [],\n 131: sort: !_.isUndefined(ARGS.sort) ? ARGS.sort.split(',') : [ARGS.timefield||'@timestamp','desc'],\n 132 overflow: 'expand',\n 133 span: 12\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\logstash.json:\n 130 \"fields\": [],\n 131 \"localTime\": true,\n 132: \"timeField\": \"@timestamp\",\n 133 \"highlight\": [],\n 134 \"sortable\": true,\n ...\n 205 \"1d\"\n 206 ],\n 207: \"timefield\": \"@timestamp\",\n 208 \"now\": true,\n 209 \"filter_id\": 0\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\noted.json:\n 155 \"1d\"\n 156 ],\n 157: \"timefield\": \"@timestamp\"\n 158 }\n 159 ],\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\timepicker\\editor.html:\n 10 <div class=\"span2\">\n 11 <label class=\"small\">Time Field</label>\n 12: <input type=\"text\" class=\"input-small\" ng-model=\"panel.timefield\">\n 13 </div>\n 14 </div>\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\timepicker\\module.js:\n 7 * time_options :: An array of possible time options. Default: ['5m','15m','1h','6h','12h','24h','2d','7d','30d']\n 8 * timespan :: The default options selected for the relative view. Default: '15m'\n 9: * timefield :: The field in which time is stored in the document.\n 10 * refresh: Object containing refresh parameters\n 11 * enable :: true/false, enable auto refresh by default. Default: false\n ..\n 40 refresh_intervals : ['5s','10s','30s','1m','5m','15m','30m','1h','2h','1d'],\n 41 \n 42: timefield : '@timestamp'\n 43 };\n 44 _.defaults($scope.panel,_d);\n ..\n 130 \n 131 _filter.type = 'time';\n 132: _filter.field = $scope.panel.timefield;\n 133 \n 134 if($scope.panel.now) {\n ...\n 154 var _filter = {\n 155 type : 'time',\n 156: field : $scope.panel.timefield,\n 157 from : \"now-\"+timespan,\n 158 to: \"now\"\n\nC:\\Dev\\oss\\grafana\\src\\app\\services\\filterSrv.js:\n 202 \n 203 // TOFIX: Error handling when there is more than one field\n 204: this.timeField = function() {\n 205 return _.pluck(self.getByType('time'),'field');\n 206 };\n\nC:\\Users\\Torkel\\Downloads\\Grafana3-1388335099517:\n 397 \"1d\"\n 398 ],\n 399: \"timefield\": \"@timestamp\",\n 400 \"enable\": true,\n 401 \"now\": false,\n\n16 matches across 9 files\n\n\nSearching 226 files for \"bs-drop\"\n\n0 matches across 0 files\n\n\nSearching 226 files for \"bsdropd\"\n\nC:\\Dev\\oss\\grafana\\src\\vendor\\angular\\angular-strap.js:\n 380 ]);\n 381 'use strict';\n 382: angular.module('$strap.directives').directive('bsDropdown', [\n 383 '$parse',\n 384 '$compile',\n ...\n 406 scope: true,\n 407 link: function postLink(scope, iElement, iAttrs) {\n 408: var getter = $parse(iAttrs.bsDropdown), items = getter(scope);\n 409 $timeout(function () {\n 410 if (!angular.isArray(items)) {\n\n2 matches in 1 file\n\n\nSearching 226 files for \"'mandate'\"\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\filtering\\module.js:\n 63 \n 64 $scope.show_key = function(key) {\n 65: return !_.contains(['type','id','alias','mandate','active','editing'],key);\n 66 };\n 67 \n\n1 match in 1 file\n\n\nSearching 226 files for \"mandate\"\n\nC:\\Dev\\oss\\grafana\\grafana.sublime-workspace:\n 239 \"D:\\\\Temp\\\\graphite-web-0.9.12\\\\graphite-web-0.9.12\",\n 240 \"\",\n 241: \" \\\"filter\\\": {\\n \\\"list\\\": {\\n \\\"0\\\": {\\n \\\"type\\\": \\\"time\\\",\\n \\\"field\\\": \\\"@timestamp\\\",\\n \\\"from\\\": \\\"now-1h\\\",\\n \\\"to\\\": \\\"now\\\",\\n \\\"mandate\\\": \\\"must\\\",\\n \\\"active\\\": true,\\n \\\"alias\\\": \\\"\\\",\\n \\\"id\\\": 0\\n }\\n },\\n \\\"ids\\\": [\\n 0\\n ]\\n\",\n 242: \" \\\"filter\\\": {\\n \\\"list\\\": {\\n \\\"0\\\": {\\n \\\"type\\\": \\\"time\\\",\\n \\\"field\\\": \\\"@timestamp\\\",\\n \\\"from\\\": \\\"now-1h\\\",\\n \\\"to\\\": \\\"now\\\",\\n \\\"mandate\\\": \\\"must\\\",\\n \\\"active\\\": true,\\n \\\"alias\\\": \\\"\\\",\\n \\\"id\\\": 0\\n }\\n },\\n \\\"ids\\\": [\\n 0\\n ]\\n \",\n 243 \"D:\\\\oss\\\\mongodb-metrics\\\\node_modules\\\\mongodb\",\n 244 \"D:\\\\ebay\\\\tradera\\\\Applications\\\\TouchWeb\",\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\default.json:\n 24 \"from\": \"now-1h\",\n 25 \"to\": \"now\",\n 26: \"mandate\": \"must\",\n 27 \"active\": true,\n 28 \"alias\": \"\",\n\nC:\\Dev\\oss\\grafana\\src\\app\\dashboards\\logstash.json:\n 24 \"from\": \"now-{{ARGS.from || '24h'}}\",\n 25 \"to\": \"now\",\n 26: \"mandate\": \"must\",\n 27 \"active\": true,\n 28 \"alias\": \"\",\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\filtering\\module.html:\n 34 margin-left: 3px;\n 35 }\n 36: .filter-mandate {\n 37 text-decoration: underline;\n 38 cursor: pointer;\n ..\n 48 <h5>No filters available</h5>\n 49 </span>\n 50: <div ng-repeat=\"id in filterSrv.ids\" class=\"small filter-panel-filter filter-{{filterSrv.list[id].mandate}}\" ng-class=\"{'filter-deselected': !filterSrv.list[id].active}\">\n 51 <div>\n 52 <i class=\"filter-action pointer icon-remove\" bs-tooltip=\"'Remove'\" ng-click=\"remove(id)\"></i>\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\filtering\\module.js:\n 63 \n 64 $scope.show_key = function(key) {\n 65: return !_.contains(['type','id','alias','mandate','active','editing'],key);\n 66 };\n 67 \n\nC:\\Dev\\oss\\grafana\\src\\app\\services\\filterSrv.js:\n 54 \n 55 _.defaults(filter,{\n 56: mandate:'must',\n 57 active: true\n 58 });\n ..\n 80 alias: '',\n 81 id: _id,\n 82: mandate: 'must'\n 83 };\n 84 _.defaults(filter,_filter);\n ..\n 144 added_a_filter = true;\n 145 \n 146: switch(self.list[id].mandate)\n 147 {\n 148 case 'mustNot':\n\n10 matches across 6 files\n\n\nSearching 226 files for \"bs-dropdown\"\n\nC:\\Dev\\oss\\grafana\\src\\app\\panels\\filtering\\module.html:\n 59 <li ng-if=\"filterSrv.list[id].name\">\n 60 {{filterSrv.list[id].name}} :\n 61: <a bs-dropdown=\"[{text: 'testing'}]\">All</a>\n 62 </li>\n 63 <li ng-repeat=\"(key,value) in filterSrv.list[id] track by $index\" ng-show=\"show_key(key)\">\n\n1 match in 1 file\n\n\nSearching 226 files for \"bspop\"\n\nC:\\Dev\\oss\\grafana\\src\\vendor\\angular\\angular-strap.js:\n 536 ]);\n 537 'use strict';\n 538: angular.module('$strap.directives').directive('bsPopover', [\n 539 '$parse',\n 540 '$compile',\n ...\n 556 scope: true,\n 557 link: function postLink(scope, element, attr, ctrl) {\n 558: var getter = $parse(attr.bsPopover), setter = getter.assign, value = getter(scope), options = {};\n 559 if (angular.isObject(value)) {\n 560 options = value;\n\n2 matches in 1 file\n",
"settings":
{
"buffer_size": 15575,
"line_ending": "Windows",
"name": "Find Results",
"scratch": true
}
},
{
"file": "src/vendor/angular/angular-strap.js",
"settings":
{
"buffer_size": 31514,
"line_ending": "Windows"
}
},
{
"file": "src/app/panels/timepicker/module.js",
"settings":
{
"buffer_size": 6147,
"line_ending": "Windows"
}
},
{
"file": "src/app/dashboards/guided.json",
"settings":
{
"buffer_size": 6721,
"line_ending": "Windows"
}
},
{
"file": "src/app/panels/filtering/module.html",
"settings":
{
"buffer_size": 2866,
"line_ending": "Windows"
}
},
{
"file": "src/app/panels/filtering/module.js",
"settings":
{
"buffer_size": 2288,
"line_ending": "Windows"
}
},
{
"file": "src/app/panels/graphite/module.js",
"settings":
{
"buffer_size": 23005,
"line_ending": "Windows"
}
},
{
"file": "src/app/services/filterSrv.js",
"settings":
{
"buffer_size": 6631,
"line_ending": "Windows"
}
},
{
"file": "src/app/services/graphite/graphiteSrv.js",
"settings":
{
"buffer_size": 2343,
"line_ending": "Windows"
}
},
{
"file": "src/app/controllers/graphiteTarget.js",
"settings":
{
"buffer_size": 6702,
"line_ending": "Windows"
}
}
],
"build_system": "",
"command_palette":
{
"height": 362.0,
"selected_items":
[
[
"install",
"Package Control: Install Package"
],
[
"syn ava",
"Set Syntax: JavaScript"
],
[
"Install ",
"Package Control: Install Package"
],
[
"powers",
"SublimeREPL: PowerShell"
],
[
"install ",
"Package Control: Install Package"
],
[
"Install",
"Package Control: Install Package"
],
[
"remove ",
"Package Control: Remove Package"
],
[
"Package Control: ",
"Package Control: List Packages"
],
[
"insta",
"Package Control: Install Package"
],
[
"packa",
"Package Control: Install Package"
],
[
"packa ",
"Package Control: Install Package"
],
[
"Pack",
"Package Control: Remove Package"
]
],
"width": 594.0
},
"console":
{
"height": 368.0,
"history":
[
"import urllib.request,os; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())"
]
},
"distraction_free":
{
"menu_visible": true,
"show_minimap": false,
"show_open_files": false,
"show_tabs": false,
"side_bar_visible": false,
"status_bar_visible": false
},
"file_history":
[
"/C/Dev/oss/grafana/src/app/services/filterSrv.js",
"/C/Dev/oss/grafana/src/app/panels/filtering/module.js",
"/C/Dev/oss/grafana/src/app/services/dashboard.js",
"/C/Users/Torkel/Downloads/Grafana3-1388335099517",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.prod_manage.json",
"/C/Dev/oss/grafana/src/app/components/settings.js",
"/C/Dev/oss/grafana/src/app/controllers/zoom.js",
"/C/Dev/oss/grafana/src/app/panels/graphite/module.js",
"/C/Dev/oss/grafana/src/app/panels/graphite/module.html",
"/C/Dev/oss/grafana/src/app/directives/kibanaPanel.js",
"/C/Dev/oss/grafana/src/app/dashboards/default.json",
"/C/Dev/oss/grafana/src/app/panels/graphite/timeSeries.js",
"/C/Dev/oss/grafana/src/app/controllers/dash.js",
"/C/Dev/oss/grafana/src/app/partials/dashboard.html",
"/C/Dev/oss/grafana/src/app/panels/graphite/graphiteSrv.js",
"/C/Dev/oss/grafana/src/vendor/bootstrap/less/grafana.less",
"/C/Dev/oss/grafana/src/index.html",
"//team-city-agent-02/d$/BuildAgent/work/dfdaf9995bf5db32/build_artifacts/output/_PublishedApplications/WebApi/BrowseInitializer/App.config",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.prod_app_servers.json",
"/D/ebay/tradera/Build/Tasks-WebApi.ps1",
"/D/oss/grafana/src/config.dev.js",
"/D/oss/grafana/src/app/controllers/dash.js",
"/D/oss/grafana/src/app/partials/dashLoader.html",
"/D/oss/grafana/src/app/panels/histogram/module.html",
"/D/oss/grafana/src/app/controllers/all.js",
"/D/oss/grafana/src/app/controllers/zoom.js",
"/D/oss/grafana/src/app/panels/graphite/module.html",
"/D/oss/grafana/src/vendor/bootstrap/less/bootstrap.dark.less",
"/D/oss/grafana/src/app/panels/graphite/editor.html",
"/D/oss/grafana/src/app/directives/kibanaPanel.js",
"/D/oss/grafana/src/app/partials/dasheditor.html",
"/D/oss/grafana/src/app/partials/paneleditor.html",
"/D/oss/grafana/src/vendor/bootstrap/less/overrides.less",
"/D/oss/grafana/src/app/partials/dashboard.html",
"/D/oss/grafana/src/app/components/require.config.js",
"/D/oss/grafana/src/vendor/bootstrap/less/grafana.less",
"/D/oss/grafana/src/app/panels/graphite/module.js",
"/D/oss/grafana/src/app/panels/graphite/graphiteSrv.js",
"/D/oss/grafana/grafana.sublime-project",
"/D/ebay/tradera/Applications/TouchWeb/touchweb.sublime-project",
"//se1-appsrv-01.prod.tradera.com/d$/Applications/WebApi/MemberActivityDenormalizer/App.config",
"/D/Temp/graphite-web-0.9.12/graphite-web-0.9.12/webapp/graphite/render/views.py",
"/D/Temp/graphite-web-0.9.12/graphite-web-0.9.12/webapp/graphite/views.py",
"/D/ebay/tradera/DB/Main/5_sprocs/Listing/EbaySweden_Trading_Listing_GetItemForRestart.proc.sql",
"//dashboards/d$/Inetpub/GiraffeOps/dashboards.js",
"/D/oss/grafana/src/app/partials/inspector.html",
"/D/ebay/tradera/Applications/TouchWeb/src/EbaySweden.TouchWeb/static/script/app/ui/layout/google-tagmanager.js",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.json",
"/D/ebay/tradera/Applications/TouchWeb/src/EbaySweden.TouchWeb/static/script/utils/cookie.js",
"/D/ebay/tradera/Applications/TouchWeb/src/EbaySweden.TouchWeb/static/script/app/boot/boot-layout.js",
"/D/ebay/tradera/Applications/TouchWeb/build/js-and-css.ps1",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.prod_tradera_site.json",
"/D/ebay/tradera/Applications/TouchWeb/node_modules/grunt-contrib-uglify/package.json",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.test.json",
"/D/oss/mongodb-metrics/node_modules/mongodb/lib/mongodb/admin.js",
"/D/oss/mongodb-metrics/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js",
"/D/oss/mongodb-metrics/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js",
"/D/oss/mongodb-metrics/node_modules/mongodb/lib/mongodb/db.js",
"/D/oss/mongodb-metrics/node_modules/mongodb/lib/mongodb/commands/db_command.js",
"/D/ebay/tradera/Deployment/VerificationPackages/TraderaSite/run.js",
"/C/Users/todegaard/AppData/Roaming/Sublime Text 3/Packages/User/node_app_js.sublime-build",
"/D/ebay/tools/Tools/AppLogs2Elastic/Gruntfile.js",
"/D/oss/mongodb-metrics/gruntfile.js",
"/C/Users/todegaard/AppData/Roaming/Sublime Text 3/Packages/User/Preferences.sublime-settings",
"/D/oss/asimov-deploy-ui/Gruntfile.js",
"/D/ebay/tradera/Applications/TouchWeb/Gruntfile.js",
"/D/oss/mongodb-metrics/app.js",
"/D/oss/mongodb-metrics/tests/test.js",
"/C/Users/todegaard/AppData/Roaming/Sublime Text 3/Installed Packages/Tomorrow Color Schemes.sublime-package",
"/D/ebay/tradera/Build/EbaySweden-StartBuild.ps1",
"/D/ebay/tradera/Applications/TouchWeb/src/EbaySweden.TouchWeb/static/script/app.js",
"/D/ebay/tradera/Applications/TouchWeb/src/EbaySweden.TouchWeb/static/script/app/ui/view-item/bidding-ui.js",
"/D/ebay/tools/Tools/AppLogs2Elastic/App.config",
"//dashboards/d$/Inetpub/Kibana/config.js",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.prod_api.json",
"/D/ebay/asimov-tradera/WinAgent.ConfigFiles/config.prod_tradera_site_test.json",
"/C/Users/todegaard/AppData/Roaming/Sublime Text 3/Packages/User/Package Control.sublime-settings"
],
"find":
{
"height": 60.0
},
"find_in_files":
{
"height": 104.0,
"where_history":
[
"",
"D:\\Temp\\graphite-web-0.9.12\\graphite-web-0.9.12",
"",
" \"filter\": {\n \"list\": {\n \"0\": {\n \"type\": \"time\",\n \"field\": \"@timestamp\",\n \"from\": \"now-1h\",\n \"to\": \"now\",\n \"mandate\": \"must\",\n \"active\": true,\n \"alias\": \"\",\n \"id\": 0\n }\n },\n \"ids\": [\n 0\n ]\n",
" \"filter\": {\n \"list\": {\n \"0\": {\n \"type\": \"time\",\n \"field\": \"@timestamp\",\n \"from\": \"now-1h\",\n \"to\": \"now\",\n \"mandate\": \"must\",\n \"active\": true,\n \"alias\": \"\",\n \"id\": 0\n }\n },\n \"ids\": [\n 0\n ]\n ",
"D:\\oss\\mongodb-metrics\\node_modules\\mongodb",
"D:\\ebay\\tradera\\Applications\\TouchWeb",
"D:\\ebay\\tradera"
]
},
"find_state":
{
"case_sensitive": false,
"find_history":
[
"bspop",
"bs-dropdown",
"alias",
"mandate",
"'mandate'",
"show_key",
"bsdropd",
"bs-drop",
"set ",
"zoom",
"timeField",
"timeF",
"timefi",
"@times",
"field",
"queries",
"editing",
"'filter'",
"load",
"pulldowns",
".input-mini",
"keyCode == 27",
"esc",
"elem",
"time_format",
"row.tit",
"'app/partials/roweditor.html'",
"== ",
"moment",
"dashboard.current.hideControls",
"ng-class='",
" ng-class='{",
"overrides.less",
"rootScope",
"bindonce",
"anel.targets = _.without(panel.targets, target)",
">\n",
"on(",
"refresh",
"get_D",
"maxDataPoints",
"colspan",
"width",
"calculate_interval\ncalculate_interval",
"resolution",
"width",
"resolution",
"calculate_interval",
"get_interval",
"graphite_options",
"maxDataPoints",
"kibanaSimplePanel",
"kibanaPanel",
"<kibanaPanel",
"$scope.panelMeta.loading",
"\"tab\"",
"\"timepicker\"",
"doSearch",
"doSearch = ",
".loading = false",
"$scope.apply",
"get_data",
"histogram",
"$scope.panelMeta.loading",
"$scope.panel.error",
"$scope.panel",
"panel.error",
"requests",
"graphiteUtil",
"populate_modal",
"get_data",
"inspect",
"partial",
"inspector",
"1h",
"graphiteFlot",
"2.4.5",
"spawn",
"connections: { cu",
"connections: { curren",
"mongoDbUrl",
"console.lo",
"createAdminDbCommandSlaveOk",
"DbCommand",
"createAdminDbCommand",
"executeDbAdminCommand",
"command",
"executeDbAdminCommand",
"primaryPreferered",
"_executeQueryCommand",
"executeDbA",
"executeDbAdminCommand",
"ReadPreference.PRIMARY_PREFERRED",
"PREFERRED",
"PRIMARY PREFERRED",
"No primary found in set",
"connectWithNoPrimary",
"No primary found in set",
"var",
"_redirectToCartCheckout",
"data:cart:after-checkout-started",
"_startCheckout",
"ui:cart:on-checkout-start",
"on-checkout-start",
"_goToCheckout",
"checkoutAction",
"data-view-cart-button",
"cdn",
"traderaSite",
"(\"#",
"traderaSite",
" ",
"${",
"\n",
"back-to-tradera",
"CreateDeferr",
"Deferr<",
".Deferr",
"IDeferredMessage",
"SendFeedbackRemovalMail",
"SendFeedbackRemovalMail'",
"SendFeedbackRemovalMail",
"Create_DSR",
"Update_DSR_Stats",
"Create_DSR",
"Create_Grade_DSR\nCreate_DSR",
"Create_Grade_DSR\nCreate_Grade_DSR",
"Create_Grade_DSR\nCreate_Grade_DSR\n"
],
"highlight": true,
"in_selection": false,
"preserve_case": false,
"regex": false,
"replace_history":
[
],
"reverse": false,
"show_context": true,
"use_buffer2": true,
"whole_word": false,
"wrap": true
},
"groups":
[
{
"selected": 3,
"sheets":
[
{
"buffer": 0,
"file": "src/app/components/require.config.js",
"semi_transient": false,
"settings":
{
"buffer_size": 3549,
"regions":
{
},
"selection":
[
[
0,
0
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 4,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 414.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 1,
"file": "src/config.dev.js",
"semi_transient": false,
"settings":
{
"buffer_size": 1492,
"regions":
{
},
"selection":
[
[
910,
910
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 302.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 2,
"semi_transient": false,
"settings":
{
"buffer_size": 15575,
"regions":
{
"match":
{
"flags": 112,
"regions":
[
[
157,
166
],
[
303,
312
],
[
480,
489
],
[
635,
644
],
[
883,
892
],
[
1243,
1252
],
[
1341,
1350
],
[
1672,
1681
],
[
1941,
1950
],
[
2232,
2240
],
[
2431,
2439
],
[
2557,
2565
],
[
2799,
2807
],
[
3097,
3105
],
[
3275,
3283
],
[
3539,
3547
],
[
3654,
3662
],
[
3772,
3780
],
[
3890,
3898
],
[
4008,
4016
],
[
4126,
4134
],
[
4244,
4252
],
[
4362,
4370
],
[
4480,
4488
],
[
4598,
4606
],
[
4716,
4724
],
[
4834,
4842
],
[
4952,
4960
],
[
5070,
5078
],
[
5188,
5196
],
[
5306,
5314
],
[
5424,
5432
],
[
5542,
5550
],
[
5660,
5668
],
[
5778,
5786
],
[
5896,
5904
],
[
6014,
6022
],
[
6132,
6140
],
[
6250,
6258
],
[
6368,
6376
],
[
6486,
6494
],
[
6604,
6612
],
[
6722,
6730
],
[
6937,
6945
],
[
7210,
7218
],
[
7568,
7577
],
[
7751,
7760
],
[
7953,
7962
],
[
8219,
8228
],
[
8400,
8409
],
[
8656,
8665
],
[
8879,
8888
],
[
9030,
9039
],
[
9211,
9220
],
[
9472,
9481
],
[
9798,
9807
],
[
10118,
10127
],
[
10293,
10302
],
[
10449,
10458
],
[
10669,
10678
],
[
10870,
10879
],
[
11220,
11227
],
[
11413,
11420
],
[
11756,
11765
],
[
12200,
12207
],
[
12568,
12575
],
[
12985,
12992
],
[
13223,
13230
],
[
13425,
13432
],
[
13683,
13690
],
[
14047,
14054
],
[
14211,
14218
],
[
14355,
14362
],
[
14528,
14535
],
[
14839,
14850
],
[
15208,
15213
],
[
15401,
15406
]
],
"scope": ""
}
},
"selection":
[
[
15398,
15398
]
],
"settings":
{
"detect_indentation": false,
"line_numbers": false,
"output_tag": 9,
"result_base_dir": "",
"result_file_regex": "^([A-Za-z\\\\/<].*):$",
"result_line_regex": "^ +([0-9]+):",
"scroll_past_end": true,
"syntax": "Packages/Default/Find Results.hidden-tmLanguage",
"translate_tabs_to_spaces": false
},
"translation.x": 0.0,
"translation.y": 18288.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 3,
"file": "src/vendor/angular/angular-strap.js",
"semi_transient": false,
"settings":
{
"buffer_size": 31514,
"regions":
{
},
"selection":
[
[
15185,
15185
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 14100.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 4,
"file": "src/app/panels/timepicker/module.js",
"semi_transient": false,
"settings":
{
"buffer_size": 6147,
"regions":
{
},
"selection":
[
[
2855,
2855
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 2742.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 5,
"file": "src/app/dashboards/guided.json",
"semi_transient": false,
"settings":
{
"buffer_size": 6721,
"regions":
{
},
"selection":
[
[
289,
289
]
],
"settings":
{
"syntax": "Packages/JavaScript/JSON.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 0.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 6,
"file": "src/app/panels/filtering/module.html",
"semi_transient": false,
"settings":
{
"buffer_size": 2866,
"regions":
{
},
"selection":
[
[
0,
0
]
],
"settings":
{
"syntax": "Packages/HTML/HTML.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 1440.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 7,
"file": "src/app/panels/filtering/module.js",
"semi_transient": false,
"settings":
{
"buffer_size": 2288,
"regions":
{
},
"selection":
[
[
0,
0
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 1500.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 8,
"file": "src/app/panels/graphite/module.js",
"semi_transient": false,
"settings":
{
"buffer_size": 23005,
"regions":
{
},
"selection":
[
[
22424,
22424
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 25998.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 9,
"file": "src/app/services/filterSrv.js",
"semi_transient": false,
"settings":
{
"buffer_size": 6631,
"regions":
{
},
"selection":
[
[
0,
0
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 1296.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 10,
"file": "src/app/services/graphite/graphiteSrv.js",
"semi_transient": false,
"settings":
{
"buffer_size": 2343,
"regions":
{
},
"selection":
[
[
1504,
1505
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 1554.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 11,
"file": "src/app/controllers/graphiteTarget.js",
"semi_transient": false,
"settings":
{
"buffer_size": 6702,
"regions":
{
},
"selection":
[
[
2673,
2673
]
],
"settings":
{
"syntax": "Packages/JavaScript/JavaScript.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 3168.0,
"zoom_level": 1.0
},
"type": "text"
}
]
}
],
"incremental_find":
{
"height": 28.0
},
"input":
{
"height": 40.0
},
"layout":
{
"cells":
[
[
0,
0,
1,
1
]
],
"cols":
[
0.0,
1.0
],
"rows":
[
0.0,
1.0
]
},
"menu_visible": false,
"output.exec":
{
"height": 271.0
},
"project": "grafana.sublime-project",
"replace":
{
"height": 52.0
},
"save_all_on_build": true,
"select_file":
{
"height": 0.0,
"selected_items":
[
[
"grapte",
"src\\app\\controllers\\graphiteTarget.js"
],
[
"fil",
"src\\app\\services\\filterSrv.js"
],
[
"mod",
"src\\app\\panels\\graphite\\module.js"
],
[
"filters",
"src\\app\\services\\filterSrv.js"
],
[
"dashb",
"src\\app\\services\\dashboard.js"
],
[
"graf",
"src\\vendor\\bootstrap\\less\\grafana.less"
],
[
"gsrv",
"src\\app\\panels\\graphite\\graphiteSrv.js"
],
[
"over",
"src\\vendor\\bootstrap\\less\\overrides.less"
],
[
"graphites",
"src\\app\\panels\\graphite\\graphiteSrv.js"
],
[
"inspec",
"src\\app\\partials\\inspector.html"
],
[
"module",
"src\\app\\panels\\graph\\module.js"
],
[
"tagm",
"src\\EbaySweden.TouchWeb\\static\\script\\app\\ui\\layout\\google-tagmanager.js"
],
[
"cookie.",
"src\\EbaySweden.TouchWeb\\static\\script\\utils\\cookie.js"
],
[
"page.js",
"src\\EbaySweden.TouchWeb\\static\\script\\app\\ui\\layout\\page.js"
],
[
"_main",
"src\\EbaySweden.TouchWeb\\Areas\\Default\\Views\\Shared\\_MainLayout.cshtml"
],
[
"",
"D:\\ebay\\tradera\\Applications\\TouchWeb\\src\\EbaySweden.TouchWeb\\TouchWeb.csproj"
],
[
"start-",
"src\\EbaySweden.TouchWeb\\static\\style\\components\\start-page.scss"
],
[
"bidding",
"src\\EbaySweden.TouchWeb\\static\\script\\app\\ui\\view-item\\bidding-ui.js"
],
[
"app.",
"src\\EbaySweden.TouchWeb\\static\\script\\app.js"
]
],
"width": 0.0
},
"select_project":
{
"height": 0.0,
"selected_items":
[
],
"width": 0.0
},
"select_symbol":
{
"height": 0.0,
"selected_items":
[
],
"width": 0.0
},
"settings":
{
},
"show_minimap": false,
"show_open_files": true,
"show_tabs": true,
"side_bar_visible": true,
"side_bar_width": 279.0,
"status_bar_visible": true,
"template_settings":
{
}
}
<div class="editor-row">
<div class="section">
<h5>Values</h5>
<div class="editor-option">
<label class="small">Chart value</label>
<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>
</div>
<div class="editor-option" ng-show="panel.mode != 'count'">
<label class="small">Value Field <tip>This field must contain a numeric value</tip></label>
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-medium" ng-model="panel.value_field">
</div>
</div>
<div class="section">
<h5>Transform Series</h5>
<div class="editor-option" ng-show="panel.mode != 'count'">
<label class="small">Scale</label>
<input type="text" class="input-mini" ng-model="panel.scale">
</div>
<div class="editor-option">
<label class="small">Seconds <tip>Normalize intervals to per-second</tip></label><input type="checkbox" ng-model="panel.scaleSeconds" ng-checked="panel.scaleSeconds">
</div>
<div class="editor-option">
<label class="small">Derivative <tip>Plot the change per interval in the series</tip></label><input type="checkbox" ng-model="panel.derivative" ng-checked="panel.derivative" ng-change="set_refresh(true)">
</div>
</div>
<div class="section">
<h5>Time Options</h5>
<div class="editor-option">
<label class="small">Time Field</label>
<input ng-change="set_refresh(true)" placeholder="Start typing" bs-typeahead="fields.list" type="text" class="input-small" ng-model="panel.time_field">
</div>
<div class="editor-option">
<label class="small">Time correction</label>
<select ng-model="panel.timezone" class='input-small' ng-options="f for f in ['browser','utc']"></select>
</div>
<div class="editor-option">
<label class="small">Auto-interval</label><input type="checkbox" ng-model="panel.auto_int" ng-checked="panel.auto_int" />
</div>
<div class="editor-option" ng-show='panel.auto_int'>
<label class="small">Resolution <tip>Shoot for this many data points, rounding to sane intervals</tip></label>
<input type="number" class='input-mini' ng-model="panel.resolution" ng-change='set_refresh(true)'/>
</div>
<div class="editor-option" ng-hide='panel.auto_int'>
<label class="small">Interval <tip>Use Elasticsearch date math format (eg 1m, 5m, 1d, 2w, 1y)</tip></label>
<input type="text" class='input-mini' ng-model="panel.interval" ng-change='set_refresh(true)'/>
</div>
</div>
</div>
\ No newline at end of file
define([
'kbn'
],
function (kbn) {
'use strict';
/**
* manages the interval logic
* @param {[type]} interval_string An interval string in the format '1m', '1y', etc
*/
function Interval(interval_string) {
this.string = interval_string;
var info = kbn.describe_interval(interval_string);
this.type = info.type;
this.ms = info.sec * 1000 * info.count;
// does the length of the interval change based on the current time?
if (this.type === 'y' || this.type === 'M') {
// we will just modify this time object rather that create a new one constantly
this.get = this.get_complex;
this.date = new Date(0);
} else {
this.get = this.get_simple;
}
}
Interval.prototype = {
toString: function () {
return this.string;
},
after: function(current_ms) {
return this.get(current_ms, 1);
},
before: function (current_ms) {
return this.get(current_ms, -1);
},
get_complex: function (current, delta) {
this.date.setTime(current);
switch(this.type) {
case 'M':
this.date.setUTCMonth(this.date.getUTCMonth() + delta);
break;
case 'y':
this.date.setUTCFullYear(this.date.getUTCFullYear() + delta);
break;
}
return this.date.getTime();
},
get_simple: function (current, delta) {
return current + (delta * this.ms);
}
};
return Interval;
});
\ No newline at end of file
<div ng-controller='histogram' ng-init="init()" style="min-height:{{panel.height || row.height}}">
<style>
.histogram-legend {
display:inline-block;
padding-right:5px
}
.histogram-legend-dot {
display:inline-block;
height:10px;
width:10px;
border-radius:5px;
}
.histogram-legend-item {
display:inline-block;
}
.histogram-chart {
position:relative;
}
.histogram-options {
padding: 5px;
margin-right: 15px;
margin-bottom: 0px;
}
.histogram-options label {
margin: 0px 0px 0px 10px !important;
}
.histogram-options span {
white-space: nowrap;
}
/* this is actually should be in bootstrap */
.form-inline .checkbox {
display: inline-block;
}
</style>
<div>
<span ng-show='panel.options'>
<a class="link small" ng-show='panel.options' ng-click="options=!options">
View <i ng-show="!options" class="icon-caret-right"></i><i ng-show="options" class="icon-caret-down"></i>
</a> |&nbsp
</span>
<span ng-show='panel.zoomlinks && data'>
<!--<a class='small' ng-click='zoom(0.5)'><i class='icon-zoom-in'></i> Zoom In</a>-->
<a class='small' ng-click='zoom(2)'><i class='icon-zoom-out'></i> Zoom Out</a> |&nbsp
</span>
<span ng-show="panel.legend" ng-repeat='series in legend' class="histogram-legend">
<i class='icon-circle' ng-style="{color: series.query.color}"></i>
<span class='small histogram-legend-item'>
<span ng-if="panel.show_query">{{series.query.alias || series.query.query}}</span>
<span ng-if="!panel.show_query">{{series.query.alias}}</span>
<span ng-show="panel.legend_counts"> ({{series.hits}})</span>
</span>
</span>
<span ng-show="panel.legend" class="small"><span ng-show="panel.derivative">change in </span><span class="strong" ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong ng-hide="panel.scaleSeconds">{{panel.interval}}</strong><strong ng-show="panel.scaleSeconds">1s</strong> | (<strong>{{hits}}</strong> hits)</span>
</div>
<form class="form-inline bordered histogram-options" ng-show="options">
<span>
<div class="checkbox">
<label class="small">
<input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars" ng-change="render()">
Bars
</label>
</div>
<div class="checkbox">
<label class="small">
<input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines" ng-change="render()">
Lines
</label>
</div>
<div class="checkbox">
<label class="small">
<input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack" ng-change="render()">
Stack
</label>
</div>
</span>
<span ng-show="panel.stack">
<div class="checkbox">
<label style="white-space:nowrap" class="small">
<input type="checkbox" ng-model="panel.percentage" ng-checked="panel.percentage" ng-change="render()">
Percent
</label>
</div>
</span>
<span>
<div class="checkbox">
<label class="small">
<input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend" ng-change="render()">
Legend
</label>
</div>
</span>
<span>
<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>
</span>
</form>
<center><img ng-show='panel.loading && _.isUndefined(data)' src="img/load_big.gif"></center>
<div histogram-chart class="pointer histogram-chart" params="{{panel}}"></div>
</div>
\ No newline at end of file
/** @scratch /panels/5
* include::panels/histogram.asciidoc[]
*/
/** @scratch /panels/histogram/0
* == Histogram
* Status: *Stable*
*
* The histogram panel allow for the display of time charts. It includes several modes and tranformations
* to display event counts, mean, min, max and total of numeric fields, and derivatives of counter
* fields.
*
*/
define([
'angular',
'app',
'jquery',
'underscore',
'kbn',
'moment',
'./timeSeries',
'jquery.flot',
'jquery.flot.events',
'jquery.flot.selection',
'jquery.flot.time',
'jquery.flot.byte',
'jquery.flot.stack',
'jquery.flot.stackpercent'
],
function (angular, app, $, _, kbn, moment, timeSeries) {
'use strict';
var module = angular.module('kibana.panels.histogram', []);
app.useModule(module);
module.controller('histogram', function($scope, querySrv, dashboard, filterSrv) {
$scope.panelMeta = {
modals : [
{
description: "Inspect",
icon: "icon-info-sign",
partial: "app/partials/inspector.html",
show: $scope.panel.spyable
}
],
editorTabs : [
{
title:'Style',
src:'app/panels/histogram/styleEditor.html'
},
{
title:'Queries',
src:'app/panels/histogram/queriesEditor.html'
},
],
status : "Stable",
description : "A bucketed time series chart of the current query or queries. Uses the "+
"Elasticsearch date_histogram facet. If using time stamped indices this panel will query"+
" them sequentially to attempt to apply the lighest possible load to your Elasticsearch cluster"
};
// Set and populate defaults
var _d = {
/** @scratch /panels/histogram/3
* === Parameters
* ==== Axis options
* mode:: Value to use for the y-axis. For all modes other than count, +value_field+ must be
* defined. Possible values: count, mean, max, min, total.
*/
mode : 'count',
/** @scratch /panels/histogram/3
* time_field:: x-axis field. This must be defined as a date type in Elasticsearch.
*/
time_field : '@timestamp',
/** @scratch /panels/histogram/3
* value_field:: y-axis field if +mode+ is set to mean, max, min or total. Must be numeric.
*/
value_field : null,
/** @scratch /panels/histogram/3
* x-axis:: Show the x-axis
*/
'x-axis' : true,
/** @scratch /panels/histogram/3
* y-axis:: Show the y-axis
*/
'y-axis' : true,
/** @scratch /panels/histogram/3
* scale:: Scale the y-axis by this factor
*/
scale : 1,
/** @scratch /panels/histogram/3
* y_format:: 'none','bytes','short '
*/
y_format : 'none',
/** @scratch /panels/histogram/5
* grid object:: Min and max y-axis values
* grid.min::: Minimum y-axis value
* grid.max::: Maximum y-axis value
*/
grid : {
max: null,
min: 0
},
/** @scratch /panels/histogram/5
* ==== Queries
* queries object:: This object describes the queries to use on this panel.
* queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
* queries.ids::: In +selected+ mode, which query ids are selected.
*/
queries : {
mode : 'all',
ids : []
},
/** @scratch /panels/histogram/3
* ==== Annotations
* annotate object:: A query can be specified, the results of which will be displayed as markers on
* the chart. For example, for noting code deploys.
* annotate.enable::: Should annotations, aka markers, be shown?
* annotate.query::: Lucene query_string syntax query to use for markers.
* annotate.size::: Max number of markers to show
* annotate.field::: Field from documents to show
* annotate.sort::: Sort array in format [field,order], For example [`@timestamp',`desc']
*/
annotate : {
enable : false,
query : "*",
size : 20,
field : '_type',
sort : ['_score','desc']
},
/** @scratch /panels/histogram/3
* ==== Interval options
* auto_int:: Automatically scale intervals?
*/
auto_int : true,
/** @scratch /panels/histogram/3
* resolution:: If auto_int is true, shoot for this many bars.
*/
resolution : 100,
/** @scratch /panels/histogram/3
* interval:: If auto_int is set to false, use this as the interval.
*/
interval : '5m',
/** @scratch /panels/histogram/3
* interval:: Array of possible intervals in the *View* selector. Example [`auto',`1s',`5m',`3h']
*/
intervals : ['auto','1s','1m','5m','10m','30m','1h','3h','12h','1d','1w','1y'],
/** @scratch /panels/histogram/3
* ==== Drawing options
* lines:: Show line chart
*/
lines : false,
/** @scratch /panels/histogram/3
* fill:: Area fill factor for line charts, 1-10
*/
fill : 0,
/** @scratch /panels/histogram/3
* linewidth:: Weight of lines in pixels
*/
linewidth : 3,
/** @scratch /panels/histogram/3
* points:: Show points on chart
*/
points : false,
/** @scratch /panels/histogram/3
* pointradius:: Size of points in pixels
*/
pointradius : 5,
/** @scratch /panels/histogram/3
* bars:: Show bars on chart
*/
bars : true,
/** @scratch /panels/histogram/3
* stack:: Stack multiple series
*/
stack : true,
/** @scratch /panels/histogram/3
* spyable:: Show inspect icon
*/
spyable : true,
/** @scratch /panels/histogram/3
* zoomlinks:: Show `Zoom Out' link
*/
zoomlinks : true,
/** @scratch /panels/histogram/3
* options:: Show quick view options section
*/
options : true,
/** @scratch /panels/histogram/3
* legend:: Display the legond
*/
legend : true,
/** @scratch /panels/histogram/3
* show_query:: If no alias is set, should the query be displayed?
*/
show_query : true,
/** @scratch /panels/histogram/3
* interactive:: Enable click-and-drag to zoom functionality
*/
interactive : true,
/** @scratch /panels/histogram/3
* legend_counts:: Show counts in legend
*/
legend_counts : true,
/** @scratch /panels/histogram/3
* ==== Transformations
* timezone:: Correct for browser timezone?. Valid values: browser, utc
*/
timezone : 'browser', // browser or utc
/** @scratch /panels/histogram/3
* percentage:: Show the y-axis as a percentage of the axis total. Only makes sense for multiple
* queries
*/
percentage : false,
/** @scratch /panels/histogram/3
* zerofill:: Improves the accuracy of line charts at a small performance cost.
*/
zerofill : true,
/** @scratch /panels/histogram/3
* derivative:: Show each point on the x-axis as the change from the previous point
*/
derivative : false,
/** @scratch /panels/histogram/3
* tooltip object::
* tooltip.value_type::: Individual or cumulative controls how tooltips are display on stacked charts
* tooltip.query_as_alias::: If no alias is set, should the query be displayed?
*/
tooltip : {
value_type: 'cumulative',
query_as_alias: true
}
};
_.defaults($scope.panel,_d);
_.defaults($scope.panel.tooltip,_d.tooltip);
_.defaults($scope.panel.annotate,_d.annotate);
_.defaults($scope.panel.grid,_d.grid);
$scope.init = function() {
// Hide view options by default
$scope.options = false;
// Always show the query if an alias isn't set. Users can set an alias if the query is too
// long
$scope.panel.tooltip.query_as_alias = true;
$scope.get_data();
};
$scope.set_interval = function(interval) {
if(interval !== 'auto') {
$scope.panel.auto_int = false;
$scope.panel.interval = interval;
} else {
$scope.panel.auto_int = true;
}
};
$scope.interval_label = function(interval) {
return $scope.panel.auto_int && interval === $scope.panel.interval ? interval+" (auto)" : interval;
};
/**
* The time range effecting the panel
* @return {[type]} [description]
*/
$scope.get_time_range = function () {
var range = $scope.range = filterSrv.timeRange();
return range;
};
$scope.get_interval = function () {
var interval = $scope.panel.interval,
range;
if ($scope.panel.auto_int) {
range = $scope.get_time_range();
if (range) {
interval = kbn.secondsToHms(
kbn.calculate_interval(range.from, range.to, $scope.panel.resolution, 0) / 1000
);
}
}
$scope.panel.interval = interval || '10m';
return $scope.panel.interval;
};
/**
* Fetch the data for a chunk of a queries results. Multiple segments occur when several indicies
* need to be consulted (like timestamped logstash indicies)
*
* The results of this function are stored on the scope's data property. This property will be an
* array of objects with the properties info, time_series, and hits. These objects are used in the
* render_panel function to create the historgram.
*
* @param {number} segment The segment count, (0 based)
* @param {number} query_id The id of the query, generated on the first run and passed back when
* this call is made recursively for more segments
*/
$scope.get_data = function(data, segment, query_id) {
var
_range,
_interval,
request,
queries,
results;
if (_.isUndefined(segment)) {
segment = 0;
}
delete $scope.panel.error;
// Make sure we have everything for the request to complete
if(dashboard.indices.length === 0) {
return;
}
_range = $scope.get_time_range();
_interval = $scope.get_interval(_range);
if ($scope.panel.auto_int) {
$scope.panel.interval = kbn.secondsToHms(
kbn.calculate_interval(_range.from,_range.to,$scope.panel.resolution,0)/1000);
}
$scope.panelMeta.loading = true;
request = $scope.ejs.Request().indices(dashboard.indices[segment]);
$scope.panel.queries.ids = querySrv.idsByMode($scope.panel.queries);
queries = querySrv.getQueryObjs($scope.panel.queries.ids);
// Build the query
_.each(queries, function(q) {
var query = $scope.ejs.FilteredQuery(
querySrv.toEjsObj(q),
filterSrv.getBoolFilter(filterSrv.ids)
);
var facet = $scope.ejs.DateHistogramFacet(q.id);
if($scope.panel.mode === 'count') {
facet = facet.field($scope.panel.time_field).global(true);
} else {
if(_.isNull($scope.panel.value_field)) {
$scope.panel.error = "In " + $scope.panel.mode + " mode a field must be specified";
return;
}
facet = facet.keyField($scope.panel.time_field).valueField($scope.panel.value_field).global(true);
}
facet = facet.interval(_interval).facetFilter($scope.ejs.QueryFilter(query));
request = request.facet(facet)
.size($scope.panel.annotate.enable ? $scope.panel.annotate.size : 0);
});
if($scope.panel.annotate.enable) {
var query = $scope.ejs.FilteredQuery(
$scope.ejs.QueryStringQuery($scope.panel.annotate.query || '*'),
filterSrv.getBoolFilter(filterSrv.idsByType('time'))
);
request = request.query(query);
// This is a hack proposed by @boaz to work around the fact that we can't get
// to field data values directly, and we need timestamps as normalized longs
request = request.sort([
$scope.ejs.Sort($scope.panel.annotate.sort[0]).order($scope.panel.annotate.sort[1]),
$scope.ejs.Sort($scope.panel.time_field).desc()
]);
}
// Populate the inspector panel
$scope.populate_modal(request);
// Then run it
results = request.doSearch();
// Populate scope when we have results
return results.then(function(results) {
$scope.panelMeta.loading = false;
if(segment === 0) {
$scope.legend = [];
$scope.hits = 0;
data = [];
$scope.annotations = [];
query_id = $scope.query_id = new Date().getTime();
}
// Check for error and abort if found
if(!(_.isUndefined(results.error))) {
$scope.panel.error = $scope.parse_error(results.error);
return;
}
// Make sure we're still on the same query/queries
if($scope.query_id === query_id) {
var i = 0,
time_series,
hits;
_.each(queries, function(q) {
var query_results = results.facets[q.id];
// we need to initialize the data variable on the first run,
// and when we are working on the first segment of the data.
if(_.isUndefined(data[i]) || segment === 0) {
var tsOpts = {
interval: _interval,
start_date: _range && _range.from,
end_date: _range && _range.to,
fill_style: $scope.panel.derivative ? 'null' : 'minimal'
};
time_series = new timeSeries.ZeroFilled(tsOpts);
hits = 0;
} else {
time_series = data[i].time_series;
hits = data[i].hits;
}
// push each entry into the time series, while incrementing counters
_.each(query_results.entries, function(entry) {
time_series.addValue(entry.time, entry[$scope.panel.mode]);
hits += entry.count; // The series level hits counter
$scope.hits += entry.count; // Entire dataset level hits counter
});
$scope.legend[i] = {query:q,hits:hits};
data[i] = {
info: q,
time_series: time_series,
hits: hits
};
console.log("elastic time_series:", time_series);
i++;
});
if($scope.panel.annotate.enable) {
$scope.annotations = $scope.annotations.concat(_.map(results.hits.hits, function(hit) {
var _p = _.omit(hit,'_source','sort','_score');
var _h = _.extend(kbn.flatten_json(hit._source),_p);
return {
min: hit.sort[1],
max: hit.sort[1],
eventType: "annotation",
title: null,
description: "<small><i class='icon-tag icon-flip-vertical'></i> "+
_h[$scope.panel.annotate.field]+"</small><br>"+
moment(hit.sort[1]).format('YYYY-MM-DD HH:mm:ss'),
score: hit.sort[0]
};
}));
// Sort the data
$scope.annotations = _.sortBy($scope.annotations, function(v){
// Sort in reverse
return v.score*($scope.panel.annotate.sort[1] === 'desc' ? -1 : 1);
});
// And slice to the right size
$scope.annotations = $scope.annotations.slice(0,$scope.panel.annotate.size);
}
// Tell the histogram directive to render.
$scope.$emit('render', data);
// If we still have segments left, get them
if(segment < dashboard.indices.length-1) {
$scope.get_data(data,segment+1,query_id);
}
}
});
};
// function $scope.zoom
// factor :: Zoom factor, so 0.5 = cuts timespan in half, 2 doubles timespan
$scope.zoom = function(factor) {
var _range = filterSrv.timeRange();
var _timespan = (_range.to.valueOf() - _range.from.valueOf());
var _center = _range.to.valueOf() - _timespan/2;
var _to = (_center + (_timespan*factor)/2);
var _from = (_center - (_timespan*factor)/2);
// If we're not already looking into the future, don't.
if(_to > Date.now() && _range.to < Date.now()) {
var _offset = _to - Date.now();
_from = _from - _offset;
_to = Date.now();
}
if(factor > 1) {
filterSrv.removeByType('time');
}
filterSrv.set({
type:'time',
from:moment.utc(_from).toDate(),
to:moment.utc(_to).toDate(),
field:$scope.panel.time_field
});
};
// I really don't like this function, too much dom manip. Break out into directive?
$scope.populate_modal = function(request) {
$scope.inspector = angular.toJson(JSON.parse(request.toString()),true);
};
$scope.set_refresh = function (state) {
$scope.refresh = state;
};
$scope.close_edit = function() {
if($scope.refresh) {
$scope.get_data();
}
$scope.refresh = false;
$scope.$emit('render');
};
$scope.render = function() {
$scope.$emit('render');
};
});
module.directive('histogramChart', function(dashboard, filterSrv) {
return {
restrict: 'A',
template: '<div></div>',
link: function(scope, elem) {
var data, plot;
scope.$on('refresh',function(){
scope.get_data();
});
// Receive render events
scope.$on('render',function(event,d){
data = d || data;
render_panel(data);
});
// Re-render if the window is resized
angular.element(window).bind('resize', function(){
render_panel(data);
});
var scale = function(series,factor) {
return _.map(series,function(p) {
return [p[0],p[1]*factor];
});
};
var scaleSeconds = function(series,interval) {
return _.map(series,function(p) {
return [p[0],p[1]/kbn.interval_to_seconds(interval)];
});
};
var derivative = function(series) {
return _.map(series, function(p,i) {
var _v;
if(i === 0 || p[1] === null) {
_v = [p[0],null];
} else {
_v = series[i-1][1] === null ? [p[0],null] : [p[0],p[1]-(series[i-1][1])];
}
return _v;
});
};
// Function for rendering panel
function render_panel(data) {
// IE doesn't work without this
elem.css({height:scope.panel.height || scope.row.height});
// Populate from the query service
try {
_.each(data, function(series) {
series.label = series.info.alias;
series.color = series.info.color;
});
} catch(e) {return;}
// Set barwidth based on specified interval
var barwidth = kbn.interval_to_ms(scope.panel.interval);
var stack = scope.panel.stack ? true : null;
// Populate element
try {
var options = {
legend: { show: false },
series: {
stackpercent: scope.panel.stack ? scope.panel.percentage : false,
stack: scope.panel.percentage ? null : stack,
lines: {
show: scope.panel.lines,
// Silly, but fixes bug in stacked percentages
fill: scope.panel.fill === 0 ? 0.001 : scope.panel.fill/10,
lineWidth: scope.panel.linewidth,
steps: false
},
bars: {
show: scope.panel.bars,
fill: 1,
barWidth: barwidth/1.5,
zero: false,
lineWidth: 0
},
points: {
show: scope.panel.points,
fill: 1,
fillColor: false,
radius: scope.panel.pointradius
},
shadowSize: 1
},
yaxis: {
show: scope.panel['y-axis'],
min: scope.panel.grid.min,
max: scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.max
},
xaxis: {
timezone: scope.panel.timezone,
show: scope.panel['x-axis'],
mode: "time",
min: _.isUndefined(scope.range.from) ? null : scope.range.from.getTime(),
max: _.isUndefined(scope.range.to) ? null : scope.range.to.getTime(),
timeformat: time_format(scope.panel.interval),
label: "Datetime",
ticks: elem.width()/100
},
grid: {
backgroundColor: null,
borderWidth: 0,
hoverable: true,
color: '#c8c8c8'
}
};
if(scope.panel.y_format === 'bytes') {
options.yaxis.mode = "byte";
}
if(scope.panel.y_format === 'short') {
options.yaxis.tickFormatter = function(val) {
return kbn.shortFormat(val,0);
};
}
if(scope.panel.annotate.enable) {
options.events = {
levels: 1,
data: scope.annotations,
types: {
'annotation': {
level: 1,
icon: {
icon: "icon-tag icon-flip-vertical",
size: 20,
color: "#222",
outline: "#bbb"
}
}
}
//xaxis: int // the x axis to attach events to
};
}
if(scope.panel.interactive) {
options.selection = { mode: "x", color: '#666' };
}
// when rendering stacked bars, we need to ensure each point that has data is zero-filled
// so that the stacking happens in the proper order
var required_times = [];
if (data.length > 1) {
required_times = Array.prototype.concat.apply([], _.map(data, function (query) {
return query.time_series.getOrderedTimes();
}));
required_times = _.uniq(required_times.sort(function (a, b) {
// decending numeric sort
return a-b;
}), true);
}
for (var i = 0; i < data.length; i++) {
var _d = data[i].time_series.getFlotPairs(required_times);
if(scope.panel.derivative) {
_d = derivative(_d);
}
if(scope.panel.scale !== 1) {
_d = scale(_d,scope.panel.scale);
}
if(scope.panel.scaleSeconds) {
_d = scaleSeconds(_d,scope.panel.interval);
}
data[i].data = _d;
}
plot = $.plot(elem, data, options);
} catch(e) {
// Nothing to do here
}
}
function time_format(interval) {
var _int = kbn.interval_to_seconds(interval);
if(_int >= 2628000) {
return "%Y-%m";
}
if(_int >= 86400) {
return "%Y-%m-%d";
}
if(_int >= 60) {
return "%H:%M<br>%m-%d";
}
return "%H:%M:%S";
}
var $tooltip = $('<div>');
elem.bind("plothover", function (event, pos, item) {
var group, value, timestamp;
if (item) {
if (item.series.info.alias || scope.panel.tooltip.query_as_alias) {
group = '<small style="font-size:0.9em;">' +
'<i class="icon-circle" style="color:'+item.series.color+';"></i>' + ' ' +
(item.series.info.alias || item.series.info.query)+
'</small><br>';
} else {
group = kbn.query_color_dot(item.series.color, 15) + ' ';
}
value = (scope.panel.stack && scope.panel.tooltip.value_type === 'individual') ?
item.datapoint[1] - item.datapoint[2] :
item.datapoint[1];
if(scope.panel.y_format === 'bytes') {
value = kbn.byteFormat(value,2);
}
if(scope.panel.y_format === 'short') {
value = kbn.shortFormat(value,2);
}
timestamp = scope.panel.timezone === 'browser' ?
moment(item.datapoint[0]).format('YYYY-MM-DD HH:mm:ss') :
moment.utc(item.datapoint[0]).format('YYYY-MM-DD HH:mm:ss');
$tooltip
.html(
group + value + " @ " + timestamp
)
.place_tt(pos.pageX, pos.pageY);
} else {
$tooltip.detach();
}
});
elem.bind("plotselected", function (event, ranges) {
filterSrv.set({
type : 'time',
from : moment.utc(ranges.xaxis.from).toDate(),
to : moment.utc(ranges.xaxis.to).toDate(),
field : scope.panel.time_field
});
});
}
};
});
});
<h4>Charted</h4>
<div ng-include src="'app/partials/querySelect.html'"></div>
<div class="editor-row">
<h4>Markers</h4>
<div class="small">
Here you can specify a query to be plotted on your chart as a marker. Hovering over a marker will display the field you specify below. If more documents are found than the limit you set, they will be scored by Elasticsearch and events that best match your query will be displayed.
</div>
<style>
.querySelect .query {
margin-right: 5px;
}
.querySelect .selected {
border: 3px solid;
}
.querySelect .unselected {
border: 0px solid;
}
</style>
<p>
<div class="editor-option">
<label class="small">Enable</label>
<input type="checkbox" ng-change="set_refresh(true)" ng-model="panel.annotate.enable" ng-checked="panel.annotate.enable">
</div>
<div class="editor-option" ng-show="panel.annotate.enable">
<label class="small">Marker Query</label>
<input type="text" ng-change="set_refresh(true)" class="input-large" ng-model="panel.annotate.query"/>
</div>
<div class="editor-option" ng-show="panel.annotate.enable">
<label class="small">Tooltip field</label>
<input type="text" class="input-small" ng-model="panel.annotate.field" bs-typeahead="fields.list"/>
</div>
<div class="editor-option" ng-show="panel.annotate.enable">
<label class="small">Limit <tip>Max markers on the chart</tip></label>
<input type="number" class="input-mini" ng-model="panel.annotate.size" ng-change="set_refresh(true)"/>
</div>
<div class="editor-option" ng-show="panel.annotate.enable">
<label class="small">Sort <tip>Determine the most relevant markers using this field</tip></label>
<input type="text" class="input-small" bs-typeahead="fields.list" ng-model="panel.annotate.sort[0]" ng-change="set_refresh(true)" />
<i ng-click="panel.annotate.sort[1] = _.toggle(panel.annotate.sort[1],'desc','asc');set_refresh(true)" ng-class="{'icon-chevron-up': panel.annotate.sort[1] == 'asc','icon-chevron-down': panel.annotate.sort[1] == 'desc'}"></i>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Chart Options</h5>
<div class="editor-option">
<label class="small">Bars</label><input type="checkbox" ng-model="panel.bars" ng-checked="panel.bars">
</div>
<div class="editor-option">
<label class="small">Lines</label><input type="checkbox" ng-model="panel.lines" ng-checked="panel.lines">
</div>
<div class="editor-option">
<label class="small">Points</label><input type="checkbox" ng-model="panel.points" ng-checked="panel.points">
</div>
<div class="editor-option">
<label class="small">Selectable</label><input type="checkbox" ng-model="panel.interactive" ng-checked="panel.interactive">
</div>
<div class="editor-option">
<label class="small">xAxis</label><input type="checkbox" ng-model="panel['x-axis']" ng-checked="panel['x-axis']"></div>
<div class="editor-option">
<label class="small">yAxis</label><input type="checkbox" ng-model="panel['y-axis']" ng-checked="panel['y-axis']"></div>
<div class="editor-option" ng-show="panel.lines">
<label class="small">Line Fill</label>
<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>
</div>
<div class="editor-option" ng-show="panel.lines">
<label class="small">Line Width</label>
<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>
</div>
<div class="editor-option" ng-show="panel.points">
<label class="small">Point Radius</label>
<select class="input-mini" ng-model="panel.pointradius" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10]"></select>
</div>
<div class="editor-option">
<label class="small">Y Format <tip>Y-axis formatting</tip></label>
<select class="input-small" ng-model="panel.y_format" ng-options="f for f in ['none','short','bytes']"></select>
</div>
</div>
<div class="section">
<h5>Multiple Series</h5>
<div class="editor-option">
<label class="small">Stack</label><input type="checkbox" ng-model="panel.stack" ng-checked="panel.stack">
</div>
<div class="editor-option" ng-show="panel.stack">
<label style="white-space:nowrap" class="small">Percent <tip>Stack as a percentage of total</tip></label>
<input type="checkbox" ng-model="panel.percentage" ng-checked="panel.percentage">
</div>
<div class="editor-option" ng-show="panel.stack">
<label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
<select class="input-small" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']"></select>
</div>
</div>
</div>
<div class="editor-row">
<div class="section">
<h5>Header<h5>
<div class="editor-option">
<label class="small">Zoom</label><input type="checkbox" ng-model="panel.zoomlinks" ng-checked="panel.zoomlinks" />
</div>
<div class="editor-option">
<label class="small">View</label><input type="checkbox" ng-model="panel.options" ng-checked="panel.options" />
</div>
</div>
<div class="section">
<h5>Legend<h5>
<div class="editor-option">
<label class="small">Legend</label><input type="checkbox" ng-model="panel.legend" ng-checked="panel.legend">
</div>
<div ng-show="panel.legend" class="editor-option">
<label class="small">Query <tip>If no alias is set, show the query in the legend</tip></label><input type="checkbox" ng-model="panel.show_query" ng-checked="panel.show_query">
</div>
<div ng-show="panel.legend" class="editor-option">
<label class="small">Counts</label><input type="checkbox" ng-model="panel.legend_counts" ng-checked="panel.legend_counts">
</div>
</div>
<div class="section">
<h5>Grid<h5>
<div class="editor-option">
<label class="small">Min / <a href='' ng-click="panel.grid.min = _.toggle(panel.grid.min,null,0)">Auto <i class="icon-star" ng-show="_.isNull(panel.grid.min)"></i></a></label>
<input type="number" class="input-small" ng-model="panel.grid.min"/>
</div>
<div class="editor-option">
<label class="small">Max / <a ref='' ng-click="panel.grid.max = _.toggle(panel.grid.max,null,0)">Auto <i class="icon-star" ng-show="_.isNull(panel.grid.max)"></i></a></label>
<input type="number" class="input-small" ng-model="panel.grid.max"/>
</div>
</div>
</div>
define([
'underscore',
'./interval'
],
function (_, Interval) {
'use strict';
var ts = {};
// map compatable parseInt
function base10Int(val) {
return parseInt(val, 10);
}
// trim the ms off of a time, but return it with empty ms.
function getDatesTime(date) {
return Math.floor(date.getTime() / 1000)*1000;
}
/**
* Certain graphs require 0 entries to be specified for them to render
* properly (like the line graph). So with this we will caluclate all of
* the expected time measurements, and fill the missing ones in with 0
* @param {object} opts An object specifying some/all of the options
*
* OPTIONS:
* @opt {string} interval The interval notion describing the expected spacing between
* each data point.
* @opt {date} start_date (optional) The start point for the time series, setting this and the
* end_date will ensure that the series streches to resemble the entire
* expected result
* @opt {date} end_date (optional) The end point for the time series, see start_date
* @opt {string} fill_style Either "minimal", or "all" describing the strategy used to zero-fill
* the series.
*/
ts.ZeroFilled = function (opts) {
opts = _.defaults(opts, {
interval: '10m',
start_date: null,
end_date: null,
fill_style: 'minimal'
});
// the expected differenece between readings.
this.interval = new Interval(opts.interval);
// will keep all values here, keyed by their time
this._data = {};
this.start_time = opts.start_date && getDatesTime(opts.start_date);
this.end_time = opts.end_date && getDatesTime(opts.end_date);
this.opts = opts;
};
/**
* Add a row
* @param {int} time The time for the value, in
* @param {any} value The value at this time
*/
ts.ZeroFilled.prototype.addValue = function (time, value) {
if (time instanceof Date) {
time = getDatesTime(time);
} else {
time = base10Int(time);
}
if (!isNaN(time)) {
this._data[time] = (_.isUndefined(value) ? 0 : value);
}
this._cached_times = null;
};
/**
* Get an array of the times that have been explicitly set in the series
* @param {array} include (optional) list of timestamps to include in the response
* @return {array} An array of integer times.
*/
ts.ZeroFilled.prototype.getOrderedTimes = function (include) {
var times = _.map(_.keys(this._data), base10Int);
if (_.isArray(include)) {
times = times.concat(include);
}
return _.uniq(times.sort(function (a, b) {
// decending numeric sort
return a - b;
}), true);
};
/**
* return the rows in the format:
* [ [time, value], [time, value], ... ]
*
* Heavy lifting is done by _get(Min|Default|All)FlotPairs()
* @param {array} required_times An array of timestamps that must be in the resulting pairs
* @return {array}
*/
ts.ZeroFilled.prototype.getFlotPairs = function (required_times) {
var times = this.getOrderedTimes(required_times),
strategy,
pairs;
if(this.opts.fill_style === 'all') {
strategy = this._getAllFlotPairs;
} else if(this.opts.fill_style === 'null') {
strategy = this._getNullFlotPairs;
} else if(this.opts.fill_style === 'no') {
strategy = this._getNoZeroFlotPairs;
} else {
strategy = this._getMinFlotPairs;
}
pairs = _.reduce(
times, // what
strategy, // how
[], // where
this // context
);
// if the first or last pair is inside either the start or end time,
// add those times to the series with null values so the graph will stretch to contain them.
// Removing, flot 0.8.1's max/min params satisfy this
/*
if (this.start_time && (pairs.length === 0 || pairs[0][0] > this.start_time)) {
pairs.unshift([this.start_time, null]);
}
if (this.end_time && (pairs.length === 0 || pairs[pairs.length - 1][0] < this.end_time)) {
pairs.push([this.end_time, null]);
}
*/
return pairs;
};
/**
* ** called as a reduce stragegy in getFlotPairs() **
* Fill zero's on either side of the current time, unless there is already a measurement there or
* we are looking at an edge.
* @return {array} An array of points to plot with flot
*/
ts.ZeroFilled.prototype._getMinFlotPairs = function (result, time, i, times) {
var next, expected_next, prev, expected_prev;
// check for previous measurement
if (i > 0) {
prev = times[i - 1];
expected_prev = this.interval.before(time);
if (prev < expected_prev) {
result.push([expected_prev, 0]);
}
}
// add the current time
result.push([ time, this._data[time] || 0]);
// check for next measurement
if (times.length > i) {
next = times[i + 1];
expected_next = this.interval.after(time);
if (next > expected_next) {
result.push([expected_next, 0]);
}
}
return result;
};
/**
* ** called as a reduce stragegy in getFlotPairs() **
* Fill zero's to the right of each time, until the next measurement is reached or we are at the
* last measurement
* @return {array} An array of points to plot with flot
*/
ts.ZeroFilled.prototype._getAllFlotPairs = function (result, time, i, times) {
var next, expected_next;
result.push([ times[i], this._data[times[i]] || 0 ]);
next = times[i + 1];
expected_next = this.interval.after(time);
for(; times.length > i && next > expected_next; expected_next = this.interval.after(expected_next)) {
result.push([expected_next, 0]);
}
return result;
};
/**
* ** called as a reduce stragegy in getFlotPairs() **
* Same as min, but fills with nulls
* @return {array} An array of points to plot with flot
*/
ts.ZeroFilled.prototype._getNullFlotPairs = function (result, time, i, times) {
var next, expected_next, prev, expected_prev;
// check for previous measurement
if (i > 0) {
prev = times[i - 1];
expected_prev = this.interval.before(time);
if (prev < expected_prev) {
result.push([expected_prev, null]);
}
}
// add the current time
result.push([ time, this._data[time] || null]);
// check for next measurement
if (times.length > i) {
next = times[i + 1];
expected_next = this.interval.after(time);
if (next > expected_next) {
result.push([expected_next, null]);
}
}
return result;
};
/**
* ** called as a reduce stragegy in getFlotPairs() **
* Not fill zero's on either side of the current time, only the current time
* @return {array} An array of points to plot with flot
*/
ts.ZeroFilled.prototype._getNoZeroFlotPairs = function (result, time) {
// add the current time
if(this._data[time]){
result.push([ time, this._data[time]]);
}
return result;
};
return ts;
});
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment