@cryptotaxi247 / netdata-1 / commits / c5572d0dd

updated docs; nut.chart.sh now autodetects multiple UPSes, web and cache directories are chowned; charts.d is now enabled by default

Costa Tsaousis (ktsaou) committed Nov 18, 2015 at 01:07 UTC c5572d0ddaf88f58995cfe4f916494e714c2f7ca
13 files changed +332 -243
README.md
+5 -4
@@ -77,7 +77,7 @@ Here is a screenshot:
77 - `/proc/meminfo` (memory information)
78 - `/proc/vmstat` (system performance)
79 - `/proc/net/rpc/nfsd` (NFS server statistics for both v3 and v4 NFS)
80 - - `tc` classes (QoS classes)
80 + - `tc` classes (QoS classes - [with FireQOS class names](http://firehol.org/tutorial/fireqos-new-user/))
81
82 - It supports **plugins** for collecting information from other sources!
83
@@ -89,12 +89,13 @@ Here is a screenshot:
89
90 - `charts.d.plugin` provides a simple way to script data collection in BASH. It includes example plugins that collect values from:
91
92 - - `nut` (UPS load, frequency, voltage, etc)
92 + - `nut` (UPS load, frequency, voltage, etc, for multiple UPSes)
93 - `sensors` (temperature, voltage, current, power, humidity, fans rotation sensors)
94 - - `cpufreq` (current CPU clock frequency)
94 + - `cpufreq` (current CPU clock frequency, for all CPUs)
95 - `postfix` (e-mail queue size)
96 - `squid` (web proxy statistics)
97 - `mysql` (mysql global statistics)
98 + - `opensips` (opensips statistics)
99
100 Of course, you can write your own using BASH scripting.
101
@@ -102,7 +103,7 @@ Here is a screenshot:
103
104 It serves its own static files and dynamic files for rendering the site.
105 It does not support authentication or SSL - limit its access using your firewall.
105 - It does not allow ` .. ` or ` / ` in the files requested (so it can only serve files stored in the `web/` directory).
106 + It does not allow ` .. ` or ` / ` in the files requested (so it can only serve files stored in the web directory `/usr/share/netdata/web`).
107
108
109 # How it works
charts.d/Makefile.am
+1
@@ -4,6 +4,7 @@
4 MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
5
6 dist_charts_SCRIPTS = \
7 + README.md \
8 airsearches.chart.sh \
9 cpu_apps.chart.sh \
10 cpufreq.chart.sh \
charts.d/README.md new
+1
@@ -0,0 +1 @@
1 +
charts.d/mysql.chart.sh
+5 -1
@@ -7,7 +7,7 @@
7 # This statement does not require any privilege.
8 # It requires only the ability to connect to the server.
9
10 -mysql_cmd_opts=""
10 +mysql_cmd_opts=
11 mysql_update_every=5
12
13 mysql_get_stats() {
@@ -15,6 +15,10 @@ mysql_get_stats() {
15 }
16
17 mysql_check() {
18 + require_cmd mysql || exit 1
19 + require_cmd egrep || exit 1
20 + require_cmd sed || exit 1
21 +
22 # check once if the url works
23 local x="$(mysql_get_stats | grep "^Connections[[:space:]]")"
24 if [ ! $? -eq 0 -o -z "$x" ]
charts.d/nut.chart.sh
+47 -27
@@ -4,56 +4,70 @@ nut_ups=
4 nut_update_every=2
5
6 nut_check() {
7 - if [ -z "${nut_ups}" ]
7 + local x all
8 +
9 + require_cmd upsc || return 1
10 + require_cmd awk || return 1
11 +
12 + all="$nut_ups"
13 + [ -z "$all" ] && all="$(upsc -l)"
14 +
15 + nut_ups=
16 + for x in $all
17 + do
18 + upsc "$x" >/dev/null
19 + [ $? -eq 0 ] && nut_ups="$nut_ups $x" && continue
20 + echo >&2 "nut: ERROR: Cannot get information for NUT UPS '$x'."
21 + done
22 +
23 + if [ -z "$nut_ups" ]
24 then
25 echo >&2 "nut: Please set nut_ups='ups_name' in $confd/nut.conf"
26 return 1
27 fi
28
13 - upsc "${nut_ups}" >/dev/null
14 - if [ ! $? -eq 0 ]
15 - then
16 - echo >&2 "nut: failed to fetch info for ups '$nut_ups'. Please set nut_ups='ups_name' in $confd/nut.conf"
17 - return 1
18 - fi
19 -
29 return 0
30 }
31
32 nut_create() {
33 # create the charts
25 - cat <<EOF
26 -CHART nut.charge '' "UPS Charge" "percentage" nut '' area 21001 $nut_update_every
34 + local x
35 +
36 + for x in $nut_ups
37 + do
38 + cat <<EOF
39 +CHART nut_$x.charge '' "UPS Charge" "percentage" $x nut area 21001 $nut_update_every
40 DIMENSION battery_charge charge absolute 1 100
41
29 -CHART nut.battery_voltage '' "UPS Battery Voltage" "Volts" nut '' line 21002 $nut_update_every
42 +CHART nut_$x.battery_voltage '' "UPS Battery Voltage" "Volts" $x nut line 21002 $nut_update_every
43 DIMENSION battery_voltage voltage absolute 1 100
44 DIMENSION battery_voltage_high high absolute 1 100
45 DIMENSION battery_voltage_low low absolute 1 100
46 DIMENSION battery_voltage_nominal nominal absolute 1 100
47
35 -CHART nut.input_voltage '' "UPS Input Voltage" "Volts" nut '' line 21003 $nut_update_every
48 +CHART nut_$x.input_voltage '' "UPS Input Voltage" "Volts" $x nut line 21003 $nut_update_every
49 DIMENSION input_voltage voltage absolute 1 100
50 DIMENSION input_voltage_fault fault absolute 1 100
51 DIMENSION input_voltage_nominal nominal absolute 1 100
52
40 -CHART nut.input_current '' "UPS Input Current" "Ampere" nut '' line 21004 $nut_update_every
53 +CHART nut_$x.input_current '' "UPS Input Current" "Ampere" $x nut line 21004 $nut_update_every
54 DIMENSION input_current_nominal nominal absolute 1 100
55
43 -CHART nut.input_frequency '' "UPS Input Frequency" "Hz" nut '' line 21005 $nut_update_every
56 +CHART nut_$x.input_frequency '' "UPS Input Frequency" "Hz" $x nut line 21005 $nut_update_every
57 DIMENSION input_frequency frequency absolute 1 100
58 DIMENSION input_frequency_nominal nominal absolute 1 100
59
47 -CHART nut.output_voltage '' "UPS Output Voltage" "Volts" nut '' line 21006 $nut_update_every
60 +CHART nut_$x.output_voltage '' "UPS Output Voltage" "Volts" $x nut line 21006 $nut_update_every
61 DIMENSION output_voltage voltage absolute 1 100
62
50 -CHART nut.load '' "UPS Load" "percentage" nut '' area 21000 $nut_update_every
63 +CHART nut_$x.load '' "UPS Load" "percentage" $x nut area 21000 $nut_update_every
64 DIMENSION load load absolute 1 100
65
53 -CHART nut.temp '' "UPS Temperature" "temperature" nut '' line 21007 $nut_update_every
66 +CHART nut_$x.temp '' "UPS Temperature" "temperature" $x nut line 21007 $nut_update_every
67 DIMENSION temp temp absolute 1 100
68 EOF
56 -
69 + done
70 +
71 return 0
72 }
73
@@ -66,7 +80,11 @@ nut_update() {
80 # for each dimension
81 # remember: KEEP IT SIMPLE AND SHORT
82
69 - upsc "${nut_ups}" | awk "
83 + local x
84 +
85 + for x in $nut_ups
86 + do
87 + upsc "$x" | awk "
88 BEGIN {
89 battery_charge = 0;
90 battery_voltage = 0;
@@ -98,45 +116,47 @@ BEGIN {
116 /^ups.load: .*/ { load = \$2 * 100 };
117 /^ups.temperature: .*/ { temp = \$2 * 100 };
118 END {
101 - print \"BEGIN nut.charge $1\";
119 + print \"BEGIN nut_$x.charge $1\";
120 print \"SET battery_charge = \" battery_charge;
121 print \"END\"
122
105 - print \"BEGIN nut.battery_voltage $1\";
123 + print \"BEGIN nut_$x.battery_voltage $1\";
124 print \"SET battery_voltage = \" battery_voltage;
125 print \"SET battery_voltage_high = \" battery_voltage_high;
126 print \"SET battery_voltage_low = \" battery_voltage_low;
127 print \"SET battery_voltage_nominal = \" battery_voltage_nominal;
128 print \"END\"
129
112 - print \"BEGIN nut.input_voltage $1\";
130 + print \"BEGIN nut_$x.input_voltage $1\";
131 print \"SET input_voltage = \" input_voltage;
132 print \"SET input_voltage_fault = \" input_voltage_fault;
133 print \"SET input_voltage_nominal = \" input_voltage_nominal;
134 print \"END\"
135
118 - print \"BEGIN nut.input_current $1\";
136 + print \"BEGIN nut_$x.input_current $1\";
137 print \"SET input_current_nominal = \" input_current_nominal;
138 print \"END\"
139
122 - print \"BEGIN nut.input_frequency $1\";
140 + print \"BEGIN nut_$x.input_frequency $1\";
141 print \"SET input_frequency = \" input_frequency;
142 print \"SET input_frequency_nominal = \" input_frequency_nominal;
143 print \"END\"
144
127 - print \"BEGIN nut.output_voltage $1\";
145 + print \"BEGIN nut_$x.output_voltage $1\";
146 print \"SET output_voltage = \" output_voltage;
147 print \"END\"
148
131 - print \"BEGIN nut.load $1\";
149 + print \"BEGIN nut_$x.load $1\";
150 print \"SET load = \" load;
151 print \"END\"
152
135 - print \"BEGIN nut.temp $1\";
153 + print \"BEGIN nut_$x.temp $1\";
154 print \"SET temp = \" temp;
155 print \"END\"
156 }
157 "
158 + done
159 +
160 return 0
161 }
162
conf.d/Makefile.am
+1
@@ -4,5 +4,6 @@
4 MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
5
6 dist_config_DATA = \
7 + charts.d.conf \
8 apps_groups.conf \
9 $(NULL)
conf.d/charts.d.conf new
+8
@@ -0,0 +1,8 @@
1 +nut=yes
2 +squid=yes
3 +postfix=yes
4 +sensors=yes
5 +cpufreq=yes
6 +mysql=yes
7 +#example=yes
8 +#load_average=yes
plugins.d/Makefile.am
+2 -2
@@ -4,12 +4,12 @@
4 MAINTAINERCLEANFILES= $(srcdir)/Makefile.in
5
6 dist_plugins_DATA = \
7 - README \
8 - loopsleepms.sh.inc \
7 + README.md \
8 $(NULL)
9
10 dist_plugins_SCRIPTS = \
11 charts.d.dryrun-helper.sh \
12 charts.d.plugin \
13 tc-qos-helper.sh \
14 + loopsleepms.sh.inc \
15 $(NULL)
plugins.d/README deleted
-195
@@ -1,195 +0,0 @@
1 -
2 --------------------------------------------------------------------------------
3 -NETDATA CUSTOM PLUGINS
4 -
5 -custom chart plugins can be any program that can print a few values on its
6 -standard output.
7 -
8 -There are 5 lines netdata parses. lines starting with:
9 -
10 -CHART - create a new chart
11 -DIMENSION - add a dimension to the chart just created
12 -
13 -BEGIN - initialize data collection for a chart
14 -SET - set the value of a dimension for the initialized chart
15 -END - complete data collection for the initialized chart
16 -
17 -a single script can produce any number of charts with any number of dimensions
18 -each. charts can also be added any time (not just the beginning).
19 -
20 -The script should accept just one parameter: the number of seconds it is
21 -expected to update the values for its charts. The value passed by netdata
22 -to the script is controlled via the configuration file.
23 -
24 -The script can overwrite the update frequency. For example, the server may
25 -request per second updates, but the script may overwrite this to one update
26 -every 5 seconds.
27 -
28 -
29 --------------------------------------------------------------------------------
30 -CREATE NEW CHART
31 -
32 - > CHART type.id name title units family[=id] category[=type] charttype[=line]
33 - priority[=1000] update_every[=user default]
34 -
35 - where:
36 - - type.id
37 - uniquely identifies the chart
38 - this is what will be needed to add values to the chart
39 -
40 - - name
41 - is the name that will be presented to the used for this chart
42 -
43 - - title
44 - the text above the chart
45 -
46 - - units
47 - the label of the vertical axis of the chart
48 -
49 - - family
50 - is used to group charts together.
51 - (for example all eth0 charts should say: eth0)
52 -
53 - - category
54 - is not used currently.
55 - it will be used to set the section under which the chart will appear
56 - (for example mem.ram should appear in the 'system' section)
57 - the special word 'none' means: do not show this chart on the home page
58 -
59 - - charttype
60 - line, area or stacked
61 -
62 - - priority
63 - is the relative priority of the charts as rendered on the web page
64 - lower numbers make the charts appear before the ones with higher numbers
65 -
66 - - update_every
67 - overwrite the update frequency set by the server
68 -
69 -
70 --------------------------------------------------------------------------------
71 -ADD DIMENSIONS
72 -
73 - > DIMENSION id name[=id] algorithm[=absolute] multiplier[=1] divisor[=1]
74 - hidden[=not set]
75 -
76 - where:
77 -
78 - - id
79 - the id of this dimension (it is a text value, not numeric)
80 - this will be needed to add values to the dimension
81 -
82 - - name
83 - the name of the dimension as it will appear at the legend of the chart
84 -
85 - - algorithms
86 - one of:
87 -
88 - * absolute
89 - the value is to drawn as-is
90 -
91 - * incremental
92 - the value increases over time.
93 - the difference from the last value is presented in the chart.
94 - the server stretches the difference to produce 1 second increments.
95 - it does this at the microsecond level.
96 -
97 - * percentage-of-absolute-row
98 - the % of this value compared to the total of all dimensions.
99 -
100 - * percentage-of-incremental-row
101 - the % of this value compared to the differential total of
102 - each dimension.
103 -
104 - - multiplier
105 - a value to multiply the collected value.
106 -
107 - - divisor
108 - a value to divide the collected value.
109 -
110 - - hidden
111 - giving the keyword 'hidden' will make this dimension hidden.
112 - it will take part in the calculation but will not be presented in the chart
113 -
114 -
115 --------------------------------------------------------------------------------
116 -DATA COLLECTION
117 -
118 - data collection is defined as a series of BEGIN -> SET -> END lines.
119 -
120 - > BEGIN type.id
121 -
122 - - type.id
123 - is the unique identification of the chart (created with CHART)
124 -
125 - > SET id = value
126 -
127 - - id
128 - is the unique identification of the dimension (of the chart just began)
129 -
130 - - value
131 - is the collected value
132 -
133 - more SET lines may appear to update all the dimensions of the chart.
134 - all of them in one BEGIN -> END block.
135 - All SET lines within a single BEGIN -> END block have to refer to the
136 - same chart. If more charts need to be updated, each chart should have
137 - its own BEGIN -> SET -> END block.
138 -
139 - > END
140 -
141 - END does not take any parameters.
142 - it commits the collected values to the chart.
143 -
144 -
145 -
146 --------------------------------------------------------------------------------
147 -A NOTE ABOUT VALUES
148 -
149 - NetData will collect any signed value in the 64bit range:
150 -
151 - -9.223.372.036.854.775.808 to +9.223.372.036.854.775.807
152 -
153 - However, to lower its memory requirements, it stores all values in the
154 - signed 32bit range, divided by 10, that is:
155 -
156 - -214.748.364 to +214.748.364
157 -
158 - This division by 10, is used to give a decimal point in the charts.
159 - In memory, every number is 4 bytes (32bits).
160 -
161 - algorithm, multiplier and divisor help maintain all the detail required.
162 -
163 - The algorithm is applied in the wider 64bit numbers. Once the calculation
164 - is complete the value is multiplied by the multiplier, by 10, and then
165 - divided by the divider (all of these at the 64bit level).
166 - The 64bit result is then stored in a 32 bit signed int.
167 -
168 - So, at the chart level:
169 -
170 - - the finest number is 0.1
171 - - the smallest -214.748.364,8
172 - - the highest 214.748.364,7
173 -
174 - You should choose a multiplier and divisor to stay within these limits.
175 -
176 - Example:
177 -
178 - eth0 bytes-in is a 64bit number that is incremented every time.
179 - let say it is 1.000.000.000.000.000.000
180 - and one second later it is 1.000.000.000.999.000.000
181 -
182 - the dimension is 'incremental' with multiplier 8 (bytes to bits)
183 - and divider 1024 (bits to kilobits).
184 -
185 - netdata will store this value:
186 -
187 - value = (1.000.000.000.000.000.000 - 1.000.000.000.999.000.000)
188 - * 10
189 - * 8
190 - / 1024
191 - = 78.046.875
192 -
193 - or 7.804.687,5 kilobits/second (a little less than 8 gigabits/second)
194 -
195 -
plugins.d/README.md new
+236
@@ -0,0 +1,236 @@
1 +netdata plugins
2 +===============
3 +
4 +Any program that can print a few values to its standard output can become
5 +a netdata plugin.
6 +
7 +There are 5 lines netdata parses. lines starting with:
8 +
9 +- `CHART` - create a new chart
10 +- `DIMENSION` - add a dimension to the chart just created
11 +- `BEGIN` - initialize data collection for a chart
12 +- `SET` - set the value of a dimension for the initialized chart
13 +- `END` - complete data collection for the initialized chart
14 +
15 +a single program can produce any number of charts with any number of dimensions
16 +each.
17 +
18 +charts can also be added any time (not just the beginning).
19 +
20 +### command line parameters
21 +
22 +The plugin should accept just **one** parameter: **the number of seconds it is
23 +expected to update the values for its charts**. The value passed by netdata
24 +to the plugin is controlled via its configuration file (so there is not need
25 +for the plugin to handle this configuration option).
26 +
27 +The script can overwrite the update frequency. For example, the server may
28 +request per second updates, but the script may overwrite this to one update
29 +every 5 seconds.
30 +
31 +### environment variables
32 +
33 +There are a few environment variables that are set by `netdata` and are
34 +available for the plugin to use.
35 +
36 +variable|description
37 +:------:|:----------
38 +`NETDATA_CONFIG_DIR`|The directory where all netdata related configuration should be stored. If the plugin requires custom configuration, this is the place to save it.
39 +`NETDATA_PLUGINS_DIR`|The directory where all netdata plugins are stored.
40 +`NETDATA_WEB_DIR`|The directory where the web files of netdata are saved.
41 +`NETDATA_CACHE_DIR`|The directory where the cache files of netdata are stored. Use this directory if the plugin requires a place to store data. A new directory should be created for the plugin for this purpose, inside this directory.
42 +`NETDATA_LOG_DIR`|The directory where the log files are stored. By default the `stderr` output of the plugin will be saved in the `error.log` file of netdata.
43 +`NETDATA_HOST_PREFIX`|This is used in environments where system directories like `/sys` and `/proc` have to be accessed at a different path.
44 +`NETDATA_DEBUG_FLAGS`|This is number (probably in hex starting with `0x`), that enables certain netdata debugging features.
45 +`NETDATA_UPDATE_EVERY`|The minimum number of seconds between chart refreshes. This is like the **internal clock** of netdata (it is user configurable, defaulting to `1`). There is no meaning for a plugin to update its values more frequently than this number of seconds.
46 +
47 +
48 +# the output of the plugin
49 +
50 +The plugin should output instructions for netdata to its output (`stdout`).
51 +
52 +## CHART
53 +
54 +`CHART` defines a new chart.
55 +
56 +the template is:
57 +
58 + > CHART type.id name title units [family [category [charttype [priority [update_every]]]]]
59 +
60 + where:
61 + - `type.id`
62 +
63 + uniquely identifies the chart,
64 + this is what will be needed to add values to the chart
65 +
66 + - `name`
67 +
68 + is the name that will be presented to the used for this chart
69 +
70 + - `title`
71 +
72 + the text above the chart
73 +
74 + - `units`
75 +
76 + the label of the vertical axis of the chart,
77 + all dimensions added to a chart should have the same units
78 + of measurement
79 +
80 + - `family`
81 +
82 + is used to group charts together
83 + (for example all eth0 charts should say: eth0),
84 + if empty or missing, the `id` part of `type.id` will be used
85 +
86 + - `category`
87 +
88 + the section under which the chart will appear
89 + (for example mem.ram should appear in the 'system' section),
90 + the special word 'none' means: do not show this chart on the home page,
91 + if empty or missing, the `type` part of `type.id` will be used
92 +
93 + - `charttype`
94 +
95 + one of `line`, `area` or `stacked`,
96 + if empty or missing, the `line` will be used
97 +
98 + - `priority`
99 +
100 + is the relative priority of the charts as rendered on the web page,
101 + lower numbers make the charts appear before the ones with higher numbers,
102 + if empty or missing, `1000` will be used
103 +
104 + - `update_every`
105 +
106 + overwrite the update frequency set by the server,
107 + if empty or missing, the user configured value will be used
108 +
109 +
110 +## DIMENSION
111 +
112 +`DIMENSION` defines a new dimension for the chart
113 +
114 +the template is:
115 +
116 + > DIMENSION id [name [algorithm [multiplier [divisor [hidden]]]]]
117 +
118 + where:
119 +
120 + - `id`
121 +
122 + the `id` of this dimension (it is a text value, not numeric),
123 + this will be needed later to add values to the dimension
124 +
125 + - `name`
126 +
127 + the name of the dimension as it will appear at the legend of the chart,
128 + if empty or missing the `id` will be used
129 +
130 + - `algorithm`
131 +
132 + one of:
133 +
134 + * `absolute`
135 +
136 + the value is to drawn as-is (interpolated to second boundary),
137 + if `algorithm` is empty, invalid or missing, `absolute` is used
138 +
139 + * `incremental`
140 +
141 + the value increases over time,
142 + the difference from the last value is presented in the chart,
143 + the server interpolates the value and calculates a per second figure
144 +
145 + * `percentage-of-absolute-row`
146 +
147 + the % of this value compared to the total of all dimensions
148 +
149 + * `percentage-of-incremental-row`
150 +
151 + the % of this value compared to the incremental total of
152 + all dimensions
153 +
154 + - `multiplier`
155 +
156 + an integer value to multiply the collected value,
157 + if empty or missing, `1` is used
158 +
159 + - `divisor`
160 +
161 + an integer value to divide the collected value,
162 + if empty or missing, `1` is used
163 +
164 + - `hidden`
165 +
166 + giving the keyword `hidden` will make this dimension hidden,
167 + it will take part in the calculations but will not be presented in the chart
168 +
169 +
170 +## data collection
171 +
172 +data collection is defined as a series of `BEGIN` -> `SET` -> `END` lines
173 +
174 + > BEGIN type.id [microseconds]
175 +
176 + - `type.id`
177 +
178 + is the unique identification of the chart (as given in `CHART`)
179 +
180 + - `microseconds`
181 +
182 + is the number of microseconds since the last update of the chart,
183 + it is optional.
184 +
185 + Under heavy system load, the system may have some latency transfering
186 + data from the plugins to netdata via the pipe. This number improves
187 + accuracy significantly, since the plugin is able to calculate the
188 + duration between its iterations better than netdata.
189 +
190 + The first time the plugin is started, no microseconds should be given
191 + to netdata.
192 +
193 + > SET id = value
194 +
195 + - `id`
196 +
197 + is the unique identification of the dimension (of the chart just began)
198 +
199 + - `value`
200 +
201 + is the collected value
202 +
203 + > END
204 +
205 +END does not take any parameters, it commits the collected values to the chart.
206 +
207 +More `SET` lines may appear to update all the dimensions of the chart.
208 +All of them in one `BEGIN` -> `END` block.
209 +
210 +All `SET` lines within a single `BEGIN` -> `END` block have to refer to the
211 +same chart.
212 +
213 +If more charts need to be updated, each chart should have its own
214 +`BEGIN` -> `SET` -> `END` block.
215 +
216 +If, for any reason, a plugin has issued a `BEGIN` but wants to cancel it,
217 +it can issue a `FLUSH`. The `FLUSH` command will instruct netdata to ignore
218 +the last `BEGIN` command.
219 +
220 +If a plugin does not behave properly (outputs invalid lines, or does not
221 +follow these guidelines), will be disabled by netdata.
222 +
223 +
224 +# collected values
225 +
226 +netdata will collect any **signed** value in the 64bit range:
227 +`-9.223.372.036.854.775.808` to `+9.223.372.036.854.775.807`
228 +
229 +Internally, all calculations are made using 128 bit double precision and are
230 +stored in 30 bits as floating point.
231 +
232 +If a value is not collected, leave it empty, like this:
233 +
234 +`SET id = `
235 +
236 +or do not output the line at all.
plugins.d/charts.d.plugin
+1
@@ -103,6 +103,7 @@ do
103 then
104 shift
105 update_every=$x
106 + [ $update_every -lt $minimum_update_frequency ] && update_every=$minimum_update_frequency
107 continue
108 fi
109
src/plugins_d.c
+18 -14
@@ -35,9 +35,9 @@ static inline int pluginsd_space(char c) {
35 }
36 }
37
38 -static void pluginsd_split_words(char *str, char **words, int max_words) {
38 +static int pluginsd_split_words(char *str, char **words, int max_words) {
39 char *s = str, quote = 0;
40 - int i = 0;
40 + int i = 0, j;
41
42 // skip all white space
43 while(unlikely(pluginsd_space(*s))) s++;
@@ -94,7 +94,10 @@ static void pluginsd_split_words(char *str, char **words, int max_words) {
94 }
95
96 // terminate the words
97 - while(likely(i < max_words)) words[i++] = NULL;
97 + j = i;
98 + while(likely(j < max_words)) words[j++] = NULL;
99 +
100 + return i;
101 }
102
103
@@ -140,9 +143,9 @@ void *pluginsd_worker_thread(void *arg)
143
144 // debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line);
145
143 - pluginsd_split_words(line, words, MAX_WORDS);
146 + int w = pluginsd_split_words(line, words, MAX_WORDS);
147 s = words[0];
145 - if(unlikely(!s || !*s)) {
148 + if(unlikely(!s || !*s || !w)) {
149 // debug(D_PLUGINSD, "PLUGINSD: empty line");
150 continue;
151 }
@@ -156,23 +159,24 @@ void *pluginsd_worker_thread(void *arg)
159 char *value = words[2];
160
161 if(unlikely(!dimension || !*dimension)) {
159 - error("PLUGINSD: '%s' is requesting a SET on chart '%s', like this: 'SET %s = %s'. Disabling it.", cd->fullfilename, st->id, dimension?dimension:"<nothing>", value?value:"<nothing>");
162 + error("PLUGINSD: '%s' is requesting a SET on chart '%s', without a dimension. Disabling it.", cd->fullfilename, st->id);
163 cd->enabled = 0;
164 killpid(cd->pid, SIGTERM);
165 break;
166 }
167
165 - if(unlikely(!value || !*value)) value = "0";
168 + if(unlikely(!value || !*value)) value = NULL;
169
170 if(unlikely(!st)) {
168 - error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value);
171 + error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value?value:"<nothing>");
172 cd->enabled = 0;
173 killpid(cd->pid, SIGTERM);
174 break;
175 }
176
174 - if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value);
175 - rrddim_set(st, dimension, atoll(value));
177 + if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value?value:"<nothing>");
178 +
179 + if(value) rrddim_set(st, dimension, atoll(value));
180
181 count++;
182 }
@@ -404,14 +408,14 @@ void *pluginsd_main(void *ptr)
408 error("Cannot set pthread cancel state to ENABLE.");
409
410 char *dir_name = config_get("plugins", "plugins directory", PLUGINS_DIR);
407 - int automatic_run = config_get_boolean("plugins", "enable running new plugins", 0);
411 + int automatic_run = config_get_boolean("plugins", "enable running new plugins", 1);
412 int scan_frequency = config_get_number("plugins", "check for new plugins every", 60);
413 DIR *dir = NULL;
414 struct dirent *file = NULL;
415 struct plugind *cd;
416
417 // enable the apps plugin by default
414 - config_get_boolean("plugins", "apps", 1);
418 + // config_get_boolean("plugins", "apps", 1);
419
420 if(scan_frequency < 1) scan_frequency = 1;
421
@@ -480,11 +484,11 @@ void *pluginsd_main(void *ptr)
484
485 // spawn a new thread for it
486 if(unlikely(pthread_create(&cd->thread, NULL, pluginsd_worker_thread, cd) != 0)) {
483 - error("CHARTS.D: failed to create new thread for chart.d %s.", cd->filename);
487 + error("PLUGINSD: failed to create new thread for plugin '%s'.", cd->filename);
488 cd->obsolete = 1;
489 }
490 else if(unlikely(pthread_detach(cd->thread) != 0))
487 - error("CHARTS.D: Cannot request detach of newly created thread for chart.d %s.", cd->filename);
491 + error("PLUGINSD: Cannot request detach of newly created thread for plugin '%s'.", cd->filename);
492 }
493
494 closedir(dir);
web/Makefile.am
+7
@@ -11,3 +11,10 @@ dist_web_DATA = \
11 robots.txt \
12 theme.css \
13 $(NULL)
14 +
15 +install-data-hook:
16 + if [ `id -u` == 0 ]; then \
17 + getent group netdata > /dev/null || groupadd -r netdata; \
18 + getent passwd netdata > /dev/null || useradd -r -g netdata -c netdata -s /sbin/nologin -d / netdata; \
19 + chown -c -R netdata $(DESTDIR)$(cachedir) $(DESTDIR)$(webdir); \
20 + fi