remove deprecated node.d modules (#12047)
Ilya Mashchenko committed
Feb 22, 2022 at 11:44 UTC
e4ed564832e0ee4c67b4ec518796168cf0743200
34 files changed
+3
-4675
.github/CODEOWNERS
-2
@@ -21,9 +21,7 @@ collectors/freebsd.plugin/ @vlvkobal @thiagoftsm
21
collectors/ebpf.plugin/ @thiagoftsm @vlvkobal
22
collectors/macos.plugin/ @vlvkobal @thiagoftsm
23
collectors/node.d.plugin/ @jacekkolasa
24
-collectors/node.d.plugin/fronius/ @ccremer
24
collectors/node.d.plugin/snmp/ @jacekkolasa
26
-collectors/node.d.plugin/stiebeleltron/ @ccremer
25
collectors/python.d.plugin/ @ilyam8
26
collectors/cups.plugin/ @simonnagl @vlvkobal @thiagoftsm
27
exporting/ @vlvkobal @thiagoftsm
collectors/COLLECTORS.md
-7
@@ -219,8 +219,6 @@ configure any of these collectors according to your setup and infrastructure.
219
accounting statistics from the `status server` using the `radclient` tool.
220
- [Libreswan](/collectors/charts.d.plugin/libreswan/README.md): Collect bytes-in, bytes-out, and uptime metrics.
221
- [Icecast](/collectors/python.d.plugin/icecast/README.md): Monitor the number of listeners for active sources.
222
-- [ISC BIND](/collectors/node.d.plugin/named/README.md): Collect nameserver summary performance statistics via a web
223
- interface (`statistics-channels` feature).
222
- [ISC Bind (RDNC)](/collectors/python.d.plugin/bind_rndc/README.md): Collect nameserver summary performance
223
statistics using the `rndc` tool.
224
- [ISC DHCP (Go)](https://learn.netdata.cloud/docs/agent/collectors/go.d.plugin/modules/isc_dhcpd): Reads a
@@ -267,13 +265,8 @@ configure any of these collectors according to your setup and infrastructure.
265
blockchain indexes, memory usage, network usage, and transactions of wallet instances.
266
- [Energi Core (Python)](/collectors/python.d.plugin/energid/README.md): Monitor blockchain, memory, network, and
267
unspent transactions statistics.
270
-- [Fronius Symo](/collectors/node.d.plugin/fronius/README.md): Collect power, consumption, autonomy, energy, and inverter
271
- statistics.
268
- [UPS/PDU](/collectors/charts.d.plugin/nut/README.md): Read the status of UPS/PDU devices using the `upsc` tool.
273
-- [SMA Sunny WebBox](/collectors/node.d.plugin/sma_webbox/README.md): Collect power statistics.
269
- [SNMP devices](/collectors/node.d.plugin/snmp/README.md): Gather data using the SNMP protocol.
275
-- [Stiebel Eltron ISG](/collectors/node.d.plugin/stiebeleltron/README.md): Collect metrics from heat pump and hot
276
- water installations.
270
- [1-Wire sensors](/collectors/python.d.plugin/w1sensor/README.md): Monitor sensor temperature.
271
272
### Search
collectors/node.d.plugin/Makefile.am
-4
@@ -36,11 +36,7 @@ dist_nodeconfig_DATA = \
36
dist_node_DATA = \
37
$(NULL)
38
39
-include fronius/Makefile.inc
40
-include named/Makefile.inc
41
-include sma_webbox/Makefile.inc
39
include snmp/Makefile.inc
43
-include stiebeleltron/Makefile.inc
40
41
nodemodulesdir=$(nodedir)/node_modules
42
dist_nodemodules_DATA = \
collectors/node.d.plugin/fronius/Makefile.inc
deleted
-13
@@ -1,13 +0,0 @@
1
-# SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-# THIS IS NOT A COMPLETE Makefile
4
-# IT IS INCLUDED BY ITS PARENT'S Makefile.am
5
-# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT
6
-
7
-# install these files
8
-dist_node_DATA += fronius/fronius.node.js
9
-# dist_nodeconfig_DATA += fronius/fronius.conf
10
-
11
-# do not install these files, but include them in the distribution
12
-dist_noinst_DATA += fronius/README.md fronius/Makefile.inc
13
-
collectors/node.d.plugin/fronius/README.md
deleted
-135
@@ -1,135 +0,0 @@
1
-<!--
2
-title: "Fronius Symo monitoring with Netdata"
3
-custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/fronius/README.md
4
-sidebar_label: "Fronius Symo"
5
--->
6
-
7
-# Fronius Symo monitoring with Netdata
8
-
9
-Collects metrics from the configured solar power installation from Fronius Symo.
10
-
11
-**Requirements**
12
-
13
-- Configuration file `fronius.conf` in the node.d Netdata config dir (default: `/etc/netdata/node.d/fronius.conf`)
14
-- Fronius Symo with network access (http)
15
-
16
-It produces per server:
17
-
18
-1. **Power**
19
-
20
-- Current power input from the grid (positive values), output to the grid (negative values), in W
21
-- Current power input from the solar panels, in W
22
-- Current power stored in the accumulator (if present), in W (in theory, untested)
23
-
24
-2. **Consumption**
25
-
26
-- Local consumption in W
27
-
28
-3. **Autonomy**
29
-
30
-- Relative autonomy in %. 100 % autonomy means that the solar panels are delivering more power than it is needed by local consumption.
31
-- Relative self consumption in %. The lower the better
32
-
33
-4. **Energy**
34
-
35
-- The energy produced during the current day, in kWh
36
-- The energy produced during the current year, in kWh
37
-
38
-5. **Inverter**
39
-
40
-- The current power output from the connected inverters, in W, one dimension per inverter. At least one is always present.
41
-
42
-## configuration
43
-
44
-Sample:
45
-
46
-```json
47
-{
48
- "enable_autodetect": false,
49
- "update_every": 5,
50
- "servers": [
51
- {
52
- "name": "Symo",
53
- "hostname": "symo.ip.or.dns",
54
- "update_every": 5,
55
- "api_path": "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"
56
- }
57
- ]
58
-}
59
-```
60
-
61
-If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `5`.
62
-
63
----
64
-
65
-[Fronius Symo 8.2](https://www.fronius.com/en/photovoltaics/products/all-products/inverters/fronius-symo/fronius-symo-8-2-3-m)
66
-
67
-The plugin has been tested with a single inverter, namely Fronius Symo 8.2-3-M:
68
-
69
-- Datalogger version: 240.162630
70
-- Software version: 3.7.4-6
71
-- Hardware version: 2.4D
72
-
73
-Other products and versions may work, but without any guarantees.
74
-
75
-Example Netdata configuration for node.d/fronius.conf. Copy this section to fronius.conf and change name/ip.
76
-The module supports any number of servers. Sometimes there is a lag when collecting every 3 seconds, so 5 should be okay too. You can modify this per server.
77
-
78
-```json
79
-{
80
- "enable_autodetect": false,
81
- "update_every": 5,
82
- "servers": [
83
- {
84
- "name": "solar",
85
- "hostname": "symo.ip.or.dns",
86
- "update_every": 5,
87
- "api_path": "/solar_api/v1/GetPowerFlowRealtimeData.fcgi"
88
- }
89
- ]
90
-}
91
-```
92
-
93
-The output of /solar_api/v1/GetPowerFlowRealtimeData.fcgi looks like this:
94
-
95
-```json
96
-{
97
- "Head" : {
98
- "RequestArguments" : {},
99
- "Status" : {
100
- "Code" : 0,
101
- "Reason" : "",
102
- "UserMessage" : ""
103
- },
104
- "Timestamp" : "2017-07-05T12:35:12+02:00"
105
- },
106
- "Body" : {
107
- "Data" : {
108
- "Site" : {
109
- "Mode" : "meter",
110
- "P_Grid" : -6834.549847,
111
- "P_Load" : -1271.450153,
112
- "P_Akku" : null,
113
- "P_PV" : 8106,
114
- "rel_SelfConsumption" : 15.685297,
115
- "rel_Autonomy" : 100,
116
- "E_Day" : 35020,
117
- "E_Year" : 5826076,
118
- "E_Total" : 14788870,
119
- "Meter_Location" : "grid"
120
- },
121
- "Inverters" : {
122
- "1" : {
123
- "DT" : 123,
124
- "P" : 8106,
125
- "E_Day" : 35020,
126
- "E_Year" : 5826076,
127
- "E_Total" : 14788870
128
- }
129
- }
130
- }
131
- }
132
-}
133
-```
134
-
135
-
collectors/node.d.plugin/fronius/fronius.node.js
deleted
-400
@@ -1,400 +0,0 @@
1
-"use strict";
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-// This program will connect to one or more Fronius Symo Inverters.
5
-// to get the Solar Power Generated (current, today).
6
-
7
-// example configuration in netdata/conf.d/node.d/fronius.conf.md
8
-
9
-require("url");
10
-require("http");
11
-var netdata = require("netdata");
12
-
13
-netdata.debug("loaded " + __filename + " plugin");
14
-
15
-var fronius = {
16
- name: "Fronius",
17
- enable_autodetect: false,
18
- update_every: 5,
19
- base_priority: 60000,
20
- charts: {},
21
-
22
- powerGridId: "p_grid",
23
- powerPvId: "p_pv",
24
- powerAccuId: "p_akku", // not my typo! Using the ID from the AP
25
- consumptionLoadId: "p_load",
26
- autonomyId: "rel_autonomy",
27
- consumptionSelfId: "rel_selfconsumption",
28
- solarConsumptionId: "solar_consumption",
29
- energyTodayId: "e_day",
30
- energyYearId: "e_year",
31
-
32
- createBasicDimension: function (id, name, divisor) {
33
- return {
34
- id: id, // the unique id of the dimension
35
- name: name, // the name of the dimension
36
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
37
- multiplier: 1, // the multiplier
38
- divisor: divisor, // the divisor
39
- hidden: false // is hidden (boolean)
40
- };
41
- },
42
-
43
- // Gets the site power chart. Will be created if not existing.
44
- getSitePowerChart: function (service, suffix) {
45
- var id = this.getChartId(service, suffix);
46
- var chart = fronius.charts[id];
47
- if (fronius.isDefined(chart)) return chart;
48
-
49
- var dim = {};
50
- dim[fronius.powerGridId] = this.createBasicDimension(fronius.powerGridId, "grid", 1);
51
- dim[fronius.powerPvId] = this.createBasicDimension(fronius.powerPvId, "photovoltaics", 1);
52
- dim[fronius.powerAccuId] = this.createBasicDimension(fronius.powerAccuId, "accumulator", 1);
53
-
54
- chart = {
55
- id: id, // the unique id of the chart
56
- name: "", // the unique name of the chart
57
- title: service.name + " Current Site Power", // the title of the chart
58
- units: "W", // the units of the chart dimensions
59
- family: "power", // the family of the chart
60
- context: "fronius.power", // the context of the chart
61
- type: netdata.chartTypes.area, // the type of the chart
62
- priority: fronius.base_priority + 1, // the priority relative to others in the same family
63
- update_every: service.update_every, // the expected update frequency of the chart
64
- dimensions: dim
65
- };
66
- chart = service.chart(id, chart);
67
- fronius.charts[id] = chart;
68
-
69
- return chart;
70
- },
71
-
72
- // Gets the site consumption chart. Will be created if not existing.
73
- getSiteConsumptionChart: function (service, suffix) {
74
- var id = this.getChartId(service, suffix);
75
- var chart = fronius.charts[id];
76
- if (fronius.isDefined(chart)) return chart;
77
- var dim = {};
78
- dim[fronius.consumptionLoadId] = this.createBasicDimension(fronius.consumptionLoadId, "load", 1);
79
-
80
- chart = {
81
- id: id, // the unique id of the chart
82
- name: "", // the unique name of the chart
83
- title: service.name + " Current Load", // the title of the chart
84
- units: "W", // the units of the chart dimensions
85
- family: "consumption", // the family of the chart
86
- context: "fronius.consumption", // the context of the chart
87
- type: netdata.chartTypes.area, // the type of the chart
88
- priority: fronius.base_priority + 2, // the priority relative to others in the same family
89
- update_every: service.update_every, // the expected update frequency of the chart
90
- dimensions: dim
91
- };
92
- chart = service.chart(id, chart);
93
- fronius.charts[id] = chart;
94
-
95
- return chart;
96
- },
97
-
98
- // Gets the site consumption chart. Will be created if not existing.
99
- getSiteAutonomyChart: function (service, suffix) {
100
- var id = this.getChartId(service, suffix);
101
- var chart = fronius.charts[id];
102
- if (fronius.isDefined(chart)) return chart;
103
- var dim = {};
104
- dim[fronius.autonomyId] = this.createBasicDimension(fronius.autonomyId, "autonomy", 1);
105
- dim[fronius.consumptionSelfId] = this.createBasicDimension(fronius.consumptionSelfId, "self_consumption", 1);
106
- dim[fronius.solarConsumptionId] = this.createBasicDimension(fronius.solarConsumptionId, "solar_consumption", 1);
107
-
108
- chart = {
109
- id: id, // the unique id of the chart
110
- name: "", // the unique name of the chart
111
- title: service.name + " Current Autonomy", // the title of the chart
112
- units: "%", // the units of the chart dimensions
113
- family: "autonomy", // the family of the chart
114
- context: "fronius.autonomy", // the context of the chart
115
- type: netdata.chartTypes.area, // the type of the chart
116
- priority: fronius.base_priority + 3, // the priority relative to others in the same family
117
- update_every: service.update_every, // the expected update frequency of the chart
118
- dimensions: dim
119
- };
120
- chart = service.chart(id, chart);
121
- fronius.charts[id] = chart;
122
-
123
- return chart;
124
- },
125
-
126
- // Gets the site energy chart for today. Will be created if not existing.
127
- getSiteEnergyTodayChart: function (service, suffix) {
128
- var chartId = this.getChartId(service, suffix);
129
- var chart = fronius.charts[chartId];
130
- if (fronius.isDefined(chart)) return chart;
131
- var dim = {};
132
- dim[fronius.energyTodayId] = this.createBasicDimension(fronius.energyTodayId, "today", 1000);
133
- chart = {
134
- id: chartId, // the unique id of the chart
135
- name: "", // the unique name of the chart
136
- title: service.name + " Energy production for today",// the title of the chart
137
- units: "kWh", // the units of the chart dimensions
138
- family: "energy", // the family of the chart
139
- context: "fronius.energy.today", // the context of the chart
140
- type: netdata.chartTypes.area, // the type of the chart
141
- priority: fronius.base_priority + 4, // the priority relative to others in the same family
142
- update_every: service.update_every, // the expected update frequency of the chart
143
- dimensions: dim
144
- };
145
- chart = service.chart(chartId, chart);
146
- fronius.charts[chartId] = chart;
147
-
148
- return chart;
149
- },
150
-
151
- // Gets the site energy chart for today. Will be created if not existing.
152
- getSiteEnergyYearChart: function (service, suffix) {
153
- var chartId = this.getChartId(service, suffix);
154
- var chart = fronius.charts[chartId];
155
- if (fronius.isDefined(chart)) return chart;
156
- var dim = {};
157
- dim[fronius.energyYearId] = this.createBasicDimension(fronius.energyYearId, "year", 1000);
158
- chart = {
159
- id: chartId, // the unique id of the chart
160
- name: "", // the unique name of the chart
161
- title: service.name + " Energy production for this year",// the title of the chart
162
- units: "kWh", // the units of the chart dimensions
163
- family: "energy", // the family of the chart
164
- context: "fronius.energy.year", // the context of the chart
165
- type: netdata.chartTypes.area, // the type of the chart
166
- priority: fronius.base_priority + 5, // the priority relative to others in the same family
167
- update_every: service.update_every, // the expected update frequency of the chart
168
- dimensions: dim
169
- };
170
- chart = service.chart(chartId, chart);
171
- fronius.charts[chartId] = chart;
172
-
173
- return chart;
174
- },
175
-
176
- // Gets the inverter power chart. Will be created if not existing.
177
- // Needs the array of inverters in order to create a chart with all inverters as dimensions
178
- getInverterPowerChart: function (service, suffix, inverters) {
179
- var chartId = this.getChartId(service, suffix);
180
- var chart = fronius.charts[chartId];
181
- if (fronius.isDefined(chart)) return chart;
182
-
183
- var dim = {};
184
- for (var key in inverters) {
185
- if (inverters.hasOwnProperty(key)) {
186
- var name = key;
187
- if (!isNaN(key)) name = "inverter_" + key;
188
- dim[key] = this.createBasicDimension("inverter_" + key, name, 1);
189
- }
190
- }
191
-
192
- chart = {
193
- id: chartId, // the unique id of the chart
194
- name: "", // the unique name of the chart
195
- title: service.name + " Current Inverter Output",// the title of the chart
196
- units: "W", // the units of the chart dimensions
197
- family: "inverters", // the family of the chart
198
- context: "fronius.inverter.output", // the context of the chart
199
- type: netdata.chartTypes.stacked, // the type of the chart
200
- priority: fronius.base_priority + 6, // the priority relative to others in the same family
201
- update_every: service.update_every, // the expected update frequency of the chart
202
- dimensions: dim
203
- };
204
- chart = service.chart(chartId, chart);
205
- fronius.charts[chartId] = chart;
206
-
207
- return chart;
208
- },
209
-
210
- processResponse: function (service, content) {
211
- var json = fronius.convertToJson(content);
212
- if (json === null) return;
213
-
214
- // add the service
215
- service.commit();
216
-
217
- var chartDefinitions = fronius.parseCharts(service, json);
218
- var chartCount = chartDefinitions.length;
219
- while (chartCount--) {
220
- var chartObj = chartDefinitions[chartCount];
221
- service.begin(chartObj.chart);
222
- var dimCount = chartObj.dimensions.length;
223
- while (dimCount--) {
224
- var dim = chartObj.dimensions[dimCount];
225
- service.set(dim.name, dim.value);
226
- }
227
- service.end();
228
- }
229
- },
230
-
231
- parseCharts: function (service, json) {
232
- var site = json.Body.Data.Site;
233
- return [
234
- this.parsePowerChart(service, site),
235
- this.parseConsumptionChart(service, site),
236
- this.parseAutonomyChart(service, site),
237
- this.parseEnergyTodayChart(service, site),
238
- this.parseEnergyYearChart(service, site),
239
- this.parseInverterChart(service, json.Body.Data.Inverters)
240
- ];
241
- },
242
-
243
- parsePowerChart: function (service, site) {
244
- return this.getChart(this.getSitePowerChart(service, "power"),
245
- [
246
- this.getDimension(this.powerGridId, Math.round(site.P_Grid)),
247
- this.getDimension(this.powerPvId, Math.round(Math.max(site.P_PV, 0))),
248
- this.getDimension(this.powerAccuId, Math.round(site.P_Akku))
249
- ]
250
- );
251
- },
252
-
253
- parseConsumptionChart: function (service, site) {
254
- return this.getChart(this.getSiteConsumptionChart(service, "consumption"),
255
- [this.getDimension(this.consumptionLoadId, Math.round(Math.abs(site.P_Load)))]
256
- );
257
- },
258
-
259
- parseAutonomyChart: function (service, site) {
260
- var selfConsumption = site.rel_SelfConsumption;
261
- var solarConsumption = 0;
262
- var load = Math.abs(site.P_Load);
263
- var power = Math.max(site.P_PV, 0);
264
- if (power <= 0) solarConsumption = 0;
265
- else if (load >= power) solarConsumption = 100;
266
- else solarConsumption = 100 / power * load;
267
- return this.getChart(this.getSiteAutonomyChart(service, "autonomy"),
268
- [
269
- this.getDimension(this.autonomyId, Math.round(site.rel_Autonomy)),
270
- this.getDimension(this.consumptionSelfId, Math.round(selfConsumption === null ? 100 : selfConsumption)),
271
- this.getDimension(this.solarConsumptionId, Math.round(solarConsumption))
272
- ]
273
- );
274
- },
275
-
276
- parseEnergyTodayChart: function (service, site) {
277
- return this.getChart(this.getSiteEnergyTodayChart(service, "energy.today"),
278
- [this.getDimension(this.energyTodayId, Math.round(Math.max(site.E_Day, 0)))]
279
- );
280
- },
281
-
282
- parseEnergyYearChart: function (service, site) {
283
- return this.getChart(this.getSiteEnergyYearChart(service, "energy.year"),
284
- [this.getDimension(this.energyYearId, Math.round(Math.max(site.E_Year, 0)))]
285
- );
286
- },
287
-
288
- parseInverterChart: function (service, inverters) {
289
- var dimensions = [];
290
- for (var key in inverters) {
291
- if (inverters.hasOwnProperty(key)) {
292
- dimensions.push(this.getDimension(key, Math.round(inverters[key].P)));
293
- }
294
- }
295
- return this.getChart(this.getInverterPowerChart(service, "inverters.output", inverters), dimensions);
296
- },
297
-
298
- getDimension: function (name, value) {
299
- return {
300
- name: name,
301
- value: value
302
- };
303
- },
304
-
305
- getChart: function (chart, dimensions) {
306
- return {
307
- chart: chart,
308
- dimensions: dimensions
309
- };
310
- },
311
-
312
- getChartId: function (service, suffix) {
313
- return "fronius_" + service.name + "." + suffix;
314
- },
315
-
316
- convertToJson: function (httpBody) {
317
- if (httpBody === null) return null;
318
- var json = httpBody;
319
- // can't parse if it's already a json object,
320
- // the check enables easier testing if the httpBody is already valid JSON.
321
- if (typeof httpBody !== "object") {
322
- try {
323
- json = JSON.parse(httpBody);
324
- } catch (error) {
325
- netdata.error("fronius: Got a response, but it is not valid JSON. Ignoring. Error: " + error.message);
326
- return null;
327
- }
328
- }
329
- return this.isResponseValid(json) ? json : null;
330
- },
331
-
332
- // some basic validation
333
- isResponseValid: function (json) {
334
- if (this.isUndefined(json.Body)) return false;
335
- if (this.isUndefined(json.Body.Data)) return false;
336
- if (this.isUndefined(json.Body.Data.Site)) return false;
337
- return this.isDefined(json.Body.Data.Inverters);
338
- },
339
-
340
- // module.serviceExecute()
341
- // this function is called only from this module
342
- // its purpose is to prepare the request and call
343
- // netdata.serviceExecute()
344
- serviceExecute: function (name, uri, update_every) {
345
- netdata.debug(this.name + ": " + name + ": url: " + uri + ", update_every: " + update_every);
346
-
347
- var service = netdata.service({
348
- name: name,
349
- request: netdata.requestFromURL("http://" + uri),
350
- update_every: update_every,
351
- module: this
352
- });
353
- service.execute(this.processResponse);
354
- },
355
-
356
-
357
- configure: function (config) {
358
- if (fronius.isUndefined(config.servers)) return 0;
359
- var added = 0;
360
- var len = config.servers.length;
361
- while (len--) {
362
- var server = config.servers[len];
363
- if (fronius.isUndefined(server.update_every)) server.update_every = this.update_every;
364
- if (fronius.areUndefined([server.name, server.hostname, server.api_path])) continue;
365
-
366
- var url = server.hostname + server.api_path;
367
- this.serviceExecute(server.name, url, server.update_every);
368
- added++;
369
- }
370
- return added;
371
- },
372
-
373
- // module.update()
374
- // this is called repeatedly to collect data, by calling
375
- // netdata.serviceExecute()
376
- update: function (service, callback) {
377
- service.execute(function (serv, data) {
378
- service.module.processResponse(serv, data);
379
- callback();
380
- });
381
- },
382
-
383
- isUndefined: function (value) {
384
- return typeof value === "undefined";
385
- },
386
-
387
- areUndefined: function (valueArray) {
388
- var i = 0;
389
- for (i; i < valueArray.length; i++) {
390
- if (this.isUndefined(valueArray[i])) return true;
391
- }
392
- return false;
393
- },
394
-
395
- isDefined: function (value) {
396
- return typeof value !== "undefined";
397
- }
398
-};
399
-
400
-module.exports = fronius;
collectors/node.d.plugin/named/Makefile.inc
deleted
-13
@@ -1,13 +0,0 @@
1
-# SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-# THIS IS NOT A COMPLETE Makefile
4
-# IT IS INCLUDED BY ITS PARENT'S Makefile.am
5
-# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT
6
-
7
-# install these files
8
-dist_node_DATA += named/named.node.js
9
-# dist_nodeconfig_DATA += named/named.conf
10
-
11
-# do not install these files, but include them in the distribution
12
-dist_noinst_DATA += named/README.md named/Makefile.inc
13
-
collectors/node.d.plugin/named/README.md
deleted
-348
@@ -1,348 +0,0 @@
1
-<!--
2
-title: "ISC BIND monitoring with Netdata"
3
-custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/named/README.md
4
-sidebar_label: "ISC BIND"
5
--->
6
-
7
-# ISC BIND monitoring with Netdata
8
-
9
-Monitor one or more ISC Bind servers.
10
-
11
-## Example Netdata charts
12
-
13
-Depending on the number of views your bind has, you may get a large number of charts.
14
-Here this is with just one view:
15
-
16
-
17
-
18
-
19
-## How it works
20
-
21
-The plugin will execute (from within node.js) the equivalent of:
22
-
23
-```sh
24
-curl "http://localhost:8888/json/v1/server"
25
-```
26
-
27
-Here is a sample of the output this command produces.
28
-
29
-```js
30
-{
31
- "json-stats-version":"1.0",
32
- "boot-time":"2016-01-31T08:20:48Z",
33
- "config-time":"2016-01-31T09:28:03Z",
34
- "current-time":"2016-02-02T22:22:20Z",
35
- "opcodes":{
36
- "QUERY":247816,
37
- "IQUERY":0,
38
- "STATUS":0,
39
- "RESERVED3":0,
40
- "NOTIFY":0,
41
- "UPDATE":3813,
42
- "RESERVED6":0,
43
- "RESERVED7":0,
44
- "RESERVED8":0,
45
- "RESERVED9":0,
46
- "RESERVED10":0,
47
- "RESERVED11":0,
48
- "RESERVED12":0,
49
- "RESERVED13":0,
50
- "RESERVED14":0,
51
- "RESERVED15":0
52
- },
53
- "qtypes":{
54
- "A":89519,
55
- "NS":863,
56
- "CNAME":1,
57
- "SOA":1,
58
- "PTR":116779,
59
- "MX":276,
60
- "TXT":198,
61
- "AAAA":39324,
62
- "SRV":850,
63
- "ANY":5
64
- },
65
- "nsstats":{
66
- "Requestv4":251630,
67
- "ReqEdns0":1255,
68
- "ReqTSIG":3813,
69
- "ReqTCP":57,
70
- "AuthQryRej":1455,
71
- "RecQryRej":122,
72
- "Response":245918,
73
- "TruncatedResp":44,
74
- "RespEDNS0":1255,
75
- "RespTSIG":3813,
76
- "QrySuccess":205159,
77
- "QryAuthAns":119495,
78
- "QryNoauthAns":120770,
79
- "QryNxrrset":32711,
80
- "QrySERVFAIL":262,
81
- "QryNXDOMAIN":2395,
82
- "QryRecursion":40885,
83
- "QryDuplicate":5712,
84
- "QryFailure":1577,
85
- "UpdateDone":2514,
86
- "UpdateFail":1299,
87
- "UpdateBadPrereq":1276,
88
- "QryUDP":246194,
89
- "QryTCP":45,
90
- "OtherOpt":101
91
- },
92
- "views":{
93
- "local":{
94
- "resolver":{
95
- "stats":{
96
- "Queryv4":74577,
97
- "Responsev4":67032,
98
- "NXDOMAIN":601,
99
- "SERVFAIL":5,
100
- "FORMERR":7,
101
- "EDNS0Fail":7,
102
- "Truncated":3071,
103
- "Lame":4,
104
- "Retry":11826,
105
- "QueryTimeout":1838,
106
- "GlueFetchv4":6864,
107
- "GlueFetchv4Fail":30,
108
- "QryRTT10":112,
109
- "QryRTT100":42900,
110
- "QryRTT500":23275,
111
- "QryRTT800":534,
112
- "QryRTT1600":97,
113
- "QryRTT1600+":20,
114
- "BucketSize":31,
115
- "REFUSED":13
116
- },
117
- "qtypes":{
118
- "A":64931,
119
- "NS":870,
120
- "CNAME":185,
121
- "PTR":5,
122
- "MX":49,
123
- "TXT":149,
124
- "AAAA":7972,
125
- "SRV":416
126
- },
127
- "cache":{
128
- "A":40356,
129
- "NS":8032,
130
- "CNAME":14477,
131
- "PTR":2,
132
- "MX":21,
133
- "TXT":32,
134
- "AAAA":3301,
135
- "SRV":94,
136
- "DS":237,
137
- "RRSIG":2301,
138
- "NSEC":126,
139
- "!A":52,
140
- "!NS":4,
141
- "!TXT":1,
142
- "!AAAA":3797,
143
- "!SRV":9,
144
- "NXDOMAIN":590
145
- },
146
- "cachestats":{
147
- "CacheHits":1085188,
148
- "CacheMisses":109,
149
- "QueryHits":464755,
150
- "QueryMisses":55624,
151
- "DeleteLRU":0,
152
- "DeleteTTL":42615,
153
- "CacheNodes":5188,
154
- "CacheBuckets":2079,
155
- "TreeMemTotal":2326026,
156
- "TreeMemInUse":1508075,
157
- "HeapMemMax":132096,
158
- "HeapMemTotal":393216,
159
- "HeapMemInUse":132096
160
- },
161
- "adb":{
162
- "nentries":1021,
163
- "entriescnt":3157,
164
- "nnames":1021,
165
- "namescnt":3022
166
- }
167
- }
168
- },
169
- "public":{
170
- "resolver":{
171
- "stats":{
172
- "BucketSize":31
173
- },
174
- "qtypes":{
175
- },
176
- "cache":{
177
- },
178
- "cachestats":{
179
- "CacheHits":0,
180
- "CacheMisses":0,
181
- "QueryHits":0,
182
- "QueryMisses":0,
183
- "DeleteLRU":0,
184
- "DeleteTTL":0,
185
- "CacheNodes":0,
186
- "CacheBuckets":64,
187
- "TreeMemTotal":287392,
188
- "TreeMemInUse":29608,
189
- "HeapMemMax":1024,
190
- "HeapMemTotal":262144,
191
- "HeapMemInUse":1024
192
- },
193
- "adb":{
194
- "nentries":1021,
195
- "nnames":1021
196
- }
197
- }
198
- },
199
- "_bind":{
200
- "resolver":{
201
- "stats":{
202
- "BucketSize":31
203
- },
204
- "qtypes":{
205
- },
206
- "cache":{
207
- },
208
- "cachestats":{
209
- "CacheHits":0,
210
- "CacheMisses":0,
211
- "QueryHits":0,
212
- "QueryMisses":0,
213
- "DeleteLRU":0,
214
- "DeleteTTL":0,
215
- "CacheNodes":0,
216
- "CacheBuckets":64,
217
- "TreeMemTotal":287392,
218
- "TreeMemInUse":29608,
219
- "HeapMemMax":1024,
220
- "HeapMemTotal":262144,
221
- "HeapMemInUse":1024
222
- },
223
- "adb":{
224
- "nentries":1021,
225
- "nnames":1021
226
- }
227
- }
228
- }
229
- }
230
-}
231
-```
232
-
233
-From this output it collects:
234
-
235
-- Global Received Requests by IP version (IPv4, IPv6)
236
-- Global Successful Queries
237
-- Current Recursive Clients
238
-- Global Queries by IP Protocol (TCP, UDP)
239
-- Global Queries Analysis
240
-- Global Received Updates
241
-- Global Query Failures
242
-- Global Query Failures Analysis
243
-- Other Global Server Statistics
244
-- Global Incoming Requests by OpCode
245
-- Global Incoming Requests by Query Type
246
-- Global Socket Statistics (will only work if the url is `http://127.0.0.1:8888/json/v1`, i.e. without `/server`, but keep in mind this produces a very long output and probably will account for 0.5% CPU overhead alone, per bind server added)
247
-- Per View Statistics (the following set will be added for each bind view):
248
- - View, Resolver Active Queries
249
- - View, Resolver Statistics
250
- - View, Resolver Round Trip Timings
251
- - View, Requests by Query Type
252
-
253
-## Configuration
254
-
255
-The collector (optionally) reads a configuration file named `/etc/netdata/node.d/named.conf`, with the following contents:
256
-
257
-```js
258
-{
259
- "enable_autodetect": true,
260
- "update_every": 5,
261
- "servers": [
262
- {
263
- "name": "bind1",
264
- "url": "http://127.0.0.1:8888/json/v1/server",
265
- "update_every": 1
266
- },
267
- {
268
- "name": "bind2",
269
- "url": "http://10.1.2.3:8888/json/v1/server",
270
- "update_every": 2
271
- }
272
- ]
273
-}
274
-```
275
-
276
-You can add any number of bind servers.
277
-
278
-If the configuration file is missing, or the key `enable_autodetect` is `true`, the collector will also attempt to fetch `http://localhost:8888/json/v1/server` which, if successful will be added too.
279
-
280
-### XML instead of JSON, from bind
281
-
282
-The collector can also accept bind URLs that return XML output. This might required if you cannot have bind 9.10+ with JSON but you have an version of bind that supports XML statistics v3. Check [this](https://www.isc.org/blogs/bind-9-10-statistics-troubleshooting-and-zone-configuration/) for versions supported.
283
-
284
-In such cases, use a URL like this:
285
-
286
-```sh
287
-curl "http://localhost:8888/xml/v3/server"
288
-```
289
-
290
-Only `xml` and `v3` has been tested.
291
-
292
-Keep in mind though, that XML parsing is done using javascript code, which requires a triple conversion:
293
-
294
-1. from XML to JSON using a javascript XML parser (**CPU intensive**),
295
-2. which is then transformed to emulate the output of the JSON output of bind (**CPU intensive** - and yes the converted JSON from XML is different to the native JSON - even bind produces different names for various attributes),
296
-3. which is then processed to generate the data for the charts (this will happen even if bind is producing JSON).
297
-
298
-In general, expect XML parsing to be 2 to 3 times more CPU intensive than JSON.
299
-
300
-**So, if you can use the JSON output of bind, prefer it over XML**. Keep also in mind that even bind will use more CPU when generating XML instead of JSON.
301
-
302
-The XML interface of bind is not autodetected.
303
-You will have to provide the config file `/etc/netdata/node.d/named.conf`, like this:
304
-
305
-```js
306
-{
307
- "enable_autodetect": false,
308
- "update_every": 1,
309
- "servers": [
310
- {
311
- "name": "local",
312
- "url": "http://localhost:8888/xml/v3/server",
313
- "update_every": 1
314
- }
315
- ]
316
-}
317
-```
318
-
319
-Of course, you can monitor more than one bind servers. Each one can be configured with either JSON or XML output.
320
-
321
-## Auto-detection
322
-
323
-Auto-detection is controlled by `enable_autodetect` in the config file. The default is enabled, so that if the collector can connect to `http://localhost:8888/json/v1/server` to receive bind statistics, it will automatically enable it.
324
-
325
-## Bind (named) configuration
326
-
327
-To use this plugin, you have to have bind v9.10+ properly compiled to provide statistics in `JSON` format.
328
-
329
-For more information on how to get your bind installation ready, please refer to the [bind statistics channel developer comments](http://jpmens.net/2013/03/18/json-in-bind-9-s-statistics-server/) and to [bind documentation](https://ftp.isc.org/isc/bind/9.10.3/doc/arm/Bv9ARM.ch06.html#statistics) or [bind Knowledge Base article AA-01123](https://kb.isc.org/article/AA-01123/0).
330
-
331
-Normally, you will need something like this in your `named.conf`:
332
-
333
-```
334
-statistics-channels {
335
- inet 127.0.0.1 port 8888 allow { 127.0.0.1; };
336
- inet ::1 port 8888 allow { ::1; };
337
-};
338
-```
339
-
340
-(use the IPv4 or IPv6 line depending on what you are using, you can also use both)
341
-
342
-Verify it works by running the following command (the collector is written in node.js and will query your bind server directly, but if this command works, the collector should be able to work too):
343
-
344
-```sh
345
-curl "http://localhost:8888/json/v1/server"
346
-```
347
-
348
-
collectors/node.d.plugin/named/named.node.js
deleted
-610
@@ -1,610 +0,0 @@
1
-'use strict';
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-// collect statistics from bind (named) v9.10+
5
-//
6
-// bind statistics documentation at:
7
-// http://jpmens.net/2013/03/18/json-in-bind-9-s-statistics-server/
8
-// https://ftp.isc.org/isc/bind/9.10.3/doc/arm/Bv9ARM.ch06.html#statistics
9
-
10
-// example configuration in /etc/netdata/node.d/named.conf
11
-// the module supports auto-detection if bind is running at localhost
12
-
13
-/*
14
-{
15
- "enable_autodetect": true,
16
- "update_every": 5,
17
- "servers": [
18
- {
19
- "name": "bind1",
20
- "url": "http://127.0.0.1:8888/json/v1/server",
21
- "update_every": 1
22
- },
23
- {
24
- "name": "bind2",
25
- "url": "http://10.0.0.1:8888/xml/v3/server",
26
- "update_every": 2
27
- }
28
- ]
29
-}
30
-*/
31
-
32
-// the following is the bind named.conf configuration required
33
-
34
-/*
35
-statistics-channels {
36
- inet 127.0.0.1 port 8888 allow { 127.0.0.1; };
37
-};
38
-*/
39
-
40
-require('url');
41
-require('http');
42
-var XML = require('pixl-xml');
43
-var netdata = require('netdata');
44
-
45
-if(netdata.options.DEBUG === true) netdata.debug('loaded', __filename, 'plugin');
46
-
47
-var named = {
48
- name: __filename,
49
- enable_autodetect: true,
50
- update_every: 1,
51
- base_priority: 60000,
52
- charts: {},
53
-
54
- chartFromMembersCreate: function(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) {
55
- var chart = {
56
- id: id, // the unique id of the chart
57
- name: '', // the unique name of the chart
58
- title: service.name + ' ' + title_suffix, // the title of the chart
59
- units: units, // the units of the chart dimensions
60
- family: family, // the family of the chart
61
- context: context, // the context of the chart
62
- type: type, // the type of the chart
63
- priority: priority, // the priority relative to others in the same family
64
- update_every: service.update_every, // the expected update frequency of the chart
65
- dimensions: {}
66
- };
67
-
68
- var found = 0;
69
- var dims = Object.keys(obj);
70
- var len = dims.length;
71
- for(var i = 0; i < len ;i++) {
72
- var x = dims[i];
73
-
74
- if(typeof(obj[x]) !== 'undefined' && obj[x] !== 0) {
75
- found++;
76
- chart.dimensions[x] = {
77
- id: x, // the unique id of the dimension
78
- name: x, // the name of the dimension
79
- algorithm: algorithm, // the id of the netdata algorithm
80
- multiplier: multiplier, // the multiplier
81
- divisor: divisor, // the divisor
82
- hidden: false // is hidden (boolean)
83
- };
84
- }
85
- }
86
-
87
- if(!found)
88
- return null;
89
-
90
- chart = service.chart(id, chart);
91
- this.charts[id] = chart;
92
- return chart;
93
- },
94
-
95
- chartFromMembers: function(service, obj, id_suffix, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) {
96
- var id = 'named_' + service.name + '.' + id_suffix;
97
- var chart = this.charts[id];
98
- var dims, len, x, i;
99
-
100
- if(typeof chart === 'undefined') {
101
- chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor);
102
- if(chart === null) return false;
103
- }
104
- else {
105
- // check if we need to re-generate the chart
106
- dims = Object.keys(obj);
107
- len = dims.length;
108
- for(i = 0; i < len ;i++) {
109
- x = dims[i];
110
- if(typeof(chart.dimensions[x]) === 'undefined') {
111
- chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor);
112
- if(chart === null) return false;
113
- break;
114
- }
115
- }
116
- }
117
-
118
- service.begin(chart);
119
-
120
- var found = 0;
121
- dims = Object.keys(obj);
122
- len = dims.length;
123
- for(i = 0; i < len ;i++) {
124
- x = dims[i];
125
- if(typeof(chart.dimensions[x]) !== 'undefined') {
126
- found++;
127
- service.set(x, obj[x]);
128
- }
129
- }
130
-
131
- service.end();
132
-
133
- return (found > 0);
134
- },
135
-
136
- // an index to map values to different charts
137
- lookups: {
138
- nsstats: {},
139
- resolver_stats: {},
140
- numfetch: {}
141
- },
142
-
143
- // transform the XML response of bind
144
- // to the JSON response of bind
145
- xml2js: function(service, data_xml) {
146
- var d = XML.parse(data_xml);
147
- if(d === null) return null;
148
-
149
- var a, aa, alen, alen2;
150
-
151
- var data = {};
152
- var len = d.server.counters.length;
153
- while(len--) {
154
- a = d.server.counters[len];
155
- if(typeof a.counter === 'undefined') continue;
156
- if(a.type === 'opcode') a.type = 'opcodes';
157
- else if(a.type === 'qtype') a.type = 'qtypes';
158
- else if(a.type === 'nsstat') a.type = 'nsstats';
159
- aa = data[a.type] = {};
160
- alen = 0;
161
- alen2 = a.counter.length;
162
- while(alen < alen2) {
163
- aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data, 10);
164
- alen++;
165
- }
166
- }
167
-
168
- data.views = {};
169
- var vlen = d.views.view.length;
170
- while(vlen--) {
171
- var vname = d.views.view[vlen].name;
172
- data.views[vname] = { resolver: {} };
173
- len = d.views.view[vlen].counters.length;
174
- while(len--) {
175
- a = d.views.view[vlen].counters[len];
176
- if(typeof a.counter === 'undefined') continue;
177
- if(a.type === 'resstats') a.type = 'stats';
178
- else if(a.type === 'resqtype') a.type = 'qtypes';
179
- else if(a.type === 'adbstat') a.type = 'adb';
180
- aa = data.views[vname].resolver[a.type] = {};
181
- alen = 0;
182
- alen2 = a.counter.length;
183
- while(alen < alen2) {
184
- aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data, 10);
185
- alen++;
186
- }
187
- }
188
- }
189
-
190
- return data;
191
- },
192
-
193
- processResponse: function(service, data) {
194
- if(data !== null) {
195
- var r, x, look, id, chart, keys, len;
196
-
197
- // parse XML or JSON
198
- // pepending on the URL given
199
- if(service.request.path.match(/^\/xml/) !== null)
200
- r = named.xml2js(service, data);
201
- else
202
- r = JSON.parse(data);
203
-
204
- if(typeof r === 'undefined' || r === null) {
205
- service.error("Cannot parse these data: " + data.toString());
206
- return;
207
- }
208
-
209
- if(service.added !== true)
210
- service.commit();
211
-
212
- if(typeof r.nsstats !== 'undefined') {
213
- // we split the nsstats object to several others
214
- var global_requests = {}, global_requests_enable = false;
215
- var global_failures = {}, global_failures_enable = false;
216
- var global_failures_detail = {}, global_failures_detail_enable = false;
217
- var global_updates = {}, global_updates_enable = false;
218
- var protocol_queries = {}, protocol_queries_enable = false;
219
- var global_queries = {}, global_queries_enable = false;
220
- var global_queries_success = {}, global_queries_success_enable = false;
221
- var default_enable = false;
222
- var RecursClients = 0;
223
-
224
- // RecursClients is an absolute value
225
- if(typeof r.nsstats['RecursClients'] !== 'undefined') {
226
- RecursClients = r.nsstats['RecursClients'];
227
- delete r.nsstats['RecursClients'];
228
- }
229
-
230
- keys = Object.keys(r.nsstats);
231
- len = keys.length;
232
- while(len--) {
233
- x = keys[len];
234
-
235
- // we maintain an index of the values found
236
- // mapping them to objects split
237
-
238
- look = named.lookups.nsstats[x];
239
- if(typeof look === 'undefined') {
240
- // a new value, not found in the index
241
- // index it:
242
- if(x === 'Requestv4') {
243
- named.lookups.nsstats[x] = {
244
- name: 'IPv4',
245
- type: 'global_requests'
246
- };
247
- }
248
- else if(x === 'Requestv6') {
249
- named.lookups.nsstats[x] = {
250
- name: 'IPv6',
251
- type: 'global_requests'
252
- };
253
- }
254
- else if(x === 'QryFailure') {
255
- named.lookups.nsstats[x] = {
256
- name: 'failures',
257
- type: 'global_failures'
258
- };
259
- }
260
- else if(x === 'QryUDP') {
261
- named.lookups.nsstats[x] = {
262
- name: 'UDP',
263
- type: 'protocol_queries'
264
- };
265
- }
266
- else if(x === 'QryTCP') {
267
- named.lookups.nsstats[x] = {
268
- name: 'TCP',
269
- type: 'protocol_queries'
270
- };
271
- }
272
- else if(x === 'QrySuccess') {
273
- named.lookups.nsstats[x] = {
274
- name: 'queries',
275
- type: 'global_queries_success'
276
- };
277
- }
278
- else if(x.match(/QryRej$/) !== null) {
279
- named.lookups.nsstats[x] = {
280
- name: x,
281
- type: 'global_failures_detail'
282
- };
283
- }
284
- else if(x.match(/^Qry/) !== null) {
285
- named.lookups.nsstats[x] = {
286
- name: x,
287
- type: 'global_queries'
288
- };
289
- }
290
- else if(x.match(/^Update/) !== null) {
291
- named.lookups.nsstats[x] = {
292
- name: x,
293
- type: 'global_updates'
294
- };
295
- }
296
- else {
297
- // values not mapped, will remain
298
- // in the default map
299
- named.lookups.nsstats[x] = {
300
- name: x,
301
- type: 'default'
302
- };
303
- }
304
-
305
- look = named.lookups.nsstats[x];
306
- // netdata.error('lookup nsstats value: ' + x + ' >>> ' + named.lookups.nsstats[x].type);
307
- }
308
-
309
- switch(look.type) {
310
- case 'global_requests': global_requests[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_requests_enable = true; break;
311
- case 'global_queries': global_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_enable = true; break;
312
- case 'global_queries_success': global_queries_success[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_success_enable = true; break;
313
- case 'global_updates': global_updates[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_updates_enable = true; break;
314
- case 'protocol_queries': protocol_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; protocol_queries_enable = true; break;
315
- case 'global_failures': global_failures[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_enable = true; break;
316
- case 'global_failures_detail': global_failures_detail[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_detail_enable = true; break;
317
- default: default_enable = true; break;
318
- }
319
- }
320
-
321
- if(global_requests_enable === true)
322
- service.module.chartFromMembers(service, global_requests, 'received_requests', 'Bind, Global Received Requests by IP version', 'requests/s', 'requests', 'named.requests', netdata.chartTypes.stacked, named.base_priority + 1, netdata.chartAlgorithms.incremental, 1, 1);
323
-
324
- if(global_queries_success_enable === true)
325
- service.module.chartFromMembers(service, global_queries_success, 'global_queries_success', 'Bind, Global Successful Queries', 'queries/s', 'queries', 'named.queries_success', netdata.chartTypes.line, named.base_priority + 2, netdata.chartAlgorithms.incremental, 1, 1);
326
-
327
- if(protocol_queries_enable === true)
328
- service.module.chartFromMembers(service, protocol_queries, 'protocols_queries', 'Bind, Global Queries by IP Protocol', 'queries/s', 'queries', 'named.protocol_queries', netdata.chartTypes.stacked, named.base_priority + 3, netdata.chartAlgorithms.incremental, 1, 1);
329
-
330
- if(global_queries_enable === true)
331
- service.module.chartFromMembers(service, global_queries, 'global_queries', 'Bind, Global Queries Analysis', 'queries/s', 'queries', 'named.global_queries', netdata.chartTypes.stacked, named.base_priority + 4, netdata.chartAlgorithms.incremental, 1, 1);
332
-
333
- if(global_updates_enable === true)
334
- service.module.chartFromMembers(service, global_updates, 'received_updates', 'Bind, Global Received Updates', 'updates/s', 'updates', 'named.global_updates', netdata.chartTypes.stacked, named.base_priority + 5, netdata.chartAlgorithms.incremental, 1, 1);
335
-
336
- if(global_failures_enable === true)
337
- service.module.chartFromMembers(service, global_failures, 'query_failures', 'Bind, Global Query Failures', 'failures/s', 'failures', 'named.global_failures', netdata.chartTypes.line, named.base_priority + 6, netdata.chartAlgorithms.incremental, 1, 1);
338
-
339
- if(global_failures_detail_enable === true)
340
- service.module.chartFromMembers(service, global_failures_detail, 'query_failures_detail', 'Bind, Global Query Failures Analysis', 'failures/s', 'failures', 'named.global_failures_detail', netdata.chartTypes.stacked, named.base_priority + 7, netdata.chartAlgorithms.incremental, 1, 1);
341
-
342
- if(default_enable === true)
343
- service.module.chartFromMembers(service, r.nsstats, 'nsstats', 'Bind, Other Global Server Statistics', 'operations/s', 'other', 'named.nsstats', netdata.chartTypes.line, named.base_priority + 8, netdata.chartAlgorithms.incremental, 1, 1);
344
-
345
- // RecursClients chart
346
- id = 'named_' + service.name + '.recursive_clients';
347
- chart = named.charts[id];
348
-
349
- if(typeof chart === 'undefined') {
350
- chart = {
351
- id: id, // the unique id of the chart
352
- name: '', // the unique name of the chart
353
- title: service.name + ' Bind, Current Recursive Clients', // the title of the chart
354
- units: 'clients', // the units of the chart dimensions
355
- family: 'clients', // the family of the chart
356
- context: 'named.recursive_clients', // the context of the chart
357
- type: netdata.chartTypes.line, // the type of the chart
358
- priority: named.base_priority + 1, // the priority relative to others in the same family
359
- update_every: service.update_every, // the expected update frequency of the chart
360
- dimensions: {
361
- 'clients': {
362
- id: 'clients', // the unique id of the dimension
363
- name: '', // the name of the dimension
364
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
365
- multiplier: 1, // the multiplier
366
- divisor: 1, // the divisor
367
- hidden: false // is hidden (boolean)
368
- }
369
- }
370
- };
371
-
372
- chart = service.chart(id, chart);
373
- named.charts[id] = chart;
374
- }
375
-
376
- service.begin(chart);
377
- service.set('clients', RecursClients);
378
- service.end();
379
- }
380
-
381
- if(typeof r.opcodes !== 'undefined')
382
- service.module.chartFromMembers(service, r.opcodes, 'in_opcodes', 'Bind, Global Incoming Requests by OpCode', 'requests/s', 'requests', 'named.in_opcodes', netdata.chartTypes.stacked, named.base_priority + 9, netdata.chartAlgorithms.incremental, 1, 1);
383
-
384
- if(typeof r.qtypes !== 'undefined')
385
- service.module.chartFromMembers(service, r.qtypes, 'in_qtypes', 'Bind, Global Incoming Requests by Query Type', 'requests/s', 'requests', 'named.in_qtypes', netdata.chartTypes.stacked, named.base_priority + 10, netdata.chartAlgorithms.incremental, 1, 1);
386
-
387
- if(typeof r.sockstats !== 'undefined')
388
- service.module.chartFromMembers(service, r.sockstats, 'in_sockstats', 'Bind, Global Socket Statistics', 'operations/s', 'sockets', 'named.in_sockstats', netdata.chartTypes.line, named.base_priority + 11, netdata.chartAlgorithms.incremental, 1, 1);
389
-
390
- if(typeof r.views !== 'undefined') {
391
- keys = Object.keys(r.views);
392
- len = keys.length;
393
- while(len--) {
394
- x = keys[len];
395
- var resolver = r.views[x].resolver;
396
-
397
- if(typeof resolver !== 'undefined') {
398
- if(typeof resolver.stats !== 'undefined') {
399
- var NumFetch = 0;
400
- var key = service.name + '.' + x;
401
- var rtt = {}, rtt_enable = false;
402
- default_enable = false;
403
-
404
- // NumFetch is an absolute value
405
- if(typeof resolver.stats['NumFetch'] !== 'undefined') {
406
- named.lookups.numfetch[key] = true;
407
- NumFetch = resolver.stats['NumFetch'];
408
- delete resolver.stats['NumFetch'];
409
- }
410
- if(typeof resolver.stats['BucketSize'] !== 'undefined') {
411
- delete resolver.stats['BucketSize'];
412
- }
413
-
414
- // split the QryRTT* from the main chart
415
- var ykeys = Object.keys(resolver.stats);
416
- var ylen = ykeys.length;
417
- while(ylen--) {
418
- var y = ykeys[ylen];
419
-
420
- // we maintain an index of the values found
421
- // mapping them to objects split
422
-
423
- look = named.lookups.resolver_stats[y];
424
- if(typeof look === 'undefined') {
425
- if(y.match(/^QryRTT/) !== null) {
426
- named.lookups.resolver_stats[y] = {
427
- name: y,
428
- type: 'rtt'
429
- };
430
- }
431
- else {
432
- named.lookups.resolver_stats[y] = {
433
- name: y,
434
- type: 'default'
435
- };
436
- }
437
-
438
- look = named.lookups.resolver_stats[y];
439
- // netdata.error('lookup resolver stats value: ' + y + ' >>> ' + look.type);
440
- }
441
-
442
- switch(look.type) {
443
- case 'rtt': rtt[look.name] = resolver.stats[y]; delete resolver.stats[y]; rtt_enable = true; break;
444
- default: default_enable = true; break;
445
- }
446
- }
447
-
448
- if(rtt_enable)
449
- service.module.chartFromMembers(service, rtt, 'view_resolver_rtt_' + x, 'Bind, ' + x + ' View, Resolver Round Trip Timings', 'queries/s', 'view_' + x, 'named.resolver_rtt', netdata.chartTypes.stacked, named.base_priority + 12, netdata.chartAlgorithms.incremental, 1, 1);
450
-
451
- if(default_enable)
452
- service.module.chartFromMembers(service, resolver.stats, 'view_resolver_stats_' + x, 'Bind, ' + x + ' View, Resolver Statistics', 'operations/s', 'view_' + x, 'named.resolver_stats', netdata.chartTypes.line, named.base_priority + 13, netdata.chartAlgorithms.incremental, 1, 1);
453
-
454
- // NumFetch chart
455
- if(typeof named.lookups.numfetch[key] !== 'undefined') {
456
- id = 'named_' + service.name + '.view_resolver_numfetch_' + x;
457
- chart = named.charts[id];
458
-
459
- if(typeof chart === 'undefined') {
460
- chart = {
461
- id: id, // the unique id of the chart
462
- name: '', // the unique name of the chart
463
- title: service.name + ' Bind, ' + x + ' View, Resolver Active Queries', // the title of the chart
464
- units: 'queries', // the units of the chart dimensions
465
- family: 'view_' + x, // the family of the chart
466
- context: 'named.resolver_active_queries', // the context of the chart
467
- type: netdata.chartTypes.line, // the type of the chart
468
- priority: named.base_priority + 1001, // the priority relative to others in the same family
469
- update_every: service.update_every, // the expected update frequency of the chart
470
- dimensions: {
471
- 'queries': {
472
- id: 'queries', // the unique id of the dimension
473
- name: '', // the name of the dimension
474
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
475
- multiplier: 1, // the multiplier
476
- divisor: 1, // the divisor
477
- hidden: false // is hidden (boolean)
478
- }
479
- }
480
- };
481
-
482
- chart = service.chart(id, chart);
483
- named.charts[id] = chart;
484
- }
485
-
486
- service.begin(chart);
487
- service.set('queries', NumFetch);
488
- service.end();
489
- }
490
- }
491
- }
492
-
493
- if(typeof resolver.qtypes !== 'undefined')
494
- service.module.chartFromMembers(service, resolver.qtypes, 'view_resolver_qtypes_' + x, 'Bind, ' + x + ' View, Requests by Query Type', 'requests/s', 'view_' + x, 'named.resolver_qtypes', netdata.chartTypes.stacked, named.base_priority + 14, netdata.chartAlgorithms.incremental, 1, 1);
495
-
496
- //if(typeof resolver.cache !== 'undefined')
497
- // service.module.chartFromMembers(service, resolver.cache, 'view_resolver_cache_' + x, 'Bind, ' + x + ' View, Cache Entries', 'entries', 'view_' + x, 'named.resolver_cache', netdata.chartTypes.stacked, named.base_priority + 15, netdata.chartAlgorithms.absolute, 1, 1);
498
-
499
- if(typeof resolver.cachestats['CacheHits'] !== 'undefined' && resolver.cachestats['CacheHits'] > 0) {
500
- id = 'named_' + service.name + '.view_resolver_cachehits_' + x;
501
- chart = named.charts[id];
502
-
503
- if(typeof chart === 'undefined') {
504
- chart = {
505
- id: id, // the unique id of the chart
506
- name: '', // the unique name of the chart
507
- title: service.name + ' Bind, ' + x + ' View, Resolver Cache Hits', // the title of the chart
508
- units: 'operations/s', // the units of the chart dimensions
509
- family: 'view_' + x, // the family of the chart
510
- context: 'named.resolver_cache_hits', // the context of the chart
511
- type: netdata.chartTypes.area, // the type of the chart
512
- priority: named.base_priority + 1100, // the priority relative to others in the same family
513
- update_every: service.update_every, // the expected update frequency of the chart
514
- dimensions: {
515
- 'CacheHits': {
516
- id: 'CacheHits', // the unique id of the dimension
517
- name: 'hits', // the name of the dimension
518
- algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm
519
- multiplier: 1, // the multiplier
520
- divisor: 1, // the divisor
521
- hidden: false // is hidden (boolean)
522
- },
523
- 'CacheMisses': {
524
- id: 'CacheMisses', // the unique id of the dimension
525
- name: 'misses', // the name of the dimension
526
- algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm
527
- multiplier: -1, // the multiplier
528
- divisor: 1, // the divisor
529
- hidden: false // is hidden (boolean)
530
- }
531
- }
532
- };
533
-
534
- chart = service.chart(id, chart);
535
- named.charts[id] = chart;
536
- }
537
-
538
- service.begin(chart);
539
- service.set('CacheHits', resolver.cachestats['CacheHits']);
540
- service.set('CacheMisses', resolver.cachestats['CacheMisses']);
541
- service.end();
542
- }
543
-
544
- // this is wrong, it contains many types of info:
545
- // 1. CacheHits, CacheMisses - incremental (added above)
546
- // 2. QueryHits, QueryMisses - incremental
547
- // 3. DeleteLRU, DeleteTTL - incremental
548
- // 4. CacheNodes, CacheBuckets - absolute
549
- // 5. TreeMemTotal, TreeMemInUse - absolute
550
- // 6. HeapMemMax, HeapMemTotal, HeapMemInUse - absolute
551
- //if(typeof resolver.cachestats !== 'undefined')
552
- // service.module.chartFromMembers(service, resolver.cachestats, 'view_resolver_cachestats_' + x, 'Bind, ' + x + ' View, Cache Statistics', 'requests/s', 'view_' + x, 'named.resolver_cache_stats', netdata.chartTypes.line, named.base_priority + 1001, netdata.chartAlgorithms.incremental, 1, 1);
553
-
554
- //if(typeof resolver.adb !== 'undefined')
555
- // service.module.chartFromMembers(service, resolver.adb, 'view_resolver_adb_' + x, 'Bind, ' + x + ' View, ADB Statistics', 'entries', 'view_' + x, 'named.resolver_adb', netdata.chartTypes.line, named.base_priority + 1002, netdata.chartAlgorithms.absolute, 1, 1);
556
- }
557
- }
558
- }
559
- },
560
-
561
- // module.serviceExecute()
562
- // this function is called only from this module
563
- // its purpose is to prepare the request and call
564
- // netdata.serviceExecute()
565
- serviceExecute: function(name, a_url, update_every) {
566
- if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': url: ' + a_url + ', update_every: ' + update_every);
567
- var service = netdata.service({
568
- name: name,
569
- request: netdata.requestFromURL(a_url),
570
- update_every: update_every,
571
- module: this
572
- });
573
-
574
- service.execute(this.processResponse);
575
- },
576
-
577
- configure: function(config) {
578
- var added = 0;
579
-
580
- if(this.enable_autodetect === true) {
581
- this.serviceExecute('local', 'http://localhost:8888/json/v1/server', this.update_every);
582
- added++;
583
- }
584
-
585
- if(typeof(config.servers) !== 'undefined') {
586
- var len = config.servers.length;
587
- while(len--) {
588
- if(typeof config.servers[len].update_every === 'undefined')
589
- config.servers[len].update_every = this.update_every;
590
-
591
- this.serviceExecute(config.servers[len].name, config.servers[len].url, config.servers[len].update_every);
592
- added++;
593
- }
594
- }
595
-
596
- return added;
597
- },
598
-
599
- // module.update()
600
- // this is called repeatedly to collect data, by calling
601
- // netdata.serviceExecute()
602
- update: function(service, callback) {
603
- service.execute(function(serv, data) {
604
- service.module.processResponse(serv, data);
605
- callback();
606
- });
607
- }
608
-};
609
-
610
-module.exports = named;
collectors/node.d.plugin/node.d.conf
-6
@@ -14,12 +14,6 @@
14
15
"___help_modules": "Enable/disable the following modules. Give only XXX for node.d/XXX.node.js",
16
"modules": {
17
- "named": {
18
- "enabled": true
19
- },
20
- "sma_webbox": {
21
- "enabled": true
22
- },
17
"snmp": {
18
"enabled": true
19
}
collectors/node.d.plugin/sma_webbox/Makefile.inc
deleted
-13
@@ -1,13 +0,0 @@
1
-# SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-# THIS IS NOT A COMPLETE Makefile
4
-# IT IS INCLUDED BY ITS PARENT'S Makefile.am
5
-# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT
6
-
7
-# install these files
8
-dist_node_DATA += sma_webbox/sma_webbox.node.js
9
-# dist_nodeconfig_DATA += sma_webbox/sma_webbox.conf
10
-
11
-# do not install these files, but include them in the distribution
12
-dist_noinst_DATA += sma_webbox/README.md sma_webbox/Makefile.inc
13
-
collectors/node.d.plugin/sma_webbox/README.md
deleted
-33
@@ -1,33 +0,0 @@
1
-<!--
2
-title: "SMA Sunny WebBox monitoring with Netdata"
3
-custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/sma_webbox/README.md
4
-sidebar_label: "SMA Sunny WebBox"
5
--->
6
-
7
-# SMA Sunny WebBox monitoring with Netdata
8
-
9
-Monitoring for the [SMA Sunny
10
-WebBox](https://www.sma-sunny.com/en/questions-and-answers-on-discontinuation-of-the-sunny-webbox/).
11
-
12
-The module supports any number of name servers:
13
-
14
-```json
15
-{
16
- "enable_autodetect": false,
17
- "update_every": 5,
18
- "servers": [
19
- {
20
- "name": "plant1",
21
- "hostname": "10.0.1.1",
22
- "update_every": 10
23
- },
24
- {
25
- "name": "plant2",
26
- "hostname": "10.0.2.1",
27
- "update_every": 15
28
- }
29
- ]
30
-}
31
-```
32
-
33
-
collectors/node.d.plugin/sma_webbox/sma_webbox.node.js
deleted
-239
@@ -1,239 +0,0 @@
1
-'use strict';
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-// This program will connect to one or more SMA Sunny Webboxes
5
-// to get the Solar Power Generated (current, today, total).
6
-
7
-// example configuration in /etc/netdata/node.d/sma_webbox.conf
8
-/*
9
-{
10
- "enable_autodetect": false,
11
- "update_every": 5,
12
- "servers": [
13
- {
14
- "name": "plant1",
15
- "hostname": "10.0.1.1",
16
- "update_every": 10
17
- },
18
- {
19
- "name": "plant2",
20
- "hostname": "10.0.2.1",
21
- "update_every": 15
22
- }
23
- ]
24
-}
25
-*/
26
-
27
-require('url');
28
-require('http');
29
-var netdata = require('netdata');
30
-
31
-if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin');
32
-
33
-var webbox = {
34
- name: __filename,
35
- enable_autodetect: true,
36
- update_every: 1,
37
- base_priority: 60000,
38
- charts: {},
39
-
40
- processResponse: function(service, data) {
41
- if(data !== null) {
42
- var r = JSON.parse(data);
43
-
44
- var d = {
45
- 'GriPwr': {
46
- unit: null,
47
- value: null
48
- },
49
- 'GriEgyTdy': {
50
- unit: null,
51
- value: null
52
- },
53
- 'GriEgyTot': {
54
- unit: null,
55
- value: null
56
- }
57
- };
58
-
59
- // parse the webbox response
60
- // and put it in our d object
61
- var found = 0;
62
- var len = r.result.overview.length;
63
- while(len--) {
64
- var e = r.result.overview[len];
65
- if(typeof(d[e.meta]) !== 'undefined') {
66
- found++;
67
- d[e.meta].value = e.value;
68
- d[e.meta].unit = e.unit;
69
- }
70
- }
71
-
72
- // add the service
73
- if(found > 0 && service.added !== true)
74
- service.commit();
75
-
76
-
77
- // Grid Current Power Chart
78
- if(d['GriPwr'].value !== null) {
79
- const id = 'smawebbox_' + service.name + '.current';
80
- let chart = webbox.charts[id];
81
-
82
- if(typeof chart === 'undefined') {
83
- chart = {
84
- id: id, // the unique id of the chart
85
- name: '', // the unique name of the chart
86
- title: service.name + ' Current Grid Power', // the title of the chart
87
- units: d['GriPwr'].unit, // the units of the chart dimensions
88
- family: 'now', // the family of the chart
89
- context: 'smawebbox.grid_power', // the context of the chart
90
- type: netdata.chartTypes.area, // the type of the chart
91
- priority: webbox.base_priority + 1, // the priority relative to others in the same family
92
- update_every: service.update_every, // the expected update frequency of the chart
93
- dimensions: {
94
- 'GriPwr': {
95
- id: 'GriPwr', // the unique id of the dimension
96
- name: 'power', // the name of the dimension
97
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
98
- multiplier: 1, // the multiplier
99
- divisor: 1, // the divisor
100
- hidden: false // is hidden (boolean)
101
- }
102
- }
103
- };
104
-
105
- chart = service.chart(id, chart);
106
- webbox.charts[id] = chart;
107
- }
108
-
109
- service.begin(chart);
110
- service.set('GriPwr', Math.round(d['GriPwr'].value));
111
- service.end();
112
- }
113
-
114
- if(d['GriEgyTdy'].value !== null) {
115
- const id = 'smawebbox_' + service.name + '.today';
116
- let chart = webbox.charts[id];
117
-
118
- if(typeof chart === 'undefined') {
119
- chart = {
120
- id: id, // the unique id of the chart
121
- name: '', // the unique name of the chart
122
- title: service.name + ' Today Grid Power', // the title of the chart
123
- units: d['GriEgyTdy'].unit, // the units of the chart dimensions
124
- family: 'today', // the family of the chart
125
- context: 'smawebbox.grid_power_today', // the context of the chart
126
- type: netdata.chartTypes.area, // the type of the chart
127
- priority: webbox.base_priority + 2, // the priority relative to others in the same family
128
- update_every: service.update_every, // the expected update frequency of the chart
129
- dimensions: {
130
- 'GriEgyTdy': {
131
- id: 'GriEgyTdy', // the unique id of the dimension
132
- name: 'power', // the name of the dimension
133
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
134
- multiplier: 1, // the multiplier
135
- divisor: 1000, // the divisor
136
- hidden: false // is hidden (boolean)
137
- }
138
- }
139
- };
140
-
141
- chart = service.chart(id, chart);
142
- webbox.charts[id] = chart;
143
- }
144
-
145
- service.begin(chart);
146
- service.set('GriEgyTdy', Math.round(d['GriEgyTdy'].value * 1000));
147
- service.end();
148
- }
149
-
150
- if(d['GriEgyTot'].value !== null) {
151
- const id = 'smawebbox_' + service.name + '.total';
152
- let chart = webbox.charts[id];
153
-
154
- if(typeof chart === 'undefined') {
155
- chart = {
156
- id: id, // the unique id of the chart
157
- name: '', // the unique name of the chart
158
- title: service.name + ' Total Grid Power', // the title of the chart
159
- units: d['GriEgyTot'].unit, // the units of the chart dimensions
160
- family: 'total', // the family of the chart
161
- context: 'smawebbox.grid_power_total', // the context of the chart
162
- type: netdata.chartTypes.area, // the type of the chart
163
- priority: webbox.base_priority + 3, // the priority relative to others in the same family
164
- update_every: service.update_every, // the expected update frequency of the chart
165
- dimensions: {
166
- 'GriEgyTot': {
167
- id: 'GriEgyTot', // the unique id of the dimension
168
- name: 'power', // the name of the dimension
169
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
170
- multiplier: 1, // the multiplier
171
- divisor: 1000, // the divisor
172
- hidden: false // is hidden (boolean)
173
- }
174
- }
175
- };
176
-
177
- chart = service.chart(id, chart);
178
- webbox.charts[id] = chart;
179
- }
180
-
181
- service.begin(chart);
182
- service.set('GriEgyTot', Math.round(d['GriEgyTot'].value * 1000));
183
- service.end();
184
- }
185
- }
186
- },
187
-
188
- // module.serviceExecute()
189
- // this function is called only from this module
190
- // its purpose is to prepare the request and call
191
- // netdata.serviceExecute()
192
- serviceExecute: function(name, hostname, update_every) {
193
- if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': hostname: ' + hostname + ', update_every: ' + update_every);
194
-
195
- var service = netdata.service({
196
- name: name,
197
- request: netdata.requestFromURL('http://' + hostname + '/rpc'),
198
- update_every: update_every,
199
- module: this
200
- });
201
- service.postData = 'RPC={"proc":"GetPlantOverview","format":"JSON","version":"1.0","id":"1"}';
202
- service.request.method = 'POST';
203
- service.request.headers['Content-Length'] = service.postData.length;
204
-
205
- service.execute(this.processResponse);
206
- },
207
-
208
- configure: function(config) {
209
- var added = 0;
210
-
211
- if(typeof(config.servers) !== 'undefined') {
212
- var len = config.servers.length;
213
- while(len--) {
214
- if(typeof config.servers[len].update_every === 'undefined')
215
- config.servers[len].update_every = this.update_every;
216
-
217
- if(config.servers[len].update_every < 5)
218
- config.servers[len].update_every = 5;
219
-
220
- this.serviceExecute(config.servers[len].name, config.servers[len].hostname, config.servers[len].update_every);
221
- added++;
222
- }
223
- }
224
-
225
- return added;
226
- },
227
-
228
- // module.update()
229
- // this is called repeatedly to collect data, by calling
230
- // netdata.serviceExecute()
231
- update: function(service, callback) {
232
- service.execute(function(serv, data) {
233
- service.module.processResponse(serv, data);
234
- callback();
235
- });
236
- },
237
-};
238
-
239
-module.exports = webbox;
collectors/node.d.plugin/stiebeleltron/Makefile.inc
deleted
-13
@@ -1,13 +0,0 @@
1
-# SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-# THIS IS NOT A COMPLETE Makefile
4
-# IT IS INCLUDED BY ITS PARENT'S Makefile.am
5
-# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT
6
-
7
-# install these files
8
-dist_node_DATA += stiebeleltron/stiebeleltron.node.js
9
-# dist_nodeconfig_DATA += stiebeleltron/stiebeleltron.conf
10
-
11
-# do not install these files, but include them in the distribution
12
-dist_noinst_DATA += stiebeleltron/README.md stiebeleltron/Makefile.inc
13
-
collectors/node.d.plugin/stiebeleltron/README.md
deleted
-525
@@ -1,525 +0,0 @@
1
-<!--
2
-title: "Stiebel Eltron ISG monitoring with Netdata"
3
-custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/stiebeleltron/README.md
4
-sidebar_label: "Stiebel Eltron ISG"
5
--->
6
-
7
-# Stiebel Eltron ISG monitoring with Netdata
8
-
9
-Collects metrics from the configured heat pump and hot water installation from Stiebel Eltron ISG web.
10
-
11
-**Requirements**
12
-
13
-- Configuration file `stiebeleltron.conf` in the node.d Netdata config dir (default: `/etc/netdata/node.d/stiebeleltron.conf`)
14
-- Stiebel Eltron ISG web with network access (http), without password login
15
-
16
-The charts are configurable, however, the provided default configuration collects the following:
17
-
18
-1. **General**
19
-
20
- - Outside temperature in C
21
- - Condenser temperature in C
22
- - Heating circuit pressure in bar
23
- - Flow rate in l/min
24
- - Output of water and heat pumps in %
25
-
26
-2. **Heating**
27
-
28
- - Heat circuit 1 temperature in C (set/actual)
29
- - Heat circuit 2 temperature in C (set/actual)
30
- - Flow temperature in C (set/actual)
31
- - Buffer temperature in C (set/actual)
32
- - Pre-flow temperature in C
33
-
34
-3. **Hot Water**
35
-
36
- - Hot water temperature in C (set/actual)
37
-
38
-4. **Room Temperature**
39
-
40
- - Heat circuit 1 room temperature in C (set/actual)
41
- - Heat circuit 2 room temperature in C (set/actual)
42
-
43
-5. **Electric Reheating**
44
-
45
- - Dual Mode Reheating temperature in C (hot water/heating)
46
-
47
-6. **Process Data**
48
-
49
- - Remaining compressor rest time in s
50
-
51
-7. **Runtime**
52
-
53
- - Compressor runtime hours (hot water/heating)
54
- - Reheating runtime hours (reheating 1/reheating 2)
55
-
56
-8. **Energy**
57
-
58
- - Compressor today in kWh (hot water/heating)
59
- - Compressor Total in kWh (hot water/heating)
60
-
61
-## configuration
62
-
63
-If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `10`.
64
-
65
----
66
-
67
-[Stiebel Eltron Heat pump system with ISG](https://www.stiebel-eltron.com/en/home/products-solutions/renewables/controller_energymanagement/internet_servicegateway/isg_web.html)
68
-
69
-Original author: BrainDoctor (github)
70
-
71
-The module supports any metrics that are parsable with RegEx. There is no API that gives direct access to the values (AFAIK), so the "workaround" is to parse the HTML output of the ISG.
72
-
73
-### Testing
74
-
75
-This plugin has been tested within the following environment:
76
-
77
-- ISG version: 8.5.6
78
-- MFG version: 12
79
-- Controller version: 9
80
-- July (summer time, not much activity)
81
-- Interface language: English
82
-- login- and password-less ISG web access (without HTTPS it's useless anyway)
83
-- Heatpump model: WPL 25 I-2
84
-- Hot water boiler model: 820 WT 1
85
-
86
-So, if the language is set to english, copy the following configuration into `/etc/netdata/node.d/stiebeleltron.conf` and change the `url`s.
87
-
88
-In my case, the ISG is relatively slow with responding (at least 1s, but also up to 4s). Collecting metrics every 10s is more than enough for me.
89
-
90
-### How to update the config
91
-
92
-- The dimensions support variable digits, the default is `1`. Most of the values printed by ISG are using 1 digit, some use 2.
93
-- The dimensions also support the `multiplier` and `divisor` attributes, however the divisor gets overridden by `digits`, if specified. Default is `1`.
94
-- The test string for the regex is always the whole HTML output from the url. For each parameter you need to have a regular expression that extracts the value from the HTML source in the first capture group.
95
- Recommended: [regexr.com](https://regexr.com/) for testing and matching, [freeformatter.com](https://www.freeformatter.com/json-escape.html) for escaping the newly created regex for the JSON config.
96
-
97
-The charts are being generated using the configuration below. So if your installation is in another language or has other metrics, just adapt the structure or regexes.
98
-
99
-### Configuration template
100
-
101
-```json
102
-{
103
- "enable_autodetect": false,
104
- "update_every": 10,
105
- "pages": [
106
- {
107
- "name": "System",
108
- "id": "system",
109
- "url": "http://machine.ip.or.dns/?s=1,0",
110
- "update_every": 10,
111
- "categories": [
112
- {
113
- "id": "eletricreheating",
114
- "name": "electric reheating",
115
- "charts": [
116
- {
117
- "title": "Dual Mode Reheating Temperature",
118
- "id": "reheatingtemp",
119
- "unit": "Celsius",
120
- "type": "line",
121
- "prio": 1,
122
- "dimensions": [
123
- {
124
- "name": "Heating",
125
- "id": "dualmodeheatingtemp",
126
- "regex": "DUAL MODE TEMP HEATING<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
127
- },
128
- {
129
- "name": "Hot Water",
130
- "id" : "dualmodehotwatertemp",
131
- "regex": "DUAL MODE TEMP DHW<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
132
- }
133
- ]
134
- }
135
- ]
136
- },
137
- {
138
- "id": "roomtemp",
139
- "name": "room temperature",
140
- "charts": [
141
- {
142
- "title": "Heat Circuit 1",
143
- "id": "hc1",
144
- "unit": "Celsius",
145
- "type": "line",
146
- "prio": 1,
147
- "dimensions": [
148
- {
149
- "name": "Actual",
150
- "id": "actual",
151
- "regex": "<tr class=\"even\">\\s*<td.*>ACTUAL TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
152
- },
153
- {
154
- "name": "Set",
155
- "id" : "set",
156
- "regex": "<tr class=\"odd\">\\s*<td.*>SET TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
157
- }
158
- ]
159
- },
160
- {
161
- "title": "Heat Circuit 2",
162
- "id": "hc2",
163
- "unit": "Celsius",
164
- "type": "line",
165
- "prio": 2,
166
- "dimensions": [
167
- {
168
- "name": "Actual",
169
- "id": "actual",
170
- "regex": "<tr class=\"even\">\\s*<td.*>ACTUAL TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
171
- },
172
- {
173
- "name": "Set",
174
- "id" : "set",
175
- "regex": "<tr class=\"odd\">\\s*<td.*>SET TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
176
- }
177
- ]
178
- }
179
- ]
180
- },
181
- {
182
- "id": "heating",
183
- "name": "heating",
184
- "charts": [
185
- {
186
- "title": "Heat Circuit 1",
187
- "id": "hc1",
188
- "unit": "Celsius",
189
- "type": "line",
190
- "prio": 1,
191
- "dimensions": [
192
- {
193
- "name": "Actual",
194
- "id": "actual",
195
- "regex": "<tr class=\"odd\">\\s*<td.*>ACTUAL TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
196
- },
197
- {
198
- "name": "Set",
199
- "id" : "set",
200
- "regex": "<tr class=\"even\">\\s*<td.*>SET TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
201
- }
202
- ]
203
- },
204
- {
205
- "title": "Heat Circuit 2",
206
- "id": "hc2",
207
- "unit": "Celsius",
208
- "type": "line",
209
- "prio": 2,
210
- "dimensions": [
211
- {
212
- "name": "Actual",
213
- "id": "actual",
214
- "regex": "<tr class=\"odd\">\\s*<td.*>ACTUAL TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
215
- },
216
- {
217
- "name": "Set",
218
- "id" : "set",
219
- "regex": "<tr class=\"even\">\\s*<td.*>SET TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
220
- }
221
- ]
222
- },
223
- {
224
- "title": "Flow Temperature",
225
- "id": "flowtemp",
226
- "unit": "Celsius",
227
- "type": "line",
228
- "prio": 3,
229
- "dimensions": [
230
- {
231
- "name": "Heating",
232
- "id": "heating",
233
- "regex": "ACTUAL FLOW TEMPERATURE WP<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
234
- },
235
- {
236
- "name": "Reheating",
237
- "id" : "reheating",
238
- "regex": "ACTUAL FLOW TEMPERATURE NHZ<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
239
- }
240
- ]
241
- },
242
- {
243
- "title": "Buffer Temperature",
244
- "id": "buffertemp",
245
- "unit": "Celsius",
246
- "type": "line",
247
- "prio": 4,
248
- "dimensions": [
249
- {
250
- "name": "Actual",
251
- "id": "actual",
252
- "regex": "ACTUAL BUFFER TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
253
- },
254
- {
255
- "name": "Set",
256
- "id" : "set",
257
- "regex": "SET BUFFER TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
258
- }
259
- ]
260
- },
261
- {
262
- "title": "Fixed Temperature",
263
- "id": "fixedtemp",
264
- "unit": "Celsius",
265
- "type": "line",
266
- "prio": 5,
267
- "dimensions": [
268
- {
269
- "name": "Set",
270
- "id" : "setfixed",
271
- "regex": "SET FIXED TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
272
- }
273
- ]
274
- },
275
- {
276
- "title": "Pre-flow Temperature",
277
- "id": "preflowtemp",
278
- "unit": "Celsius",
279
- "type": "line",
280
- "prio": 6,
281
- "dimensions": [
282
- {
283
- "name": "Actual",
284
- "id": "actualreturn",
285
- "regex": "ACTUAL RETURN TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
286
- }
287
- ]
288
- }
289
- ]
290
- },
291
- {
292
- "id": "hotwater",
293
- "name": "hot water",
294
- "charts": [
295
- {
296
- "title": "Hot Water Temperature",
297
- "id": "hotwatertemp",
298
- "unit": "Celsius",
299
- "type": "line",
300
- "prio": 1,
301
- "dimensions": [
302
- {
303
- "name": "Actual",
304
- "id": "actual",
305
- "regex": "ACTUAL TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
306
- },
307
- {
308
- "name": "Set",
309
- "id" : "set",
310
- "regex": "SET TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
311
- }
312
- ]
313
- }
314
- ]
315
- },
316
- {
317
- "id": "general",
318
- "name": "general",
319
- "charts": [
320
- {
321
- "title": "Outside Temperature",
322
- "id": "outside",
323
- "unit": "Celsius",
324
- "type": "line",
325
- "prio": 1,
326
- "dimensions": [
327
- {
328
- "name": "Outside temperature",
329
- "id": "outsidetemp",
330
- "regex": "OUTSIDE TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>"
331
- }
332
- ]
333
- },
334
- {
335
- "title": "Condenser Temperature",
336
- "id": "condenser",
337
- "unit": "Celsius",
338
- "type": "line",
339
- "prio": 2,
340
- "dimensions": [
341
- {
342
- "name": "Condenser",
343
- "id": "condenser",
344
- "regex": "CONDENSER TEMP\\.<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
345
- }
346
- ]
347
- },
348
- {
349
- "title": "Heating Circuit Pressure",
350
- "id": "heatingcircuit",
351
- "unit": "bar",
352
- "type": "line",
353
- "prio": 3,
354
- "dimensions": [
355
- {
356
- "name": "Heating Circuit",
357
- "id": "heatingcircuit",
358
- "digits": 2,
359
- "regex": "PRESSURE HTG CIRC<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]*).*<\\\/td>"
360
- }
361
- ]
362
- },
363
- {
364
- "title": "Flow Rate",
365
- "id": "flowrate",
366
- "unit": "liters/min",
367
- "type": "line",
368
- "prio": 4,
369
- "dimensions": [
370
- {
371
- "name": "Flow Rate",
372
- "id": "flowrate",
373
- "digits": 2,
374
- "regex": "FLOW RATE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>"
375
- }
376
- ]
377
- },
378
- {
379
- "title": "Output",
380
- "id": "output",
381
- "unit": "%",
382
- "type": "line",
383
- "prio": 5,
384
- "dimensions": [
385
- {
386
- "name": "Heat Pump",
387
- "id": "outputheatpump",
388
- "regex": "OUTPUT HP<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*).*<\\\/td>"
389
- },
390
- {
391
- "name": "Water Pump",
392
- "id": "intpumprate",
393
- "regex": "INT PUMP RATE<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*).*<\\\/td>"
394
- }
395
- ]
396
- }
397
- ]
398
- }
399
- ]
400
- },
401
- {
402
- "name": "Heat Pump",
403
- "id": "heatpump",
404
- "url": "http://machine.ip.or.dns/?s=1,1",
405
- "update_every": 10,
406
- "categories": [
407
- {
408
- "id": "runtime",
409
- "name": "runtime",
410
- "charts": [
411
- {
412
- "title": "Compressor",
413
- "id": "compressor",
414
- "unit": "h",
415
- "type": "line",
416
- "prio": 1,
417
- "dimensions": [
418
- {
419
- "name": "Heating",
420
- "id": "heating",
421
- "regex": "RNT COMP 1 HEA<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
422
- },
423
- {
424
- "name": "Hot Water",
425
- "id" : "hotwater",
426
- "regex": "RNT COMP 1 DHW<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
427
- }
428
- ]
429
- },
430
- {
431
- "title": "Reheating",
432
- "id": "reheating",
433
- "unit": "h",
434
- "type": "line",
435
- "prio": 2,
436
- "dimensions": [
437
- {
438
- "name": "Reheating 1",
439
- "id": "rh1",
440
- "regex": "BH 1<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
441
- },
442
- {
443
- "name": "Reheating 2",
444
- "id" : "rh2",
445
- "regex": "BH 2<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
446
- }
447
- ]
448
- }
449
- ]
450
- },
451
- {
452
- "id": "processdata",
453
- "name": "process data",
454
- "charts": [
455
- {
456
- "title": "Remaining Compressor Rest Time",
457
- "id": "remaincomp",
458
- "unit": "s",
459
- "type": "line",
460
- "prio": 1,
461
- "dimensions": [
462
- {
463
- "name": "Timer",
464
- "id": "timer",
465
- "regex": "COMP DLAY CNTR<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
466
- }
467
- ]
468
- }
469
- ]
470
- },
471
- {
472
- "id": "energy",
473
- "name": "energy",
474
- "charts": [
475
- {
476
- "title": "Compressor Today",
477
- "id": "compressorday",
478
- "unit": "kWh",
479
- "type": "line",
480
- "prio": 1,
481
- "dimensions": [
482
- {
483
- "name": "Heating",
484
- "id": "heating",
485
- "digits": 3,
486
- "regex": "COMPRESSOR HEATING DAY<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
487
- },
488
- {
489
- "name": "Hot Water",
490
- "id": "hotwater",
491
- "digits": 3,
492
- "regex": "COMPRESSOR DHW DAY<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
493
- }
494
- ]
495
- },
496
- {
497
- "title": "Compressor Total",
498
- "id": "compressortotal",
499
- "unit": "MWh",
500
- "type": "line",
501
- "prio": 2,
502
- "dimensions": [
503
- {
504
- "name": "Heating",
505
- "id": "heating",
506
- "digits": 3,
507
- "regex": "COMPRESSOR HEATING TOTAL<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
508
- },
509
- {
510
- "name": "Hot Water",
511
- "id": "hotwater",
512
- "digits": 3,
513
- "regex": "COMPRESSOR DHW TOTAL<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)"
514
- }
515
- ]
516
- }
517
- ]
518
- }
519
- ]
520
- }
521
- ]
522
-}
523
-```
524
-
525
-
collectors/node.d.plugin/stiebeleltron/stiebeleltron.node.js
deleted
-197
@@ -1,197 +0,0 @@
1
-'use strict';
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-// This program will connect to one Stiebel Eltron ISG for heatpump heating
5
-// to get the heat pump metrics.
6
-
7
-// example configuration in netdata/conf.d/node.d/stiebeleltron.conf.md
8
-
9
-require("url");
10
-require("http");
11
-var netdata = require("netdata");
12
-
13
-netdata.debug("loaded " + __filename + " plugin");
14
-
15
-var stiebeleltron = {
16
- name: "Stiebel Eltron",
17
- enable_autodetect: false,
18
- update_every: 10,
19
- base_priority: 60000,
20
- charts: {},
21
- pages: {},
22
-
23
- createBasicDimension: function (id, name, multiplier, divisor) {
24
- return {
25
- id: id, // the unique id of the dimension
26
- name: name, // the name of the dimension
27
- algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm
28
- multiplier: multiplier, // the multiplier
29
- divisor: divisor, // the divisor
30
- hidden: false // is hidden (boolean)
31
- };
32
- },
33
-
34
- processResponse: function (service, html) {
35
- if (html === null) return;
36
-
37
- // add the service
38
- service.commit();
39
-
40
- var page = stiebeleltron.pages[service.name];
41
- var categories = page.categories;
42
- var categoriesCount = categories.length;
43
- while (categoriesCount--) {
44
- var context = {
45
- html: html,
46
- service: service,
47
- category: categories[categoriesCount],
48
- page: page,
49
- chartDefinition: null,
50
- dimension: null
51
- };
52
- stiebeleltron.processCategory(context);
53
-
54
- }
55
- },
56
-
57
- processCategory: function (context) {
58
- var charts = context.category.charts;
59
- var chartCount = charts.length;
60
- while (chartCount--) {
61
- context.chartDefinition = charts[chartCount];
62
- stiebeleltron.processChart(context);
63
- }
64
- },
65
-
66
- processChart: function (context) {
67
- var dimensions = context.chartDefinition.dimensions;
68
- var dimensionCount = dimensions.length;
69
- context.service.begin(stiebeleltron.getChartFromContext(context));
70
-
71
- while (dimensionCount--) {
72
- context.dimension = dimensions[dimensionCount];
73
- stiebeleltron.processDimension(context);
74
- }
75
- context.service.end();
76
- },
77
-
78
- processDimension: function (context) {
79
- var dimension = context.dimension;
80
- var match = new RegExp(dimension.regex).exec(context.html);
81
- if (match === null) return;
82
- var value = match[1].replace(",", ".");
83
- // most values have a single digit by default, which requires the values to be multiplied. can be overridden.
84
- if (stiebeleltron.isDefined(dimension.digits)) {
85
- value *= Math.pow(10, dimension.digits);
86
- } else {
87
- value *= 10;
88
- }
89
- context.service.set(stiebeleltron.getDimensionId(context), value);
90
- },
91
-
92
- getChartFromContext: function (context) {
93
- var chartId = this.getChartId(context);
94
- var chart = stiebeleltron.charts[chartId];
95
- if (stiebeleltron.isDefined(chart)) return chart;
96
-
97
- var chartDefinition = context.chartDefinition;
98
- var service = context.service;
99
- var dimensions = {};
100
-
101
- var dimCount = chartDefinition.dimensions.length;
102
- while (dimCount--) {
103
- var dim = chartDefinition.dimensions[dimCount];
104
- var multiplier = 1;
105
- var divisor = 10;
106
- if (stiebeleltron.isDefined(dim.digits)) divisor = Math.pow(10, Math.max(0, dim.digits));
107
- if (stiebeleltron.isDefined(dim.multiplier)) multiplier = dim.multiplier;
108
- if (stiebeleltron.isDefined(dim.divisor)) divisor = dim.divisor;
109
- context.dimension = dim;
110
- var dimId = this.getDimensionId(context);
111
- dimensions[dimId] = this.createBasicDimension(dimId, dim.name, multiplier, divisor);
112
- }
113
-
114
- chart = {
115
- id: chartId,
116
- name: '',
117
- title: chartDefinition.title,
118
- units: chartDefinition.unit,
119
- family: context.category.name,
120
- context: 'stiebeleltron.' + context.category.id + '.' + chartDefinition.id,
121
- type: chartDefinition.type,
122
- priority: stiebeleltron.base_priority + chartDefinition.prio,// the priority relative to others in the same family
123
- update_every: service.update_every, // the expected update frequency of the chart
124
- dimensions: dimensions
125
- };
126
- chart = service.chart(chartId, chart);
127
- stiebeleltron.charts[chartId] = chart;
128
-
129
- return chart;
130
- },
131
-
132
- // module.serviceExecute()
133
- // this function is called only from this module
134
- // its purpose is to prepare the request and call
135
- // netdata.serviceExecute()
136
- serviceExecute: function (name, uri, update_every) {
137
- netdata.debug(this.name + ': ' + name + ': url: ' + uri + ', update_every: ' + update_every);
138
-
139
- var service = netdata.service({
140
- name: name,
141
- request: netdata.requestFromURL(uri),
142
- update_every: update_every,
143
- module: this
144
- });
145
- service.execute(this.processResponse);
146
- },
147
-
148
-
149
- configure: function (config) {
150
- if (stiebeleltron.isUndefined(config.pages)) return 0;
151
- var added = 0;
152
- var pageCount = config.pages.length;
153
- while (pageCount--) {
154
- var page = config.pages[pageCount];
155
- // some validation
156
- if (stiebeleltron.isUndefined(page.categories) || page.categories.length < 1) {
157
- netdata.error("Your Stiebel Eltron config is invalid. Disabling plugin.");
158
- return 0;
159
- }
160
- if (stiebeleltron.isUndefined(page.update_every)) page.update_every = this.update_every;
161
- this.pages[page.name] = page;
162
- this.serviceExecute(page.name, page.url, page.update_every);
163
- added++;
164
- }
165
- return added;
166
- },
167
-
168
- // module.update()
169
- // this is called repeatedly to collect data, by calling
170
- // netdata.serviceExecute()
171
- update: function (service, callback) {
172
- service.execute(function (serv, data) {
173
- service.module.processResponse(serv, data);
174
- callback();
175
- });
176
- },
177
-
178
- getChartId: function (context) {
179
- return "stiebeleltron_" + context.page.id +
180
- "." + context.category.id +
181
- "." + context.chartDefinition.id;
182
- },
183
-
184
- getDimensionId: function (context) {
185
- return context.dimension.id;
186
- },
187
-
188
- isUndefined: function (value) {
189
- return typeof value === 'undefined';
190
- },
191
-
192
- isDefined: function (value) {
193
- return typeof value !== 'undefined';
194
- }
195
-};
196
-
197
-module.exports = stiebeleltron;
health/Makefile.am
-2
@@ -46,7 +46,6 @@ dist_healthconfig_DATA = \
46
health.d/fping.conf \
47
health.d/geth.conf \
48
health.d/ioping.conf \
49
- health.d/fronius.conf \
49
health.d/gearman.conf \
50
health.d/go.d.plugin.conf \
51
health.d/haproxy.conf \
@@ -77,7 +76,6 @@ dist_healthconfig_DATA = \
76
health.d/riakkv.conf \
77
health.d/scaleio.conf \
78
health.d/softnet.conf \
80
- health.d/stiebeleltron.conf \
79
health.d/synchronization.conf \
80
health.d/swap.conf \
81
health.d/systemdunits.conf \
health/QUICKSTART.md
+2
-2
@@ -52,8 +52,8 @@ Navigate to the health configuration directory to see all the available files an
52
cd /usr/lib/netdata/conf.d/health.d/
53
ls
54
adaptec_raid.conf entropy.conf memory.conf squid.conf
55
-am2320.conf fping.conf mongodb.conf stiebeleltron.conf
56
-apache.conf fronius.conf mysql.conf swap.conf
55
+am2320.conf fping.conf mongodb.conf
56
+apache.conf mysql.conf swap.conf
57
...
58
```
59
health/health.d/fronius.conf
deleted
-14
@@ -1,14 +0,0 @@
1
- template: fronius_last_collected_secs
2
- families: *
3
- on: fronius.power
4
- class: Latency
5
- type: Power Supply
6
-component: Solar
7
- calc: $now - $last_collected_t
8
- every: 10s
9
- units: seconds ago
10
- warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every))
11
- crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every))
12
- delay: down 5m multiplier 1.5 max 1h
13
- info: number of seconds since the last successful data collection
14
- to: sitemgr
health/health.d/stiebeleltron.conf
deleted
-14
@@ -1,14 +0,0 @@
1
- template: stiebeleltron_last_collected_secs
2
- families: *
3
- on: stiebeleltron.heating.hc1
4
- class: Latency
5
- type: Other
6
-component: Sensors
7
- calc: $now - $last_collected_t
8
- every: 10s
9
- units: seconds ago
10
- warn: $this > (($status >= $WARNING) ? ($update_every) : ( 5 * $update_every))
11
- crit: $this > (($status == $CRITICAL) ? ($update_every) : (60 * $update_every))
12
- delay: down 5m multiplier 1.5 max 1h
13
- info: number of seconds since the last successful data collection
14
- to: sitemgr
netdata-installer.sh
-8
@@ -1075,14 +1075,6 @@ if [ -d "${NETDATA_PREFIX}/etc/netdata" ]; then
1075
run mkdir "${NETDATA_PREFIX}/etc/netdata/node.d"
1076
fi
1077
1078
- # move the node.d config files
1079
- for x in named sma_webbox snmp; do
1080
- for y in "" ".old" ".orig"; do
1081
- if [ -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" ] && [ ! -f "${NETDATA_PREFIX}/etc/netdata/node.d/${x}.conf${y}" ]; then
1082
- run mv -f "${NETDATA_PREFIX}/etc/netdata/${x}.conf${y}" "${NETDATA_PREFIX}/etc/netdata/node.d/${x}.conf${y}"
1083
- fi
1084
- done
1085
- done
1078
fi
1079
1080
# -----------------------------------------------------------------------------
tests/Makefile.am
-10
@@ -15,16 +15,6 @@ include $(top_srcdir)/build/subst.inc
15
SUFFIXES = .in
16
17
dist_noinst_DATA = \
18
- README.md \
19
- web/lib/jasmine-jquery.js \
20
- web/easypiechart.chart.spec.js \
21
- web/easypiechart.percentage.spec.js \
22
- web/karma.conf.js \
23
- web/fixtures/easypiechart.chart.fixture1.html \
24
- node.d/fronius.chart.spec.js \
25
- node.d/fronius.parse.spec.js \
26
- node.d/fronius.process.spec.js \
27
- node.d/fronius.validation.spec.js \
18
health_mgmtapi/health-cmdapi-test.sh.in \
19
acls/acl.sh.in \
20
urls/request.sh.in \
tests/README.md
deleted
-148
@@ -1,148 +0,0 @@
1
-<!--
2
-title: "Testing"
3
-custom_edit_url: https://github.com/netdata/netdata/edit/master/tests/README.md
4
--->
5
-
6
-# Testing
7
-
8
-This readme is a manual on how to get started with unit testing on javascript and nodejs
9
-
10
-Original author: BrainDoctor (github), July 2017
11
-
12
-## Installation
13
-
14
-Tested on Linux Mint 18.2 Sara (Ubuntu/debian derivative)
15
-
16
-Make sure you are the user who is developer (permissions, except sudo ofc)
17
-
18
-```sh
19
-sudo apt-get install nodejs npm chromium-browser
20
-
21
-cd /path/to/your/netdata
22
-npm install
23
-```
24
-
25
-That should install the necessary node modules.
26
-
27
-Other browsers work too (Chrome, Firefox). However, only the Chromium Browser 59 has been tested for headless unit testing.
28
-
29
-### Versions
30
-
31
-The commands above leave me with the following versions (July 2017):
32
-
33
-- nodejs: v4.2.6
34
-- npm: 3.5.2
35
-- chromium-browser: 59.0.3071.109
36
-- WebStorm (optional): 2017.1.4
37
-
38
-## Configuration
39
-
40
-### NPM
41
-
42
-The dependencies are installed in `netdata/package.json`. If you install a new NPM module, it gets added here. Future developers just need to execute `npm install` and every dep gets added automatically.
43
-
44
-### Karma
45
-
46
-Karma configuration is in `tests/web/karma.conf.js`. Documentation is provided via comments.
47
-
48
-### WebStorm
49
-
50
-If you use the JetBrains WebStorm IDE, you can integrate the karma runtime.
51
-
52
-#### for Karma (Client side testing)
53
-
54
-Headless Chromium:
55
-
56
-1. Run > Edit Configurations
57
-2. "+" > Karma
58
-3. - Name: Karma Headless Chromium
59
- - Configuration file: /path/to/your/netdata/tests/web/karma.conf.js
60
- - Browsers to start: ChromiumHeadless
61
- - Node interpreter: /usr/bin/nodejs (MUST be absolute, NVM works too)
62
- - Karma package: /path/to/your/netdata/node_modules/karma
63
-
64
-GUI Chromium is similar:
65
-
66
-1. Run > Edit Configurations
67
-2. "+" > Karma
68
-3. - Name: Karma Chromium
69
- - Configuration file: /path/to/your/netdata/tests/web/karma.conf.js
70
- - Browsers to start: Chromium
71
- - Node interpreter: /usr/bin/nodejs (MUST be absolute, NVM works too)
72
- - Karma package: /path/to/your/netdata/node_modules/karma
73
-
74
-You may add other browsers too (comma separated). With the "Browsers to start" field you can override any settings in karma.conf.js.
75
-
76
-Also it is recommended to install WebStorm IDE Extension/Addon to Chrome/Chromium for awesome debugging.
77
-
78
-#### for node.d plugins (nodejs)
79
-
80
-1. Run > Edit Configurations
81
-2. "+" > Node.js
82
-3. - Name: Node.d plugins
83
- - Node interpreter: /usr/bin/nodejs (MUST be absolute, NVM works too)
84
- - JavaScript file: node_modules/jasmine-node/bin/jasmine-node
85
- - Application parameters: --captureExceptions tests/node.d
86
-
87
-## Running
88
-
89
-### In WebStorm
90
-
91
-#### Karma
92
-
93
-Just run the configured run configurations and they produce nice test trees:
94
-
95
-
96
-
97
-#### node.js
98
-
99
-Debugging is awesome too!
100
-
101
-
102
-### From CLI
103
-
104
-#### Karma
105
-
106
-```sh
107
-cd /path/to/your/netdata
108
-
109
-nodejs ./node_modules/karma/bin/karma start tests/web/karma.conf.js --single-run=true --browsers=ChromiumHeadless
110
-```
111
-
112
-will start the karma server, start chromium in headless mode and exit.
113
-
114
-If a test fails, it produces even a stack trace:
115
-
116
-
117
-#### Node.d plugins
118
-
119
-```sh
120
-cd /path/to/your/netdata
121
-
122
-nodejs node_modules/jasmine-node/bin/jasmine-node --captureExceptions tests/node.d
123
-```
124
-
125
-will run the tests in `tests/node.d` and produce a stacktrace too on error:
126
-
127
-
128
-### Coverage
129
-
130
-#### Karma
131
-
132
-A nice HTML is produced from Karma which shows which code paths were executed. It is located somewhere in `/path/to/your/netdata/coverage/`
133
-
134
-
135
-and
136
-
137
-
138
-#### Node.d
139
-
140
-Apparently, jasmine-node can produce a junit report with the `--junitreport` flag. But that output was not very useful. Maybe it's configurable?
141
-
142
-### CI
143
-
144
-The karma and node.d runners can be integrated in Travis (AFAIK), but that is outside my ability.
145
-
146
-Note: Karma is for browser-testing. On a build server, no GUI or browser might by available, unless browsers support headless mode.
147
-
148
-
tests/node.d/fronius.chart.spec.js
deleted
-162
@@ -1,162 +0,0 @@
1
-"use strict";
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-var netdata = require("../../node.d/node_modules/netdata");
5
-// remember: subject will be a singleton!
6
-var subject = require("../../node.d/fronius.node");
7
-
8
-var service = netdata.service({
9
- name: "chart",
10
- module: this
11
-});
12
-
13
-describe("fronius chart creation", function () {
14
-
15
- var chartPrefix = "fronius_chart.";
16
-
17
- beforeAll(function () {
18
- // change this to enable debug log
19
- netdata.options.DEBUG = false;
20
- });
21
-
22
- afterAll(function () {
23
- deleteProperties(subject.charts)
24
- });
25
-
26
- it("should return a basic chart dimension", function () {
27
- var result = subject.createBasicDimension("id", "name", 2);
28
-
29
- expect(result.divisor).toBe(2);
30
- expect(result.id).toBe("id");
31
- expect(result.algorithm).toEqual(netdata.chartAlgorithms.absolute);
32
- expect(result.multiplier).toBe(1);
33
- });
34
-
35
- it("should return the power chart definition", function () {
36
- var suffix = "power";
37
- var result = subject.getSitePowerChart(service, suffix);
38
-
39
- expect(result.id).toBe(chartPrefix + suffix);
40
- expect(result.units).toBe("W");
41
- expect(result.type).toBe(netdata.chartTypes.area);
42
- expect(result.family).toBe("power");
43
- expect(result.context).toBe("fronius.power");
44
- expect(result.dimensions[subject.powerGridId].name).toBe("grid");
45
- expect(result.dimensions[subject.powerPvId].name).toBe("photovoltaics");
46
- expect(result.dimensions[subject.powerAccuId].name).toBe("accumulator");
47
- expect(Object.keys(result.dimensions).length).toBe(3);
48
- });
49
-
50
- it("should return the consumption chart definition", function () {
51
- var suffix = "Load";
52
- var result = subject.getSiteConsumptionChart(service, suffix);
53
-
54
- expect(result.id).toBe(chartPrefix + suffix);
55
- expect(result.units).toBe("W");
56
- expect(result.type).toBe(netdata.chartTypes.area);
57
- expect(result.family).toBe("consumption");
58
- expect(result.context).toBe("fronius.consumption");
59
- expect(Object.keys(result.dimensions).length).toBe(1);
60
- expect(result.dimensions[subject.consumptionLoadId].name).toBe("load");
61
- });
62
-
63
- it("should return the autonomy chart definition", function () {
64
- var suffix = "Autonomy";
65
- var result = subject.getSiteAutonomyChart(service, suffix);
66
-
67
- expect(result.id).toBe(chartPrefix + suffix);
68
- expect(result.units).toBe("%");
69
- expect(result.type).toBe(netdata.chartTypes.area);
70
- expect(result.family).toBe("autonomy");
71
- expect(result.context).toBe("fronius.autonomy");
72
- expect(Object.keys(result.dimensions).length).toBe(3);
73
- expect(result.dimensions[subject.autonomyId].name).toBe("autonomy");
74
- expect(result.dimensions[subject.consumptionSelfId].name).toBe("self_consumption");
75
- });
76
-
77
- it("should return the energy today chart definition", function () {
78
- var suffix = "Energy today";
79
- var result = subject.getSiteEnergyTodayChart(service, suffix);
80
-
81
- expect(result.id).toBe(chartPrefix + suffix);
82
- expect(result.units).toBe("kWh");
83
- expect(result.type).toBe(netdata.chartTypes.area);
84
- expect(result.family).toBe("energy");
85
- expect(result.context).toBe("fronius.energy.today");
86
- expect(Object.keys(result.dimensions).length).toBe(1);
87
- expect(result.dimensions[subject.energyTodayId].name).toBe("today");
88
- });
89
-
90
- it("should return the energy year chart definition", function () {
91
- var suffix = "Energy year";
92
- var result = subject.getSiteEnergyYearChart(service, suffix);
93
-
94
- expect(result.id).toBe(chartPrefix + suffix);
95
- expect(result.units).toBe("kWh");
96
- expect(result.type).toBe(netdata.chartTypes.area);
97
- expect(result.family).toBe("energy");
98
- expect(result.context).toBe("fronius.energy.year");
99
- expect(Object.keys(result.dimensions).length).toBe(1);
100
- expect(result.dimensions[subject.energyYearId].name).toBe("year");
101
- });
102
-
103
- it("should return the inverter chart definition with a single numerical inverter", function () {
104
- var inverters = {
105
- "1": {}
106
- };
107
- var suffix = "numerical";
108
- var result = subject.getInverterPowerChart(service, suffix, inverters);
109
-
110
- expect(result.id).toBe(chartPrefix + suffix);
111
- expect(result.units).toBe("W");
112
- expect(result.type).toBe(netdata.chartTypes.stacked);
113
- expect(result.family).toBe("inverters");
114
- expect(result.context).toBe("fronius.inverter.output");
115
- expect(Object.keys(result.dimensions).length).toBe(1);
116
- expect(result.dimensions["1"].name).toBe("inverter_1");
117
- });
118
-
119
- it("should return the inverter chart definition with a single alphabetical inverter", function () {
120
- var key = "Cellar";
121
- var inverters = {
122
- "Cellar": {}
123
- };
124
- var suffix = "alphabetical";
125
- var result = subject.getInverterPowerChart(service, suffix, inverters);
126
-
127
- expect(result.id).toBe(chartPrefix + suffix);
128
- expect(result.units).toBe("W");
129
- expect(result.type).toBe(netdata.chartTypes.stacked);
130
- expect(result.family).toBe("inverters");
131
- expect(result.context).toBe("fronius.inverter.output");
132
- expect(Object.keys(result.dimensions).length).toBe(1);
133
- expect(result.dimensions[key].name).toBe(key);
134
- });
135
-
136
- it("should return the inverter chart definition with multiple alphanumerical inverter", function () {
137
- var alpha = "Cellar";
138
- var numerical = 1;
139
- var inverters = {
140
- "Cellar": {},
141
- "1": {}
142
- };
143
- var suffix = "alphanumerical";
144
- var result = subject.getInverterPowerChart(service, suffix, inverters);
145
-
146
- expect(result.id).toBe(chartPrefix + suffix);
147
- expect(result.units).toBe("W");
148
- expect(result.type).toBe(netdata.chartTypes.stacked);
149
- expect(result.family).toBe("inverters");
150
- expect(result.context).toBe("fronius.inverter.output");
151
- expect(Object.keys(result.dimensions).length).toBe(2);
152
- expect(result.dimensions[alpha].name).toBe(alpha);
153
- expect(result.dimensions[numerical].name).toBe("inverter_" + numerical);
154
- });
155
-
156
- it("should return the same chart definition on second call for lazy loading", function () {
157
- var first = subject.getSitePowerChart(service, "id");
158
- var second = subject.getSitePowerChart(service, "id");
159
-
160
- expect(first).toBe(second);
161
- });
162
-});
tests/node.d/fronius.parse.spec.js
deleted
-333
@@ -1,333 +0,0 @@
1
-"use strict";
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-var netdata = require("../../node.d/node_modules/netdata");
5
-// remember: subject will be a singleton!
6
-var subject = require("../../node.d/fronius.node");
7
-
8
-var service = netdata.service({
9
- name: "parse",
10
- module: this
11
-});
12
-
13
-var root = {
14
- "Body": {
15
- "Data": {
16
- "Site": {},
17
- "Inverters": {}
18
- }
19
- }
20
-};
21
-
22
-describe("fronius parsing for power chart", function () {
23
-
24
- var site = root.Body.Data.Site;
25
-
26
- afterEach(function () {
27
- deleteProperties(site);
28
- });
29
-
30
- it("should return 3000 for P_Grid when rounded", function () {
31
- site.P_Grid = 2999.501;
32
- var result = subject.parsePowerChart(service, site).dimensions[0];
33
-
34
- expect(result.name).toBe(subject.powerGridId);
35
- expect(result.value).toBe(3000);
36
- });
37
-
38
- it("should return -3000 for P_Grid", function () {
39
- site.P_Grid = -3000;
40
- var result = subject.parsePowerChart(service, site).dimensions[0];
41
-
42
- expect(result.name).toBe(subject.powerGridId);
43
- expect(result.value).toBe(-3000);
44
- });
45
-
46
- it("should return 0 for P_Grid if it is null", function () {
47
- site.P_Grid = null;
48
- var result = subject.parsePowerChart(service, site).dimensions[0];
49
-
50
- expect(result.name).toBe(subject.powerGridId);
51
- expect(result.value).toBe(0);
52
- });
53
-
54
- it("should return 0 for P_Grid if it is zero", function () {
55
- site.P_Grid = 0;
56
- var result = subject.parsePowerChart(service, site).dimensions[0];
57
-
58
- expect(result.name).toBe(subject.powerGridId);
59
- expect(result.value).toBe(0);
60
- });
61
-
62
- it("should return -100 for P_Akku", function () {
63
- // it is unclear whether negative values are possible for p_akku (couldn't test, nor any API docs found).
64
- site.P_Akku = -100;
65
- var result = subject.parsePowerChart(service, site).dimensions[2];
66
-
67
- expect(result.name).toBe(subject.powerAccuId);
68
- expect(result.value).toBe(-100);
69
- });
70
-
71
- it("should return 0 for P_Akku if it is null", function () {
72
- site.P_Akku = null;
73
- var result = subject.parsePowerChart(service, site).dimensions[2];
74
-
75
- expect(result.name).toBe(subject.powerAccuId);
76
- expect(result.value).toBe(0);
77
- });
78
-
79
- it("should return 0 for P_Akku if it is zero", function () {
80
- site.P_Akku = 0;
81
- var result = subject.parsePowerChart(service, site).dimensions[2];
82
-
83
- expect(result.name).toBe(subject.powerAccuId);
84
- expect(result.value).toBe(0);
85
- });
86
-
87
- it("should return 100 for P_PV", function () {
88
- site.P_PV = 100;
89
- var result = subject.parsePowerChart(service, site).dimensions[1];
90
-
91
- expect(result.name).toBe(subject.powerPvId);
92
- expect(result.value).toBe(100);
93
- });
94
-
95
- it("should return 0 for P_PV if it is zero", function () {
96
- site.P_PV = 0;
97
- var result = subject.parsePowerChart(service, site).dimensions[1];
98
-
99
- expect(result.name).toBe(subject.powerPvId);
100
- expect(result.value).toBe(0);
101
- });
102
-
103
- it("should return 0 for P_PV if it is null", function () {
104
- site.P_PV = null;
105
- var result = subject.parsePowerChart(service, site).dimensions[1];
106
-
107
- expect(result.name).toBe(subject.powerPvId);
108
- expect(result.value).toBe(0);
109
- });
110
-
111
- it("should return 0 for P_PV if it is negative", function () {
112
- // solar panels shouldn't consume anything, only produce.
113
- site.P_PV = -1;
114
- var result = subject.parsePowerChart(service, site).dimensions[1];
115
-
116
- expect(result.name).toBe(subject.powerPvId);
117
- expect(result.value).toBe(0);
118
- });
119
-
120
-});
121
-
122
-describe("fronius parsing for consumption", function () {
123
-
124
- var site = root.Body.Data.Site;
125
-
126
- afterEach(function () {
127
- deleteProperties(site);
128
- });
129
-
130
- it("should return 1000 for P_Load when rounded", function () {
131
- site.P_Load = 1000.499;
132
- var result = subject.parseConsumptionChart(service, site).dimensions[0];
133
-
134
- expect(result.name).toBe(subject.consumptionLoadId);
135
- expect(result.value).toBe(1000);
136
- });
137
-
138
- it("should return absolute value for P_Load when negative", function () {
139
- /*
140
- with firmware 3.7.4 it is sometimes possible that negative values are returned for P_Load,
141
- which makes absolutely no sense. There is always a device that consumes some electricity around the clock.
142
- Best we can do is to make it a positive value, since 0 also doesn't make much sense.
143
- This "workaround" seems to work, as there couldn't be any strange peaks observed during long-time testing.
144
- */
145
- site.P_Load = -50;
146
- var result = subject.parseConsumptionChart(service, site).dimensions[0];
147
-
148
- expect(result.name).toBe(subject.consumptionLoadId);
149
- expect(result.value).toBe(50);
150
- });
151
-
152
- it("should return 0 for P_Load if it is null", function () {
153
- site.P_Load = null;
154
- var result = subject.parseConsumptionChart(service, site).dimensions[0];
155
-
156
- expect(result.name).toBe(subject.consumptionLoadId);
157
- expect(result.value).toBe(0);
158
- });
159
-
160
- it("should return 0 for P_Load if it is zero", function () {
161
- site.P_Load = 0;
162
- var result = subject.parseConsumptionChart(service, site).dimensions[0];
163
-
164
- expect(result.name).toBe(subject.consumptionLoadId);
165
- expect(result.value).toBe(0);
166
- });
167
-
168
-});
169
-
170
-describe("fronius parsing for autonomy", function () {
171
-
172
- var site = root.Body.Data.Site;
173
-
174
- afterEach(function () {
175
- deleteProperties(site);
176
- });
177
-
178
- it("should return 100 for rel_Autonomy", function () {
179
- site.rel_Autonomy = 100;
180
- var result = subject.parseAutonomyChart(service, site).dimensions[0];
181
-
182
- expect(result.name).toBe(subject.autonomyId);
183
- expect(result.value).toBe(100);
184
- });
185
-
186
- it("should return 0 for rel_Autonomy if it is zero", function () {
187
- site.rel_Autonomy = 0;
188
- var result = subject.parseAutonomyChart(service, site).dimensions[0];
189
-
190
- expect(result.name).toBe(subject.autonomyId);
191
- expect(result.value).toBe(0);
192
- });
193
-
194
- it("should return 0 for rel_Autonomy if it is null", function () {
195
- site.rel_Autonomy = null;
196
- var result = subject.parseAutonomyChart(service, site).dimensions[0];
197
-
198
- expect(result.name).toBe(subject.autonomyId);
199
- expect(result.value).toBe(0);
200
- });
201
-
202
- it("should return 20 for rel_Autonomy if it is 20", function () {
203
- site.rel_Autonomy = 20.1;
204
- var result = subject.parseAutonomyChart(service, site).dimensions[0];
205
-
206
- expect(result.name).toBe(subject.autonomyId);
207
- expect(result.value).toBe(20);
208
- });
209
-
210
- it("should return 20 for rel_SelfConsumption if it is 19.5", function () {
211
- site.rel_SelfConsumption = 19.5;
212
- var result = subject.parseAutonomyChart(service, site).dimensions[1];
213
-
214
- expect(result.name).toBe(subject.consumptionSelfId);
215
- expect(result.value).toBe(20);
216
- });
217
-
218
- it("should return 100 for rel_SelfConsumption if it is null", function () {
219
- /*
220
- During testing it could be observed that the API is delivering null if the solar panels
221
- do not produce enough energy to supply the local load. But in this case it should be 100, since all
222
- the produced energy is directly consumed.
223
- */
224
- site.rel_SelfConsumption = null;
225
- var result = subject.parseAutonomyChart(service, site).dimensions[1];
226
-
227
- expect(result.name).toBe(subject.consumptionSelfId);
228
- expect(result.value).toBe(100);
229
- });
230
-
231
- it("should return 0 for rel_SelfConsumption if it is zero", function () {
232
- site.rel_SelfConsumption = 0;
233
- var result = subject.parseAutonomyChart(service, site).dimensions[1];
234
-
235
- expect(result.name).toBe(subject.consumptionSelfId);
236
- expect(result.value).toBe(0);
237
- });
238
-
239
- it("should return 0 for solarConsumption if PV is null", function () {
240
- site.P_PV = null;
241
- site.P_Load = -1000;
242
- var result = subject.parseAutonomyChart(service, site).dimensions[2];
243
-
244
- expect(result.name).toBe(subject.solarConsumptionId);
245
- expect(result.value).toBe(0);
246
- });
247
-
248
- it("should return 100 for solarConsumption if Load is higher than solar power", function () {
249
- site.P_PV = 500;
250
- site.P_Load = -1500;
251
- var result = subject.parseAutonomyChart(service, site).dimensions[2];
252
-
253
- expect(result.name).toBe(subject.solarConsumptionId);
254
- expect(result.value).toBe(100);
255
- });
256
-
257
- it("should return 50 for solarConsumption if Load is half than solar power", function () {
258
- site.P_PV = 3000;
259
- site.P_Load = -1500;
260
- var result = subject.parseAutonomyChart(service, site).dimensions[2];
261
-
262
- expect(result.name).toBe(subject.solarConsumptionId);
263
- expect(result.value).toBe(50);
264
- });
265
-});
266
-
267
-describe("fronius parsing for energy", function () {
268
-
269
- var site = root.Body.Data.Site;
270
-
271
- afterEach(function () {
272
- deleteProperties(site);
273
- });
274
-
275
- it("should return 10000 for E_Day", function () {
276
- site.E_Day = 10000;
277
- var result = subject.parseEnergyTodayChart(service, site).dimensions[0];
278
-
279
- expect(result.name).toBe(subject.energyTodayId);
280
- expect(result.value).toBe(10000);
281
- });
282
-
283
- it("should return 0 for E_Day if it is negative", function () {
284
- /*
285
- The solar panels can't produce negative energy, really. It would be a fault of the API.
286
- */
287
- site.E_Day = -0.4;
288
- var result = subject.parseEnergyTodayChart(service, site).dimensions[0];
289
-
290
- expect(result.name).toBe(subject.energyTodayId);
291
- expect(result.value).toBe(0);
292
- });
293
-
294
- it("should return 100'000 for E_Year", function () {
295
- site.E_Year = 100000.4;
296
- var result = subject.parseEnergyYearChart(service, site).dimensions[0];
297
-
298
- expect(result.name).toBe(subject.energyYearId);
299
- expect(result.value).toBe(100000);
300
- });
301
-
302
- it("should return 0 for E_Year if it is negative", function () {
303
- /*
304
- A return value of 0 only makes sense in the silvester night anyway, when the counter is being reset.
305
- A negative value is a fault from the API though. It wouldn't make sense.
306
- */
307
- site.E_Year = -1;
308
- var result = subject.parseEnergyYearChart(service, site).dimensions[0];
309
-
310
- expect(result.name).toBe(subject.energyYearId);
311
- expect(result.value).toBe(0);
312
- });
313
-});
314
-
315
-describe("fronius parsing for inverters", function () {
316
-
317
- var inverters = root.Body.Data.Inverters;
318
-
319
- afterEach(function () {
320
- deleteProperties(inverters);
321
- });
322
-
323
- it("should return 1000 for P for inverter with name", function () {
324
- inverters["cellar"] = {
325
- P: 1000
326
- };
327
- var result = subject.parseInverterChart(service, inverters).dimensions[0];
328
-
329
- expect(result.name).toBe("cellar");
330
- expect(result.value).toBe(1000);
331
- });
332
-
333
-});
tests/node.d/fronius.process.spec.js
deleted
-75
@@ -1,75 +0,0 @@
1
-"use strict";
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-var netdata = require("../../node.d/node_modules/netdata");
5
-// remember: subject will be a singleton!
6
-var subject = require("../../node.d/fronius.node");
7
-
8
-var service = netdata.service({
9
- name: "process",
10
- module: this
11
-});
12
-
13
-var exampleResponse = {
14
- "Body": {
15
- "Data": {
16
- "Site": {
17
- "Mode": "meter",
18
- "P_Grid": -3430.729923,
19
- "P_Load": -910.270077,
20
- "P_Akku": null,
21
- "P_PV": 4341,
22
- "rel_SelfConsumption": 20.969133,
23
- "rel_Autonomy": 100,
24
- "E_Day": 57230,
25
- "E_Year": 6425915.5,
26
- "E_Total": 15388710,
27
- "Meter_Location": "grid"
28
- },
29
- "Inverters": {
30
- "1": {
31
- "DT": 123,
32
- "P": 4341,
33
- "E_Day": 57230,
34
- "E_Year": 6425915.5,
35
- "E_Total": 15388710
36
- }
37
- }
38
- }
39
- }
40
-};
41
-
42
-describe("fronius main processing", function () {
43
-
44
- beforeAll(function () {
45
- // change this to enable debug log
46
- netdata.options.DEBUG = false;
47
- });
48
-
49
- beforeEach(function () {
50
- deleteProperties(subject.charts);
51
- });
52
-
53
- it("should send parsed values to netdata", function () {
54
- netdata.send = jasmine.createSpy("send");
55
-
56
- subject.processResponse(service, exampleResponse);
57
-
58
- expect(netdata.send.calls.count()).toBe(6);
59
-
60
- // check if some parsed values were sent.
61
- var powerChart = netdata.send.calls.argsFor(5)[0];
62
-
63
- expect(powerChart).toContain("SET p_grid = -3431");
64
- expect(powerChart).toContain("SET p_pv = 4341");
65
-
66
- var inverterChart = netdata.send.calls.argsFor(0)[0];
67
-
68
- expect(inverterChart).toContain("SET 1 = 4341");
69
-
70
- var autonomyChart = netdata.send.calls.argsFor(3)[0];
71
- expect(autonomyChart).toContain("SET rel_selfconsumption = 21");
72
- });
73
-
74
-
75
-});
tests/node.d/fronius.validation.spec.js
deleted
-155
@@ -1,155 +0,0 @@
1
-"use strict";
2
-// SPDX-License-Identifier: GPL-3.0-or-later
3
-
4
-var netdata = require("../../node.d/node_modules/netdata");
5
-// remember: subject will be a singleton!
6
-var subject = require("../../node.d/fronius.node");
7
-
8
-var service = netdata.service({
9
- name: "validation",
10
- module: this
11
-});
12
-
13
-describe("fronius response validation", function () {
14
-
15
- it("should do nothing if response is null", function () {
16
- netdata.send = jasmine.createSpy("send");
17
-
18
- subject.processResponse(service, null);
19
- var result = netdata.send.calls.count();
20
-
21
- expect(result).toBe(0);
22
- });
23
-
24
- it("should return null if response is null", function () {
25
- var result = subject.convertToJson(null);
26
-
27
- expect(result).toBeNull();
28
- });
29
-
30
- it("should return null and log error if response cannot be parsed", function () {
31
- netdata.error = jasmine.createSpy("error");
32
-
33
- // trailing commas are enough to create syntax exceptions
34
- var result = subject.convertToJson("{name,}");
35
-
36
- expect(result).toBeNull();
37
- expect(netdata.error.calls.count()).toBe(1);
38
- });
39
-
40
- it("should return true if response is valid", function () {
41
- var result = subject.isResponseValid({
42
- "Body": {
43
- "Data": {
44
- "Site": {
45
- "Mode": "meter"
46
- },
47
- "Inverters": {
48
- "1": {}
49
- }
50
- }
51
- }
52
- });
53
-
54
- expect(result).toBeTruthy();
55
- });
56
-
57
- it("should return false if response is missing data", function () {
58
- var result = subject.isResponseValid({
59
- "Body": {}
60
- });
61
-
62
- expect(result).toBeFalsy();
63
- });
64
-
65
- it("should return false if response is missing inverter", function () {
66
- var result = subject.isResponseValid({
67
- "Body": {
68
- "Data": {
69
- "Site": {}
70
- }
71
- }
72
- });
73
-
74
- expect(result).toBeFalsy();
75
- });
76
-
77
- it("should return false if response is missing inverter", function () {
78
- var result = subject.isResponseValid({
79
- "Body": {
80
- "Data": {
81
- "Inverters": {}
82
- }
83
- }
84
- });
85
-
86
- expect(result).toBeFalsy();
87
- });
88
-
89
-});
90
-
91
-describe("fronius configuration validation", function () {
92
-
93
- it("should return 0 if there are no servers configured", function () {
94
- var result = subject.configure({});
95
-
96
- expect(result).toBe(0);
97
- });
98
-
99
- it("should return 0 if the servers array is empty", function () {
100
- var result = subject.configure({
101
- "servers": []
102
- });
103
-
104
- expect(result).toBe(0);
105
- });
106
-
107
- it("should return 0 if there is one server configured incorrectly", function () {
108
- var result = subject.configure({
109
- "servers": [{}]
110
- });
111
-
112
- expect(result).toBe(0);
113
- });
114
-
115
- it("should return 1 if there is one server configured", function () {
116
- subject.serviceExecute = jasmine.createSpy("serviceExecute");
117
- var name = "solar1";
118
- var result = subject.configure({
119
- "servers": [{
120
- "name": name,
121
- "api_path": "/api/",
122
- "hostname": "solar1.local"
123
- }]
124
- });
125
-
126
- expect(result).toBe(1);
127
- expect(subject.serviceExecute).toHaveBeenCalledWith(name, "solar1.local/api/", 5);
128
- });
129
-
130
- it("should return 2 if there are two servers configured", function () {
131
- subject.serviceExecute = jasmine.createSpy("serviceExecute");
132
- var name1 = "solar 1";
133
- var name2 = "solar 2";
134
- var result = subject.configure({
135
- "servers": [
136
- {
137
- "name": name1,
138
- "api_path": "/",
139
- "hostname": "solar1.local"
140
- },
141
- {
142
- "name": name2,
143
- "api_path": "/",
144
- "hostname": "solar2.local",
145
- "update_every": 3
146
- }
147
- ]
148
- });
149
-
150
- expect(result).toBe(2);
151
- expect(subject.serviceExecute).toHaveBeenCalledWith(name1, "solar1.local/", 5);
152
- expect(subject.serviceExecute).toHaveBeenCalledWith(name2, "solar2.local/", 3);
153
- });
154
-
155
-});
tests/web/easypiechart.chart.spec.js
deleted
-39
@@ -1,39 +0,0 @@
1
-"use strict";
2
-
3
-
4
-// with xdescribe, this is skipped.
5
-describe("creation of easy pie charts", function () {
6
-
7
- beforeAll(function () {
8
- // karma stores the loaded files relative to "base/".
9
- // This command is needed to load HTML fixtures
10
- jasmine.getFixtures().fixturesPath = "base/tests/web/fixtures";
11
- });
12
-
13
- it("should create new chart, but it's failure is expected for demonstration purpose", function () {
14
- // arrange
15
- // Theoretically we can load some html. What about jquery? could this work?
16
- // https://stackoverflow.com/questions/5337481/spying-on-jquery-selectors-in-jasmine
17
- loadFixtures("easypiechart.chart.fixture1.html");
18
-
19
- // for easy pie chart, we can fake the data result:
20
- var data = {
21
- result: [5]
22
- };
23
- // act
24
- var result = NETDATA.easypiechartChartCreate(createState(), data);
25
- // assert
26
- expect(result).toBe(true);
27
- });
28
-
29
- function createState(min, max) {
30
- // create a fake state with only needed properties.
31
- return {
32
- tmp: {
33
- easyPieChartMin: min,
34
- easyPieChartMax: max
35
- }
36
- };
37
- }
38
-
39
-});
tests/web/easypiechart.percentage.spec.js
deleted
-142
@@ -1,142 +0,0 @@
1
-"use strict";
2
-
3
-
4
-describe("percentage calculations for easy pie charts with dynamic range", function () {
5
-
6
- it("should return positive value, if value greater than dynamic max", function () {
7
- var state = createState(null, null);
8
-
9
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 6, 2, 10);
10
-
11
- expect(result).toBe(60);
12
- });
13
-
14
- it("should return negative value, if value lesser than dynamic min", function () {
15
- var state = createState(null, null);
16
-
17
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, -6, -10, 10);
18
-
19
- expect(result).toBe(-60);
20
- });
21
-
22
- it("should return 0 if value is zero and min negative, max positive", function () {
23
- var state = createState(null, null);
24
-
25
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 0, -1, 2);
26
-
27
- expect(result).toBe(0);
28
- });
29
-
30
- it("should return 0.1 if value and min are zero and max positive", function () {
31
- var state = createState(null, null);
32
-
33
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 0, 0, 2);
34
-
35
- expect(result).toBe(0.1);
36
- });
37
-
38
- it("should return -0.1 if value is zero, max and min negative", function () {
39
- var state = createState(null, null);
40
-
41
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 0, -2, -1);
42
-
43
- expect(result).toBe(-0.1);
44
- });
45
-
46
- it("should return positive value, if max is user-defined", function () {
47
- var state = createState(null, 50);
48
-
49
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 46, -40, 50);
50
-
51
- expect(result).toBe(92);
52
- });
53
-
54
- it("should return negative value, if min is user-defined", function () {
55
- var state = createState(-50, null);
56
-
57
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, -46, -50, 40);
58
-
59
- expect(result).toBe(-92);
60
- });
61
-
62
-});
63
-
64
-describe("percentage calculations for easy pie charts with fixed range", function () {
65
-
66
- it("should return positive value, if min and max are user-defined", function () {
67
- var state = createState(40, 50);
68
-
69
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 46, 40, 50);
70
-
71
- expect(result).toBe(60);
72
- });
73
-
74
- it("should return 100 if positive min and max are user-defined, but value is greater than max", function () {
75
- var state = createState(40, 50);
76
-
77
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 60, 40, 50);
78
-
79
- expect(result).toBe(100);
80
- });
81
-
82
- it("should return 0.1 if positive min and max are user-defined, but value is smaller than min", function () {
83
- var state = createState(40, 50);
84
-
85
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 39.9, 42, 48);
86
-
87
- expect(result).toBe(0.1);
88
- });
89
-
90
- it("should return -100 if negative min and max are user-defined, but value is smaller than min", function () {
91
- var state = createState(-40, -50);
92
-
93
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, -50.1, -40, -50);
94
-
95
- expect(result).toBe(-100);
96
- });
97
-
98
- it("should return 0.1 if negative min and max are user-defined, but value is smaller than min", function () {
99
- var state = createState(-40, -50);
100
-
101
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, -50.1, -20, -45);
102
-
103
- expect(result).toBe(-100);
104
- });
105
-});
106
-
107
-describe("percentage calculations for easy pie charts with invalid input", function () {
108
-
109
- it("should return 0.1 if value undefined", function () {
110
- var state = createState(null, null);
111
-
112
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, null, 40, 50);
113
-
114
- expect(result).toBe(0.1);
115
- });
116
-
117
- it("should return positive value if min is undefined", function () {
118
- var state = createState(null, null);
119
-
120
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 1, null, 2);
121
-
122
- expect(result).toBe(50);
123
- });
124
-
125
- it("should return positive if max is undefined", function () {
126
- var state = createState(null, null);
127
-
128
- var result = NETDATA.easypiechartPercentFromValueMinMax(state, 21, 42, null);
129
-
130
- expect(result).toBe(50);
131
- });
132
-});
133
-
134
-function createState(min, max) {
135
- // create a fake state with only the needed properties.
136
- return {
137
- tmp: {
138
- easyPieChartMin: min,
139
- easyPieChartMax: max
140
- }
141
- };
142
-}
tests/web/fixtures/easypiechart.chart.fixture1.html
deleted
-6
@@ -1,6 +0,0 @@
1
-<div data-netdata="system.cpu"
2
- data-chart-library="easypiechart"
3
- data-width="5%"
4
- data-height="20"
5
- data-after="-30"
6
-></div>
\ No newline at end of file
tests/web/karma.conf.js
deleted
-110
@@ -1,110 +0,0 @@
1
-// Karma configuration
2
-// Generated on Sun Jul 16 2017 02:28:05 GMT+0200 (CEST)
3
-
4
-module.exports = function (config) {
5
- config.set({
6
-
7
- // base path that will be used to resolve all patterns (eg. files, exclude)
8
- // this path should always resolve so that "." is the "netdata" root folder.
9
- basePath: '../../',
10
-
11
- // frameworks to use
12
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
13
- frameworks: ['jasmine'],
14
-
15
-
16
- // list of files / patterns to load in the browser
17
- files: [
18
- // order matters! load jquery libraries first
19
- 'web/lib/jquery*.js',
20
- // our jasmine libs and fixtures
21
- 'tests/web/lib/*.js',
22
- 'tests/web/fixtures/*.html',
23
- // then bootstrap
24
- 'web/lib/bootstrap*.js',
25
- // then the rest
26
- 'web/lib/perfect-scrollbar*.js',
27
- 'web/lib/dygraph*.js',
28
- 'web/lib/gauge*.js',
29
- 'web/lib/morris*.js',
30
- 'web/lib/raphael*.js',
31
- 'web/lib/tableExport*.js',
32
- 'web/lib/d3*.js',
33
- 'web/lib/c3*.js',
34
- // some CSS
35
- 'web/css/*.css',
36
- 'web/dashboard.css',
37
- // our dashboard
38
- 'web/dashboard.js',
39
- // finally our test specs
40
- 'tests/web/*.spec.js',
41
- ],
42
-
43
-
44
- // list of files to exclude
45
- exclude: [],
46
-
47
-
48
- // preprocess matching files before serving them to the browser
49
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
50
- preprocessors: {
51
- 'web/dashboard.js': ['coverage']
52
- },
53
-
54
-
55
- // test results reporter to use
56
- // possible values: 'dots', 'progress'
57
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
58
- reporters: ['progress', 'coverage'],
59
-
60
- // optionally, configure the reporter
61
- coverageReporter: {
62
- type : 'html',
63
- dir : 'coverage/'
64
- },
65
-
66
- // web server port
67
- port: 9876,
68
-
69
-
70
- // enable / disable colors in the output (reporters and logs)
71
- colors: true,
72
-
73
-
74
- // level of logging
75
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
76
- logLevel: config.LOG_INFO,
77
-
78
-
79
- // enable / disable watching file and executing tests whenever any file changes
80
- autoWatch: false,
81
- // not needed with WebStorm. Just hit Alt+Shift+R to rerun.
82
-
83
- // start these browsers
84
- // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
85
- browsers: ['Chromium', 'ChromiumHeadless'],
86
-
87
- customLaunchers: {
88
- // Headless browsers could be useful for CI integration, if installed.
89
- ChromiumHeadless: {
90
- // needs Chrome/Chromium version >= 59
91
- // see https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
92
- base: "Chromium",
93
- flags: [
94
- "--headless",
95
- "--disable-gpu",
96
- // Without a remote debugging port, Chromium exits immediately.
97
- "--remote-debugging-port=9222"
98
- ]
99
- }
100
- },
101
-
102
- // Continuous Integration mode
103
- // if true, Karma captures browsers, runs the tests and exits
104
- singleRun: false,
105
-
106
- // Concurrency level
107
- // how many browser should be started simultaneous
108
- concurrency: Infinity
109
- })
110
-};
tests/web/lib/jasmine-jquery.js
deleted
-841
@@ -1,841 +0,0 @@
1
-/*!
2
- Jasmine-jQuery: a set of jQuery helpers for Jasmine tests.
3
-
4
- Version 2.1.1
5
-
6
- https://github.com/velesin/jasmine-jquery
7
-
8
- Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining
11
- a copy of this software and associated documentation files (the
12
- "Software"), to deal in the Software without restriction, including
13
- without limitation the rights to use, copy, modify, merge, publish,
14
- distribute, sublicense, and/or sell copies of the Software, and to
15
- permit persons to whom the Software is furnished to do so, subject to
16
- the following conditions:
17
-
18
- The above copyright notice and this permission notice shall be
19
- included in all copies or substantial portions of the Software.
20
-
21
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
- */
29
-
30
-(function (root, factory) {
31
- if (typeof module !== 'undefined' && module.exports && typeof exports !== 'undefined') {
32
- factory(root, root.jasmine, require('jquery'));
33
- } else {
34
- factory(root, root.jasmine, root.jQuery);
35
- }
36
-}((function() {return this; })(), function (window, jasmine, $) { "use strict";
37
-
38
- jasmine.spiedEventsKey = function (selector, eventName) {
39
- return [$(selector).selector, eventName].toString()
40
- }
41
-
42
- jasmine.getFixtures = function () {
43
- return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()
44
- }
45
-
46
- jasmine.getStyleFixtures = function () {
47
- return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()
48
- }
49
-
50
- jasmine.Fixtures = function () {
51
- this.containerId = 'jasmine-fixtures'
52
- this.fixturesCache_ = {}
53
- this.fixturesPath = 'spec/javascripts/fixtures'
54
- }
55
-
56
- jasmine.Fixtures.prototype.set = function (html) {
57
- this.cleanUp()
58
- return this.createContainer_(html)
59
- }
60
-
61
- jasmine.Fixtures.prototype.appendSet= function (html) {
62
- this.addToContainer_(html)
63
- }
64
-
65
- jasmine.Fixtures.prototype.preload = function () {
66
- this.read.apply(this, arguments)
67
- }
68
-
69
- jasmine.Fixtures.prototype.load = function () {
70
- this.cleanUp()
71
- this.createContainer_(this.read.apply(this, arguments))
72
- }
73
-
74
- jasmine.Fixtures.prototype.appendLoad = function () {
75
- this.addToContainer_(this.read.apply(this, arguments))
76
- }
77
-
78
- jasmine.Fixtures.prototype.read = function () {
79
- var htmlChunks = []
80
- , fixtureUrls = arguments
81
-
82
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
83
- htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))
84
- }
85
-
86
- return htmlChunks.join('')
87
- }
88
-
89
- jasmine.Fixtures.prototype.clearCache = function () {
90
- this.fixturesCache_ = {}
91
- }
92
-
93
- jasmine.Fixtures.prototype.cleanUp = function () {
94
- $('#' + this.containerId).remove()
95
- }
96
-
97
- jasmine.Fixtures.prototype.sandbox = function (attributes) {
98
- var attributesToSet = attributes || {}
99
- return $('<div id="sandbox" />').attr(attributesToSet)
100
- }
101
-
102
- jasmine.Fixtures.prototype.createContainer_ = function (html) {
103
- var container = $('<div>')
104
- .attr('id', this.containerId)
105
- .html(html)
106
-
107
- $(document.body).append(container)
108
- return container
109
- }
110
-
111
- jasmine.Fixtures.prototype.addToContainer_ = function (html){
112
- var container = $(document.body).find('#'+this.containerId).append(html)
113
-
114
- if (!container.length) {
115
- this.createContainer_(html)
116
- }
117
- }
118
-
119
- jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) {
120
- if (typeof this.fixturesCache_[url] === 'undefined') {
121
- this.loadFixtureIntoCache_(url)
122
- }
123
- return this.fixturesCache_[url]
124
- }
125
-
126
- jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
127
- var self = this
128
- , url = this.makeFixtureUrl_(relativeUrl)
129
- , htmlText = ''
130
- , request = $.ajax({
131
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
132
- cache: false,
133
- url: url,
134
- dataType: 'html',
135
- success: function (data, status, $xhr) {
136
- htmlText = $xhr.responseText
137
- }
138
- }).fail(function ($xhr, status, err) {
139
- throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
140
- })
141
-
142
- var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || [];
143
-
144
- scripts.each(function(){
145
- $.ajax({
146
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
147
- cache: false,
148
- dataType: 'script',
149
- url: $(this).attr('src'),
150
- success: function (data, status, $xhr) {
151
- htmlText += '<script>' + $xhr.responseText + '</script>'
152
- },
153
- error: function ($xhr, status, err) {
154
- throw new Error('Script could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
155
- }
156
- });
157
- })
158
-
159
- self.fixturesCache_[relativeUrl] = htmlText;
160
- }
161
-
162
- jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){
163
- return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
164
- }
165
-
166
- jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
167
- return this[methodName].apply(this, passedArguments)
168
- }
169
-
170
-
171
- jasmine.StyleFixtures = function () {
172
- this.fixturesCache_ = {}
173
- this.fixturesNodes_ = []
174
- this.fixturesPath = 'spec/javascripts/fixtures'
175
- }
176
-
177
- jasmine.StyleFixtures.prototype.set = function (css) {
178
- this.cleanUp()
179
- this.createStyle_(css)
180
- }
181
-
182
- jasmine.StyleFixtures.prototype.appendSet = function (css) {
183
- this.createStyle_(css)
184
- }
185
-
186
- jasmine.StyleFixtures.prototype.preload = function () {
187
- this.read_.apply(this, arguments)
188
- }
189
-
190
- jasmine.StyleFixtures.prototype.load = function () {
191
- this.cleanUp()
192
- this.createStyle_(this.read_.apply(this, arguments))
193
- }
194
-
195
- jasmine.StyleFixtures.prototype.appendLoad = function () {
196
- this.createStyle_(this.read_.apply(this, arguments))
197
- }
198
-
199
- jasmine.StyleFixtures.prototype.cleanUp = function () {
200
- while(this.fixturesNodes_.length) {
201
- this.fixturesNodes_.pop().remove()
202
- }
203
- }
204
-
205
- jasmine.StyleFixtures.prototype.createStyle_ = function (html) {
206
- var styleText = $('<div></div>').html(html).text()
207
- , style = $('<style>' + styleText + '</style>')
208
-
209
- this.fixturesNodes_.push(style)
210
- $('head').append(style)
211
- }
212
-
213
- jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache
214
- jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read
215
- jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_
216
- jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_
217
- jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_
218
- jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_
219
-
220
- jasmine.getJSONFixtures = function () {
221
- return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
222
- }
223
-
224
- jasmine.JSONFixtures = function () {
225
- this.fixturesCache_ = {}
226
- this.fixturesPath = 'spec/javascripts/fixtures/json'
227
- }
228
-
229
- jasmine.JSONFixtures.prototype.load = function () {
230
- this.read.apply(this, arguments)
231
- return this.fixturesCache_
232
- }
233
-
234
- jasmine.JSONFixtures.prototype.read = function () {
235
- var fixtureUrls = arguments
236
-
237
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
238
- this.getFixtureData_(fixtureUrls[urlIndex])
239
- }
240
-
241
- return this.fixturesCache_
242
- }
243
-
244
- jasmine.JSONFixtures.prototype.clearCache = function () {
245
- this.fixturesCache_ = {}
246
- }
247
-
248
- jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) {
249
- if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url)
250
- return this.fixturesCache_[url]
251
- }
252
-
253
- jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
254
- var self = this
255
- , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
256
-
257
- $.ajax({
258
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
259
- cache: false,
260
- dataType: 'json',
261
- url: url,
262
- success: function (data) {
263
- self.fixturesCache_[relativeUrl] = data
264
- },
265
- error: function ($xhr, status, err) {
266
- throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
267
- }
268
- })
269
- }
270
-
271
- jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
272
- return this[methodName].apply(this, passedArguments)
273
- }
274
-
275
- jasmine.jQuery = function () {}
276
-
277
- jasmine.jQuery.browserTagCaseIndependentHtml = function (html) {
278
- return $('<div/>').append(html).html()
279
- }
280
-
281
- jasmine.jQuery.elementToString = function (element) {
282
- return $(element).map(function () { return this.outerHTML; }).toArray().join(', ')
283
- }
284
-
285
- var data = {
286
- spiedEvents: {}
287
- , handlers: []
288
- }
289
-
290
- jasmine.jQuery.events = {
291
- spyOn: function (selector, eventName) {
292
- var handler = function (e) {
293
- var calls = (typeof data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] !== 'undefined') ? data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0
294
- data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = {
295
- args: jasmine.util.argsToArray(arguments),
296
- calls: ++calls
297
- }
298
- }
299
-
300
- $(selector).on(eventName, handler)
301
- data.handlers.push(handler)
302
-
303
- return {
304
- selector: selector,
305
- eventName: eventName,
306
- handler: handler,
307
- reset: function (){
308
- delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
309
- },
310
- calls: {
311
- count: function () {
312
- return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ?
313
- data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : 0;
314
- },
315
- any: function () {
316
- return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] ?
317
- !!data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].calls : false;
318
- }
319
- }
320
- }
321
- },
322
-
323
- args: function (selector, eventName) {
324
- var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].args
325
-
326
- if (!actualArgs) {
327
- throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."
328
- }
329
-
330
- return actualArgs
331
- },
332
-
333
- wasTriggered: function (selector, eventName) {
334
- return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
335
- },
336
-
337
- wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) {
338
- var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1)
339
-
340
- if (Object.prototype.toString.call(expectedArgs) !== '[object Array]')
341
- actualArgs = actualArgs[0]
342
-
343
- return util.equals(actualArgs, expectedArgs, customEqualityTesters)
344
- },
345
-
346
- wasPrevented: function (selector, eventName) {
347
- var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
348
- , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args
349
- , e = args ? args[0] : undefined
350
-
351
- return e && e.isDefaultPrevented()
352
- },
353
-
354
- wasStopped: function (selector, eventName) {
355
- var spiedEvent = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
356
- , args = (jasmine.util.isUndefined(spiedEvent)) ? {} : spiedEvent.args
357
- , e = args ? args[0] : undefined
358
-
359
- return e && e.isPropagationStopped()
360
- },
361
-
362
- cleanUp: function () {
363
- data.spiedEvents = {}
364
- data.handlers = []
365
- }
366
- }
367
-
368
- var hasProperty = function (actualValue, expectedValue) {
369
- if (expectedValue === undefined)
370
- return actualValue !== undefined
371
-
372
- return actualValue === expectedValue
373
- }
374
-
375
- beforeEach(function () {
376
- jasmine.addMatchers({
377
- toHaveClass: function () {
378
- return {
379
- compare: function (actual, className) {
380
- return { pass: $(actual).hasClass(className) }
381
- }
382
- }
383
- },
384
-
385
- toHaveCss: function () {
386
- return {
387
- compare: function (actual, css) {
388
- var stripCharsRegex = /[\s;\"\']/g
389
- for (var prop in css) {
390
- var value = css[prop]
391
- // see issue #147 on gh
392
- ;if ((value === 'auto') && ($(actual).get(0).style[prop] === 'auto')) continue
393
- var actualStripped = $(actual).css(prop).replace(stripCharsRegex, '')
394
- var valueStripped = value.replace(stripCharsRegex, '')
395
- if (actualStripped !== valueStripped) return { pass: false }
396
- }
397
- return { pass: true }
398
- }
399
- }
400
- },
401
-
402
- toBeVisible: function () {
403
- return {
404
- compare: function (actual) {
405
- return { pass: $(actual).is(':visible') }
406
- }
407
- }
408
- },
409
-
410
- toBeHidden: function () {
411
- return {
412
- compare: function (actual) {
413
- return { pass: $(actual).is(':hidden') }
414
- }
415
- }
416
- },
417
-
418
- toBeSelected: function () {
419
- return {
420
- compare: function (actual) {
421
- return { pass: $(actual).is(':selected') }
422
- }
423
- }
424
- },
425
-
426
- toBeChecked: function () {
427
- return {
428
- compare: function (actual) {
429
- return { pass: $(actual).is(':checked') }
430
- }
431
- }
432
- },
433
-
434
- toBeEmpty: function () {
435
- return {
436
- compare: function (actual) {
437
- return { pass: $(actual).is(':empty') }
438
- }
439
- }
440
- },
441
-
442
- toBeInDOM: function () {
443
- return {
444
- compare: function (actual) {
445
- return { pass: $.contains(document.documentElement, $(actual)[0]) }
446
- }
447
- }
448
- },
449
-
450
- toExist: function () {
451
- return {
452
- compare: function (actual) {
453
- return { pass: $(actual).length }
454
- }
455
- }
456
- },
457
-
458
- toHaveLength: function () {
459
- return {
460
- compare: function (actual, length) {
461
- return { pass: $(actual).length === length }
462
- }
463
- }
464
- },
465
-
466
- toHaveAttr: function () {
467
- return {
468
- compare: function (actual, attributeName, expectedAttributeValue) {
469
- return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) }
470
- }
471
- }
472
- },
473
-
474
- toHaveProp: function () {
475
- return {
476
- compare: function (actual, propertyName, expectedPropertyValue) {
477
- return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) }
478
- }
479
- }
480
- },
481
-
482
- toHaveId: function () {
483
- return {
484
- compare: function (actual, id) {
485
- return { pass: $(actual).attr('id') == id }
486
- }
487
- }
488
- },
489
-
490
- toHaveHtml: function () {
491
- return {
492
- compare: function (actual, html) {
493
- return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) }
494
- }
495
- }
496
- },
497
-
498
- toContainHtml: function () {
499
- return {
500
- compare: function (actual, html) {
501
- var actualHtml = $(actual).html()
502
- , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html)
503
-
504
- return { pass: (actualHtml.indexOf(expectedHtml) >= 0) }
505
- }
506
- }
507
- },
508
-
509
- toHaveText: function () {
510
- return {
511
- compare: function (actual, text) {
512
- var actualText = $(actual).text()
513
- var trimmedText = $.trim(actualText)
514
-
515
- if (text && $.isFunction(text.test)) {
516
- return { pass: text.test(actualText) || text.test(trimmedText) }
517
- } else {
518
- return { pass: (actualText == text || trimmedText == text) }
519
- }
520
- }
521
- }
522
- },
523
-
524
- toContainText: function () {
525
- return {
526
- compare: function (actual, text) {
527
- var trimmedText = $.trim($(actual).text())
528
-
529
- if (text && $.isFunction(text.test)) {
530
- return { pass: text.test(trimmedText) }
531
- } else {
532
- return { pass: trimmedText.indexOf(text) != -1 }
533
- }
534
- }
535
- }
536
- },
537
-
538
- toHaveValue: function () {
539
- return {
540
- compare: function (actual, value) {
541
- return { pass: $(actual).val() === value }
542
- }
543
- }
544
- },
545
-
546
- toHaveData: function () {
547
- return {
548
- compare: function (actual, key, expectedValue) {
549
- return { pass: hasProperty($(actual).data(key), expectedValue) }
550
- }
551
- }
552
- },
553
-
554
- toContainElement: function () {
555
- return {
556
- compare: function (actual, selector) {
557
- return { pass: $(actual).find(selector).length }
558
- }
559
- }
560
- },
561
-
562
- toBeMatchedBy: function () {
563
- return {
564
- compare: function (actual, selector) {
565
- return { pass: $(actual).filter(selector).length }
566
- }
567
- }
568
- },
569
-
570
- toBeDisabled: function () {
571
- return {
572
- compare: function (actual, selector) {
573
- return { pass: $(actual).is(':disabled') }
574
- }
575
- }
576
- },
577
-
578
- toBeFocused: function (selector) {
579
- return {
580
- compare: function (actual, selector) {
581
- return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement }
582
- }
583
- }
584
- },
585
-
586
- toHandle: function () {
587
- return {
588
- compare: function (actual, event) {
589
- if ( !actual || actual.length === 0 ) return { pass: false };
590
- var events = $._data($(actual).get(0), "events")
591
-
592
- if (!events || !event || typeof event !== "string") {
593
- return { pass: false }
594
- }
595
-
596
- var namespaces = event.split(".")
597
- , eventType = namespaces.shift()
598
- , sortedNamespaces = namespaces.slice(0).sort()
599
- , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)")
600
-
601
- if (events[eventType] && namespaces.length) {
602
- for (var i = 0; i < events[eventType].length; i++) {
603
- var namespace = events[eventType][i].namespace
604
-
605
- if (namespaceRegExp.test(namespace))
606
- return { pass: true }
607
- }
608
- } else {
609
- return { pass: (events[eventType] && events[eventType].length > 0) }
610
- }
611
-
612
- return { pass: false }
613
- }
614
- }
615
- },
616
-
617
- toHandleWith: function () {
618
- return {
619
- compare: function (actual, eventName, eventHandler) {
620
- if ( !actual || actual.length === 0 ) return { pass: false };
621
- var normalizedEventName = eventName.split('.')[0]
622
- , stack = $._data($(actual).get(0), "events")[normalizedEventName]
623
-
624
- for (var i = 0; i < stack.length; i++) {
625
- if (stack[i].handler == eventHandler) return { pass: true }
626
- }
627
-
628
- return { pass: false }
629
- }
630
- }
631
- },
632
-
633
- toHaveBeenTriggeredOn: function () {
634
- return {
635
- compare: function (actual, selector) {
636
- var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) }
637
-
638
- result.message = result.pass ?
639
- "Expected event " + $(actual) + " not to have been triggered on " + selector :
640
- "Expected event " + $(actual) + " to have been triggered on " + selector
641
-
642
- return result;
643
- }
644
- }
645
- },
646
-
647
- toHaveBeenTriggered: function (){
648
- return {
649
- compare: function (actual) {
650
- var eventName = actual.eventName
651
- , selector = actual.selector
652
- , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) }
653
-
654
- result.message = result.pass ?
655
- "Expected event " + eventName + " not to have been triggered on " + selector :
656
- "Expected event " + eventName + " to have been triggered on " + selector
657
-
658
- return result
659
- }
660
- }
661
- },
662
-
663
- toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) {
664
- return {
665
- compare: function (actual, selector, expectedArgs) {
666
- var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual)
667
- , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) }
668
-
669
- if (wasTriggered) {
670
- var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1]
671
- result.message = result.pass ?
672
- "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) :
673
- "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs)
674
-
675
- } else {
676
- // todo check on this
677
- result.message = result.pass ?
678
- "Expected event " + actual + " not to have been triggered on " + selector :
679
- "Expected event " + actual + " to have been triggered on " + selector
680
- }
681
-
682
- return result
683
- }
684
- }
685
- },
686
-
687
- toHaveBeenPreventedOn: function () {
688
- return {
689
- compare: function (actual, selector) {
690
- var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) }
691
-
692
- result.message = result.pass ?
693
- "Expected event " + actual + " not to have been prevented on " + selector :
694
- "Expected event " + actual + " to have been prevented on " + selector
695
-
696
- return result
697
- }
698
- }
699
- },
700
-
701
- toHaveBeenPrevented: function () {
702
- return {
703
- compare: function (actual) {
704
- var eventName = actual.eventName
705
- , selector = actual.selector
706
- , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) }
707
-
708
- result.message = result.pass ?
709
- "Expected event " + eventName + " not to have been prevented on " + selector :
710
- "Expected event " + eventName + " to have been prevented on " + selector
711
-
712
- return result
713
- }
714
- }
715
- },
716
-
717
- toHaveBeenStoppedOn: function () {
718
- return {
719
- compare: function (actual, selector) {
720
- var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) }
721
-
722
- result.message = result.pass ?
723
- "Expected event " + actual + " not to have been stopped on " + selector :
724
- "Expected event " + actual + " to have been stopped on " + selector
725
-
726
- return result;
727
- }
728
- }
729
- },
730
-
731
- toHaveBeenStopped: function () {
732
- return {
733
- compare: function (actual) {
734
- var eventName = actual.eventName
735
- , selector = actual.selector
736
- , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) }
737
-
738
- result.message = result.pass ?
739
- "Expected event " + eventName + " not to have been stopped on " + selector :
740
- "Expected event " + eventName + " to have been stopped on " + selector
741
-
742
- return result
743
- }
744
- }
745
- }
746
- })
747
-
748
- jasmine.getEnv().addCustomEqualityTester(function(a, b) {
749
- if (a && b) {
750
- if (a instanceof $ || jasmine.isDomNode(a)) {
751
- var $a = $(a)
752
-
753
- if (b instanceof $)
754
- return $a.length == b.length && $a.is(b)
755
-
756
- return $a.is(b);
757
- }
758
-
759
- if (b instanceof $ || jasmine.isDomNode(b)) {
760
- var $b = $(b)
761
-
762
- if (a instanceof $)
763
- return a.length == $b.length && $b.is(a)
764
-
765
- return $b.is(a);
766
- }
767
- }
768
- })
769
-
770
- jasmine.getEnv().addCustomEqualityTester(function (a, b) {
771
- if (a instanceof $ && b instanceof $ && a.size() == b.size())
772
- return a.is(b)
773
- })
774
- })
775
-
776
- afterEach(function () {
777
- jasmine.getFixtures().cleanUp()
778
- jasmine.getStyleFixtures().cleanUp()
779
- jasmine.jQuery.events.cleanUp()
780
- })
781
-
782
- window.readFixtures = function () {
783
- return jasmine.getFixtures().proxyCallTo_('read', arguments)
784
- }
785
-
786
- window.preloadFixtures = function () {
787
- jasmine.getFixtures().proxyCallTo_('preload', arguments)
788
- }
789
-
790
- window.loadFixtures = function () {
791
- jasmine.getFixtures().proxyCallTo_('load', arguments)
792
- }
793
-
794
- window.appendLoadFixtures = function () {
795
- jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)
796
- }
797
-
798
- window.setFixtures = function (html) {
799
- return jasmine.getFixtures().proxyCallTo_('set', arguments)
800
- }
801
-
802
- window.appendSetFixtures = function () {
803
- jasmine.getFixtures().proxyCallTo_('appendSet', arguments)
804
- }
805
-
806
- window.sandbox = function (attributes) {
807
- return jasmine.getFixtures().sandbox(attributes)
808
- }
809
-
810
- window.spyOnEvent = function (selector, eventName) {
811
- return jasmine.jQuery.events.spyOn(selector, eventName)
812
- }
813
-
814
- window.preloadStyleFixtures = function () {
815
- jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)
816
- }
817
-
818
- window.loadStyleFixtures = function () {
819
- jasmine.getStyleFixtures().proxyCallTo_('load', arguments)
820
- }
821
-
822
- window.appendLoadStyleFixtures = function () {
823
- jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)
824
- }
825
-
826
- window.setStyleFixtures = function (html) {
827
- jasmine.getStyleFixtures().proxyCallTo_('set', arguments)
828
- }
829
-
830
- window.appendSetStyleFixtures = function (html) {
831
- jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)
832
- }
833
-
834
- window.loadJSONFixtures = function () {
835
- return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)
836
- }
837
-
838
- window.getJSONFixture = function (url) {
839
- return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]
840
- }
841
-}));
web/gui/custom/README.md
+1
-1
@@ -581,7 +581,7 @@ Negative values are rendered counter-clockwise.
581
This is a chart that displays the hotwater temperature in the given range of 40
582
to 50.
583
```html
584
-<div data-netdata="stiebeleltron_system.hotwater.hotwatertemp"
584
+<div data-netdata="acme_system.hotwater.hotwatertemp"
585
data-title="Hot Water Temperature"
586
data-decimal-digits="1"
587
data-chart-library="easypiechart"
web/gui/dashboard_info.js
-55
@@ -430,12 +430,6 @@ netdataDashboard.menu = {
430
info: 'Information extracted from a server log file. <code>web_log</code> plugin incrementally parses the server log file to provide, in real-time, a break down of key server performance metrics. For web servers, an extended log file format may optionally be used (for <code>nginx</code> and <code>apache</code>) offering timing information and bandwidth for both requests and responses. <code>web_log</code> plugin may also be configured to provide a break down of requests per URL pattern (check <a href="https://github.com/netdata/netdata/blob/master/collectors/python.d.plugin/web_log/web_log.conf" target="_blank"><code>/etc/netdata/python.d/web_log.conf</code></a>).'
431
},
432
433
- 'named': {
434
- title: 'named',
435
- icon: '<i class="fas fa-tag"></i>',
436
- info: undefined
437
- },
438
-
433
'squid': {
434
title: 'squid',
435
icon: '<i class="fas fa-exchange-alt"></i>',
@@ -454,24 +448,6 @@ netdataDashboard.menu = {
448
info: undefined
449
},
450
457
- 'smawebbox': {
458
- title: 'Solar Power',
459
- icon: '<i class="fas fa-sun"></i>',
460
- info: undefined
461
- },
462
-
463
- 'fronius': {
464
- title: 'Fronius',
465
- icon: '<i class="fas fa-sun"></i>',
466
- info: undefined
467
- },
468
-
469
- 'stiebeleltron': {
470
- title: 'Stiebel Eltron',
471
- icon: '<i class="fas fa-thermometer-half"></i>',
472
- info: undefined
473
- },
474
-
451
'snmp': {
452
title: 'SNMP',
453
icon: '<i class="fas fa-random"></i>',
@@ -4835,37 +4811,6 @@ netdataDashboard.context = {
4811
}
4812
]
4813
},
4838
- // ------------------------------------------------------------------------
4839
- // Fronius Solar Power
4840
-
4841
- 'fronius.power': {
4842
- info: 'Positive <code>Grid</code> values mean that power is coming from the grid. Negative values are excess power that is going back into the grid, possibly selling it. ' +
4843
- '<code>Photovoltaics</code> is the power generated from the solar panels. ' +
4844
- '<code>Accumulator</code> is the stored power in the accumulator, if one is present.'
4845
- },
4846
-
4847
- 'fronius.autonomy': {
4848
- commonMin: true,
4849
- commonMax: true,
4850
- valueRange: "[0, 100]",
4851
- info: 'The <code>Autonomy</code> is the percentage of how autonomous the installation is. An autonomy of 100 % means that the installation is producing more energy than it is needed. ' +
4852
- 'The <code>Self consumption</code> indicates the ratio between the current power generated and the current load. When it reaches 100 %, the <code>Autonomy</code> declines, since the solar panels can not produce enough energy and need support from the grid.'
4853
- },
4854
-
4855
- 'fronius.energy.today': {
4856
- commonMin: true,
4857
- commonMax: true,
4858
- valueRange: "[0, null]"
4859
- },
4860
-
4861
- // ------------------------------------------------------------------------
4862
- // Stiebel Eltron Heat pump installation
4863
-
4864
- 'stiebeleltron.system.roomtemp': {
4865
- commonMin: true,
4866
- commonMax: true,
4867
- valueRange: "[0, null]"
4868
- },
4814
4815
// ------------------------------------------------------------------------
4816
// Port check