Просмотр исходного кода

Merge branch 'master' into export-dashboard

Torkel Ödegaard 9 лет назад
Родитель
Сommit
53bb264375

+ 16 - 0
docker/blocks/collectd/Dockerfile

@@ -0,0 +1,16 @@
+FROM    ubuntu:xenial
+
+ENV     DEBIAN_FRONTEND noninteractive
+
+RUN     apt-get -y update
+RUN     apt-get -y install collectd curl python-pip
+
+# add a fake mtab for host disk stats
+ADD     etc_mtab /etc/mtab
+
+ADD     collectd.conf.tpl /etc/collectd/collectd.conf.tpl
+
+RUN	pip install envtpl
+ADD     start_container /usr/bin/start_container
+RUN     chmod +x /usr/bin/start_container
+CMD     start_container

+ 37 - 0
docker/blocks/collectd/README.md

@@ -0,0 +1,37 @@
+collectd-write-graphite
+=======================
+
+Basic collectd-based server monitoring. Sends stats to Graphite.
+
+Collectd metrics:
+
+* CPU used/free/idle/etc
+* Free disk (via mounting hosts '/' into container, eg: -v /:/hostfs:ro)
+* Disk performance
+* Load average
+* Memory used/free/etc
+* Uptime
+* Network interface
+* Swap
+
+Environment variables
+---------------------
+
+* `HOST_NAME`
+  - Will be sent to Graphite
+  - Required
+* `GRAPHITE_HOST`
+  - Graphite IP or hostname
+  - Required
+* `GRAPHITE_PORT`
+  - Graphite port
+  - Optional, defaults to 2003
+* `GRAPHITE_PREFIX`
+  - Graphite prefix
+  - Optional, defaults to collectd.
+* `REPORT_BY_CPU`
+  - Report per-CPU metrics if true, global sum of CPU metrics if false (details: [collectd.conf man page](https://collectd.org/documentation/manpages/collectd.conf.5.shtml#plugin_cpu))
+  - Optional, defaults to false.
+* `COLLECT_INTERVAL`
+  - Collection interval and thus resolution of metrics
+  - Optional, defaults to 10

+ 76 - 0
docker/blocks/collectd/collectd.conf.tpl

@@ -0,0 +1,76 @@
+Hostname "{{ HOST_NAME }}"
+
+FQDNLookup false
+Interval {{ COLLECT_INTERVAL | default("10") }}
+Timeout 2
+ReadThreads 5
+
+LoadPlugin cpu
+LoadPlugin df
+LoadPlugin load
+LoadPlugin memory
+LoadPlugin disk
+LoadPlugin interface
+LoadPlugin uptime
+LoadPlugin swap
+LoadPlugin write_graphite
+
+<Plugin cpu>
+  ReportByCpu {{ REPORT_BY_CPU | default("false") }}
+</Plugin>
+
+<Plugin df>
+  # expose host's mounts into container using -v /:/host:ro  (location inside container does not matter much)
+  # ignore rootfs; else, the root file-system would appear twice, causing
+  # one of the updates to fail and spam the log
+  FSType rootfs
+  # ignore the usual virtual / temporary file-systems
+  FSType sysfs
+  FSType proc
+  FSType devtmpfs
+  FSType devpts
+  FSType tmpfs
+  FSType fusectl
+  FSType cgroup
+  FSType overlay
+  FSType debugfs
+  FSType pstore
+  FSType securityfs
+  FSType hugetlbfs
+  FSType squashfs
+  FSType mqueue
+  MountPoint "/etc/resolv.conf"
+  MountPoint "/etc/hostname"
+  MountPoint "/etc/hosts"
+  IgnoreSelected true
+  ReportByDevice false
+  ReportReserved true
+  ReportInodes true
+</Plugin>
+
+<Plugin "disk">
+  Disk "/^[hs]d[a-z]/"
+  IgnoreSelected false
+</Plugin>
+
+
+<Plugin interface>
+  Interface "lo"
+  Interface "/^veth.*/"
+  Interface "/^docker.*/"
+  IgnoreSelected true
+</Plugin>
+
+
+<Plugin "write_graphite">
+ <Carbon>
+   Host "{{ GRAPHITE_HOST }}"
+   Port "{{ GRAPHITE_PORT | default("2003") }}"
+   Prefix "{{ GRAPHITE_PREFIX | default("collectd.") }}"
+   EscapeCharacter "_"
+   SeparateInstances true
+   StoreRates true
+   AlwaysAppendDS false
+ </Carbon>
+</Plugin>
+

+ 1 - 0
docker/blocks/collectd/etc_mtab

@@ -0,0 +1 @@
+hostfs /.dockerinit ext4 ro,relatime,user_xattr,barrier=1,data=ordered 0 0

+ 11 - 0
docker/blocks/collectd/fig

@@ -0,0 +1,11 @@
+collectd:
+  build: blocks/collectd
+  environment:
+    HOST_NAME: myserver
+    GRAPHITE_HOST: graphite
+    GRAPHITE_PORT: 2003
+    GRAPHITE_PREFIX: collectd.
+    REPORT_BY_CPU: 'false'
+    COLLECT_INTERVAL: 10
+  links:
+    - graphite

+ 5 - 0
docker/blocks/collectd/start_container

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+envtpl /etc/collectd/collectd.conf.tpl
+
+collectd -f

+ 1 - 1
public/app/core/directives/plugin_component.ts

@@ -244,7 +244,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
         registerPluginComponent(scope, elem, attrs, componentInfo);
         registerPluginComponent(scope, elem, attrs, componentInfo);
       }).catch(err => {
       }).catch(err => {
         $rootScope.appEvent('alert-error', ['Plugin Error', err.message || err]);
         $rootScope.appEvent('alert-error', ['Plugin Error', err.message || err]);
-        console.log('Plugin componnet error', err);
+        console.log('Plugin component error', err);
       });
       });
     }
     }
   };
   };

+ 18 - 5
public/app/core/utils/kbn.js

@@ -12,9 +12,21 @@ function($, _) {
 
 
   kbn.round_interval = function(interval) {
   kbn.round_interval = function(interval) {
     switch (true) {
     switch (true) {
-    // 0.3s
-    case (interval <= 300):
-      return 100;       // 0.1s
+    // 0.015s
+    case (interval <= 15):
+      return 10;      // 0.01s
+    // 0.035s
+    case (interval <= 35):
+      return 20;      // 0.02s
+    // 0.075s
+    case (interval <= 75):
+      return 50;       // 0.05s
+    // 0.15s
+    case (interval <= 150):
+      return 100;      // 0.1s
+    // 0.35s
+    case (interval <= 350):
+      return 200;      // 0.2s
     // 0.75s
     // 0.75s
     case (interval <= 750):
     case (interval <= 750):
       return 500;       // 0.5s
       return 500;       // 0.5s
@@ -133,7 +145,7 @@ function($, _) {
     return str;
     return str;
   };
   };
 
 
-  kbn.interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/;
+  kbn.interval_regex = /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/;
 
 
   // histogram & trends
   // histogram & trends
   kbn.intervals_in_seconds = {
   kbn.intervals_in_seconds = {
@@ -143,7 +155,8 @@ function($, _) {
     d: 86400,
     d: 86400,
     h: 3600,
     h: 3600,
     m: 60,
     m: 60,
-    s: 1
+    s: 1,
+    ms: 0.001
   };
   };
 
 
   kbn.calculateInterval = function(range, resolution, userInterval) {
   kbn.calculateInterval = function(range, resolution, userInterval) {

+ 20 - 0
public/app/features/templating/editorCtrl.js

@@ -25,6 +25,7 @@ function (angular, _) {
       {value: "interval",   text: "Interval"},
       {value: "interval",   text: "Interval"},
       {value: "datasource", text: "Data source"},
       {value: "datasource", text: "Data source"},
       {value: "custom",     text: "Custom"},
       {value: "custom",     text: "Custom"},
+      {value: "constant",   text: "Constant"},
     ];
     ];
 
 
     $scope.refreshOptions = [
     $scope.refreshOptions = [
@@ -141,15 +142,34 @@ function (angular, _) {
       $scope.current = angular.copy(replacementDefaults);
       $scope.current = angular.copy(replacementDefaults);
     };
     };
 
 
+    $scope.showSelectionOptions = function() {
+      if ($scope.current) {
+        if ($scope.current.type === 'query') {
+          return true;
+        }
+        if ($scope.current.type === 'custom') {
+          return true;
+        }
+      }
+      return false;
+    };
+
     $scope.typeChanged = function () {
     $scope.typeChanged = function () {
       if ($scope.current.type === 'interval') {
       if ($scope.current.type === 'interval') {
         $scope.current.query = '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d';
         $scope.current.query = '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d';
+        $scope.current.refresh = 0;
       }
       }
 
 
       if ($scope.current.type === 'query') {
       if ($scope.current.type === 'query') {
         $scope.current.query = '';
         $scope.current.query = '';
       }
       }
 
 
+      if ($scope.current.type === 'constant') {
+        $scope.current.query = '';
+        $scope.current.refresh = 0;
+        $scope.current.hide = 2;
+      }
+
       if ($scope.current.type === 'datasource') {
       if ($scope.current.type === 'datasource') {
         $scope.current.query = $scope.datasourceTypes[0].value;
         $scope.current.query = $scope.datasourceTypes[0].value;
         $scope.current.regex = '';
         $scope.current.regex = '';

+ 9 - 1
public/app/features/templating/partials/editor.html

@@ -152,6 +152,14 @@
 				</div>
 				</div>
 			</div>
 			</div>
 
 
+			<div ng-show="current.type === 'constant'" class="gf-form-group">
+        <h5 class="section-heading">Constant options</h5>
+				<div class="gf-form">
+					<span class="gf-form-label">Value</span>
+					<input type="text" class="gf-form-input" ng-model='current.query' ng-blur="runQuery()" placeholder="your metric prefix"></input>
+				</div>
+			</div>
+
 			<div ng-show="current.type === 'query'" class="gf-form-group">
 			<div ng-show="current.type === 'query'" class="gf-form-group">
         <h5 class="section-heading">Query Options</h5>
         <h5 class="section-heading">Query Options</h5>
 
 
@@ -214,7 +222,7 @@
         </div>
         </div>
       </div>
       </div>
 
 
-      <div class="section gf-form-group" ng-hide="current.type === 'datasource'">
+      <div class="section gf-form-group" ng-show="showSelectionOptions()">
         <h5 class="section-heading">Selection Options</h5>
         <h5 class="section-heading">Selection Options</h5>
         <div class="section">
         <div class="section">
           <gf-form-switch class="gf-form"
           <gf-form-switch class="gf-form"

+ 7 - 1
public/app/features/templating/templateValuesSrv.js

@@ -168,6 +168,11 @@ function (angular, _, kbn) {
         return;
         return;
       }
       }
 
 
+      if (variable.type === 'constant') {
+        variable.options = [{text: variable.query, value: variable.query}];
+        return;
+      }
+
       // extract options in comma seperated string
       // extract options in comma seperated string
       variable.options = _.map(variable.query.split(/[,]+/), function(text) {
       variable.options = _.map(variable.query.split(/[,]+/), function(text) {
         return { text: text.trim(), value: text.trim() };
         return { text: text.trim(), value: text.trim() };
@@ -175,6 +180,7 @@ function (angular, _, kbn) {
 
 
       if (variable.type === 'interval') {
       if (variable.type === 'interval') {
         self.updateAutoInterval(variable);
         self.updateAutoInterval(variable);
+        return;
       }
       }
 
 
       if (variable.type === 'custom' && variable.includeAll) {
       if (variable.type === 'custom' && variable.includeAll) {
@@ -273,7 +279,7 @@ function (angular, _, kbn) {
         if (currentOption) {
         if (currentOption) {
           return self.setVariableValue(variable, currentOption, false);
           return self.setVariableValue(variable, currentOption, false);
         } else {
         } else {
-          if (!variable.options.length) { return; }
+          if (!variable.options.length) { return $q.when(null); }
           return self.setVariableValue(variable, variable.options[0]);
           return self.setVariableValue(variable, variable.options[0]);
         }
         }
       }
       }

+ 6 - 0
public/test/core/utils/kbn_specs.js

@@ -147,5 +147,11 @@ define([
       var str = kbn.calculateInterval(range, 1000, '>10s');
       var str = kbn.calculateInterval(range, 1000, '>10s');
       expect(str).to.be('20m');
       expect(str).to.be('20m');
     });
     });
+	
+    it('10s 900 resolution and user low limit in ms', function() {
+      var range = { from: dateMath.parse('now-10s'), to: dateMath.parse('now') };
+      var str = kbn.calculateInterval(range, 900, '>15ms');
+      expect(str).to.be('15ms');
+    });
   });
   });
 });
 });