diff options
Diffstat (limited to 'collectors/node.d.plugin')
-rw-r--r-- | collectors/node.d.plugin/Makefile.am | 4 | ||||
-rw-r--r-- | collectors/node.d.plugin/README.md | 2 | ||||
-rw-r--r-- | collectors/node.d.plugin/fronius/Makefile.inc | 13 | ||||
-rw-r--r-- | collectors/node.d.plugin/fronius/README.md | 135 | ||||
-rw-r--r-- | collectors/node.d.plugin/fronius/fronius.node.js | 400 | ||||
-rw-r--r-- | collectors/node.d.plugin/named/Makefile.inc | 13 | ||||
-rw-r--r-- | collectors/node.d.plugin/named/README.md | 348 | ||||
-rw-r--r-- | collectors/node.d.plugin/named/named.node.js | 610 | ||||
-rw-r--r-- | collectors/node.d.plugin/node.d.conf | 6 | ||||
-rw-r--r-- | collectors/node.d.plugin/sma_webbox/Makefile.inc | 13 | ||||
-rw-r--r-- | collectors/node.d.plugin/sma_webbox/README.md | 33 | ||||
-rw-r--r-- | collectors/node.d.plugin/sma_webbox/sma_webbox.node.js | 239 | ||||
-rw-r--r-- | collectors/node.d.plugin/snmp/README.md | 2 | ||||
-rw-r--r-- | collectors/node.d.plugin/stiebeleltron/Makefile.inc | 13 | ||||
-rw-r--r-- | collectors/node.d.plugin/stiebeleltron/README.md | 525 | ||||
-rw-r--r-- | collectors/node.d.plugin/stiebeleltron/stiebeleltron.node.js | 197 |
16 files changed, 2 insertions, 2551 deletions
diff --git a/collectors/node.d.plugin/Makefile.am b/collectors/node.d.plugin/Makefile.am index c3142d433..1b8281748 100644 --- a/collectors/node.d.plugin/Makefile.am +++ b/collectors/node.d.plugin/Makefile.am @@ -36,11 +36,7 @@ dist_nodeconfig_DATA = \ dist_node_DATA = \ $(NULL) -include fronius/Makefile.inc -include named/Makefile.inc -include sma_webbox/Makefile.inc include snmp/Makefile.inc -include stiebeleltron/Makefile.inc nodemodulesdir=$(nodedir)/node_modules dist_nodemodules_DATA = \ diff --git a/collectors/node.d.plugin/README.md b/collectors/node.d.plugin/README.md index 8db80d85b..4c5f278bd 100644 --- a/collectors/node.d.plugin/README.md +++ b/collectors/node.d.plugin/README.md @@ -233,4 +233,4 @@ The `service` object defines a set of functions to allow you send information to _FIXME: document an operational node.d.plugin data collector - the best example is the [snmp collector](https://raw.githubusercontent.com/netdata/netdata/master/collectors/node.d.plugin/snmp/snmp.node.js)_ -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) + diff --git a/collectors/node.d.plugin/fronius/Makefile.inc b/collectors/node.d.plugin/fronius/Makefile.inc deleted file mode 100644 index da0743a88..000000000 --- a/collectors/node.d.plugin/fronius/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# THIS IS NOT A COMPLETE Makefile -# IT IS INCLUDED BY ITS PARENT'S Makefile.am -# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT - -# install these files -dist_node_DATA += fronius/fronius.node.js -# dist_nodeconfig_DATA += fronius/fronius.conf - -# do not install these files, but include them in the distribution -dist_noinst_DATA += fronius/README.md fronius/Makefile.inc - diff --git a/collectors/node.d.plugin/fronius/README.md b/collectors/node.d.plugin/fronius/README.md deleted file mode 100644 index 746737d0b..000000000 --- a/collectors/node.d.plugin/fronius/README.md +++ /dev/null @@ -1,135 +0,0 @@ -<!-- -title: "Fronius Symo monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/fronius/README.md -sidebar_label: "Fronius Symo" ---> - -# Fronius Symo monitoring with Netdata - -Collects metrics from the configured solar power installation from Fronius Symo. - -**Requirements** - -- Configuration file `fronius.conf` in the node.d Netdata config dir (default: `/etc/netdata/node.d/fronius.conf`) -- Fronius Symo with network access (http) - -It produces per server: - -1. **Power** - -- Current power input from the grid (positive values), output to the grid (negative values), in W -- Current power input from the solar panels, in W -- Current power stored in the accumulator (if present), in W (in theory, untested) - -2. **Consumption** - -- Local consumption in W - -3. **Autonomy** - -- Relative autonomy in %. 100 % autonomy means that the solar panels are delivering more power than it is needed by local consumption. -- Relative self consumption in %. The lower the better - -4. **Energy** - -- The energy produced during the current day, in kWh -- The energy produced during the current year, in kWh - -5. **Inverter** - -- The current power output from the connected inverters, in W, one dimension per inverter. At least one is always present. - -## configuration - -Sample: - -```json -{ - "enable_autodetect": false, - "update_every": 5, - "servers": [ - { - "name": "Symo", - "hostname": "symo.ip.or.dns", - "update_every": 5, - "api_path": "/solar_api/v1/GetPowerFlowRealtimeData.fcgi" - } - ] -} -``` - -If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `5`. - ---- - -[Fronius Symo 8.2](https://www.fronius.com/en/photovoltaics/products/all-products/inverters/fronius-symo/fronius-symo-8-2-3-m) - -The plugin has been tested with a single inverter, namely Fronius Symo 8.2-3-M: - -- Datalogger version: 240.162630 -- Software version: 3.7.4-6 -- Hardware version: 2.4D - -Other products and versions may work, but without any guarantees. - -Example Netdata configuration for node.d/fronius.conf. Copy this section to fronius.conf and change name/ip. -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. - -```json -{ - "enable_autodetect": false, - "update_every": 5, - "servers": [ - { - "name": "solar", - "hostname": "symo.ip.or.dns", - "update_every": 5, - "api_path": "/solar_api/v1/GetPowerFlowRealtimeData.fcgi" - } - ] -} -``` - -The output of /solar_api/v1/GetPowerFlowRealtimeData.fcgi looks like this: - -```json -{ - "Head" : { - "RequestArguments" : {}, - "Status" : { - "Code" : 0, - "Reason" : "", - "UserMessage" : "" - }, - "Timestamp" : "2017-07-05T12:35:12+02:00" - }, - "Body" : { - "Data" : { - "Site" : { - "Mode" : "meter", - "P_Grid" : -6834.549847, - "P_Load" : -1271.450153, - "P_Akku" : null, - "P_PV" : 8106, - "rel_SelfConsumption" : 15.685297, - "rel_Autonomy" : 100, - "E_Day" : 35020, - "E_Year" : 5826076, - "E_Total" : 14788870, - "Meter_Location" : "grid" - }, - "Inverters" : { - "1" : { - "DT" : 123, - "P" : 8106, - "E_Day" : 35020, - "E_Year" : 5826076, - "E_Total" : 14788870 - } - } - } - } -} -``` - -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2Ffronius%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/node.d.plugin/fronius/fronius.node.js b/collectors/node.d.plugin/fronius/fronius.node.js deleted file mode 100644 index 436f3a325..000000000 --- a/collectors/node.d.plugin/fronius/fronius.node.js +++ /dev/null @@ -1,400 +0,0 @@ -"use strict"; -// SPDX-License-Identifier: GPL-3.0-or-later - -// This program will connect to one or more Fronius Symo Inverters. -// to get the Solar Power Generated (current, today). - -// example configuration in netdata/conf.d/node.d/fronius.conf.md - -require("url"); -require("http"); -var netdata = require("netdata"); - -netdata.debug("loaded " + __filename + " plugin"); - -var fronius = { - name: "Fronius", - enable_autodetect: false, - update_every: 5, - base_priority: 60000, - charts: {}, - - powerGridId: "p_grid", - powerPvId: "p_pv", - powerAccuId: "p_akku", // not my typo! Using the ID from the AP - consumptionLoadId: "p_load", - autonomyId: "rel_autonomy", - consumptionSelfId: "rel_selfconsumption", - solarConsumptionId: "solar_consumption", - energyTodayId: "e_day", - energyYearId: "e_year", - - createBasicDimension: function (id, name, divisor) { - return { - id: id, // the unique id of the dimension - name: name, // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: divisor, // the divisor - hidden: false // is hidden (boolean) - }; - }, - - // Gets the site power chart. Will be created if not existing. - getSitePowerChart: function (service, suffix) { - var id = this.getChartId(service, suffix); - var chart = fronius.charts[id]; - if (fronius.isDefined(chart)) return chart; - - var dim = {}; - dim[fronius.powerGridId] = this.createBasicDimension(fronius.powerGridId, "grid", 1); - dim[fronius.powerPvId] = this.createBasicDimension(fronius.powerPvId, "photovoltaics", 1); - dim[fronius.powerAccuId] = this.createBasicDimension(fronius.powerAccuId, "accumulator", 1); - - chart = { - id: id, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Site Power", // the title of the chart - units: "W", // the units of the chart dimensions - family: "power", // the family of the chart - context: "fronius.power", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 1, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(id, chart); - fronius.charts[id] = chart; - - return chart; - }, - - // Gets the site consumption chart. Will be created if not existing. - getSiteConsumptionChart: function (service, suffix) { - var id = this.getChartId(service, suffix); - var chart = fronius.charts[id]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.consumptionLoadId] = this.createBasicDimension(fronius.consumptionLoadId, "load", 1); - - chart = { - id: id, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Load", // the title of the chart - units: "W", // the units of the chart dimensions - family: "consumption", // the family of the chart - context: "fronius.consumption", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 2, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(id, chart); - fronius.charts[id] = chart; - - return chart; - }, - - // Gets the site consumption chart. Will be created if not existing. - getSiteAutonomyChart: function (service, suffix) { - var id = this.getChartId(service, suffix); - var chart = fronius.charts[id]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.autonomyId] = this.createBasicDimension(fronius.autonomyId, "autonomy", 1); - dim[fronius.consumptionSelfId] = this.createBasicDimension(fronius.consumptionSelfId, "self_consumption", 1); - dim[fronius.solarConsumptionId] = this.createBasicDimension(fronius.solarConsumptionId, "solar_consumption", 1); - - chart = { - id: id, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Autonomy", // the title of the chart - units: "%", // the units of the chart dimensions - family: "autonomy", // the family of the chart - context: "fronius.autonomy", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 3, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(id, chart); - fronius.charts[id] = chart; - - return chart; - }, - - // Gets the site energy chart for today. Will be created if not existing. - getSiteEnergyTodayChart: function (service, suffix) { - var chartId = this.getChartId(service, suffix); - var chart = fronius.charts[chartId]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.energyTodayId] = this.createBasicDimension(fronius.energyTodayId, "today", 1000); - chart = { - id: chartId, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Energy production for today",// the title of the chart - units: "kWh", // the units of the chart dimensions - family: "energy", // the family of the chart - context: "fronius.energy.today", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 4, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(chartId, chart); - fronius.charts[chartId] = chart; - - return chart; - }, - - // Gets the site energy chart for today. Will be created if not existing. - getSiteEnergyYearChart: function (service, suffix) { - var chartId = this.getChartId(service, suffix); - var chart = fronius.charts[chartId]; - if (fronius.isDefined(chart)) return chart; - var dim = {}; - dim[fronius.energyYearId] = this.createBasicDimension(fronius.energyYearId, "year", 1000); - chart = { - id: chartId, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Energy production for this year",// the title of the chart - units: "kWh", // the units of the chart dimensions - family: "energy", // the family of the chart - context: "fronius.energy.year", // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: fronius.base_priority + 5, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(chartId, chart); - fronius.charts[chartId] = chart; - - return chart; - }, - - // Gets the inverter power chart. Will be created if not existing. - // Needs the array of inverters in order to create a chart with all inverters as dimensions - getInverterPowerChart: function (service, suffix, inverters) { - var chartId = this.getChartId(service, suffix); - var chart = fronius.charts[chartId]; - if (fronius.isDefined(chart)) return chart; - - var dim = {}; - for (var key in inverters) { - if (inverters.hasOwnProperty(key)) { - var name = key; - if (!isNaN(key)) name = "inverter_" + key; - dim[key] = this.createBasicDimension("inverter_" + key, name, 1); - } - } - - chart = { - id: chartId, // the unique id of the chart - name: "", // the unique name of the chart - title: service.name + " Current Inverter Output",// the title of the chart - units: "W", // the units of the chart dimensions - family: "inverters", // the family of the chart - context: "fronius.inverter.output", // the context of the chart - type: netdata.chartTypes.stacked, // the type of the chart - priority: fronius.base_priority + 6, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dim - }; - chart = service.chart(chartId, chart); - fronius.charts[chartId] = chart; - - return chart; - }, - - processResponse: function (service, content) { - var json = fronius.convertToJson(content); - if (json === null) return; - - // add the service - service.commit(); - - var chartDefinitions = fronius.parseCharts(service, json); - var chartCount = chartDefinitions.length; - while (chartCount--) { - var chartObj = chartDefinitions[chartCount]; - service.begin(chartObj.chart); - var dimCount = chartObj.dimensions.length; - while (dimCount--) { - var dim = chartObj.dimensions[dimCount]; - service.set(dim.name, dim.value); - } - service.end(); - } - }, - - parseCharts: function (service, json) { - var site = json.Body.Data.Site; - return [ - this.parsePowerChart(service, site), - this.parseConsumptionChart(service, site), - this.parseAutonomyChart(service, site), - this.parseEnergyTodayChart(service, site), - this.parseEnergyYearChart(service, site), - this.parseInverterChart(service, json.Body.Data.Inverters) - ]; - }, - - parsePowerChart: function (service, site) { - return this.getChart(this.getSitePowerChart(service, "power"), - [ - this.getDimension(this.powerGridId, Math.round(site.P_Grid)), - this.getDimension(this.powerPvId, Math.round(Math.max(site.P_PV, 0))), - this.getDimension(this.powerAccuId, Math.round(site.P_Akku)) - ] - ); - }, - - parseConsumptionChart: function (service, site) { - return this.getChart(this.getSiteConsumptionChart(service, "consumption"), - [this.getDimension(this.consumptionLoadId, Math.round(Math.abs(site.P_Load)))] - ); - }, - - parseAutonomyChart: function (service, site) { - var selfConsumption = site.rel_SelfConsumption; - var solarConsumption = 0; - var load = Math.abs(site.P_Load); - var power = Math.max(site.P_PV, 0); - if (power <= 0) solarConsumption = 0; - else if (load >= power) solarConsumption = 100; - else solarConsumption = 100 / power * load; - return this.getChart(this.getSiteAutonomyChart(service, "autonomy"), - [ - this.getDimension(this.autonomyId, Math.round(site.rel_Autonomy)), - this.getDimension(this.consumptionSelfId, Math.round(selfConsumption === null ? 100 : selfConsumption)), - this.getDimension(this.solarConsumptionId, Math.round(solarConsumption)) - ] - ); - }, - - parseEnergyTodayChart: function (service, site) { - return this.getChart(this.getSiteEnergyTodayChart(service, "energy.today"), - [this.getDimension(this.energyTodayId, Math.round(Math.max(site.E_Day, 0)))] - ); - }, - - parseEnergyYearChart: function (service, site) { - return this.getChart(this.getSiteEnergyYearChart(service, "energy.year"), - [this.getDimension(this.energyYearId, Math.round(Math.max(site.E_Year, 0)))] - ); - }, - - parseInverterChart: function (service, inverters) { - var dimensions = []; - for (var key in inverters) { - if (inverters.hasOwnProperty(key)) { - dimensions.push(this.getDimension(key, Math.round(inverters[key].P))); - } - } - return this.getChart(this.getInverterPowerChart(service, "inverters.output", inverters), dimensions); - }, - - getDimension: function (name, value) { - return { - name: name, - value: value - }; - }, - - getChart: function (chart, dimensions) { - return { - chart: chart, - dimensions: dimensions - }; - }, - - getChartId: function (service, suffix) { - return "fronius_" + service.name + "." + suffix; - }, - - convertToJson: function (httpBody) { - if (httpBody === null) return null; - var json = httpBody; - // can't parse if it's already a json object, - // the check enables easier testing if the httpBody is already valid JSON. - if (typeof httpBody !== "object") { - try { - json = JSON.parse(httpBody); - } catch (error) { - netdata.error("fronius: Got a response, but it is not valid JSON. Ignoring. Error: " + error.message); - return null; - } - } - return this.isResponseValid(json) ? json : null; - }, - - // some basic validation - isResponseValid: function (json) { - if (this.isUndefined(json.Body)) return false; - if (this.isUndefined(json.Body.Data)) return false; - if (this.isUndefined(json.Body.Data.Site)) return false; - return this.isDefined(json.Body.Data.Inverters); - }, - - // module.serviceExecute() - // this function is called only from this module - // its purpose is to prepare the request and call - // netdata.serviceExecute() - serviceExecute: function (name, uri, update_every) { - netdata.debug(this.name + ": " + name + ": url: " + uri + ", update_every: " + update_every); - - var service = netdata.service({ - name: name, - request: netdata.requestFromURL("http://" + uri), - update_every: update_every, - module: this - }); - service.execute(this.processResponse); - }, - - - configure: function (config) { - if (fronius.isUndefined(config.servers)) return 0; - var added = 0; - var len = config.servers.length; - while (len--) { - var server = config.servers[len]; - if (fronius.isUndefined(server.update_every)) server.update_every = this.update_every; - if (fronius.areUndefined([server.name, server.hostname, server.api_path])) continue; - - var url = server.hostname + server.api_path; - this.serviceExecute(server.name, url, server.update_every); - added++; - } - return added; - }, - - // module.update() - // this is called repeatedly to collect data, by calling - // netdata.serviceExecute() - update: function (service, callback) { - service.execute(function (serv, data) { - service.module.processResponse(serv, data); - callback(); - }); - }, - - isUndefined: function (value) { - return typeof value === "undefined"; - }, - - areUndefined: function (valueArray) { - var i = 0; - for (i; i < valueArray.length; i++) { - if (this.isUndefined(valueArray[i])) return true; - } - return false; - }, - - isDefined: function (value) { - return typeof value !== "undefined"; - } -}; - -module.exports = fronius; diff --git a/collectors/node.d.plugin/named/Makefile.inc b/collectors/node.d.plugin/named/Makefile.inc deleted file mode 100644 index 95f423012..000000000 --- a/collectors/node.d.plugin/named/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# THIS IS NOT A COMPLETE Makefile -# IT IS INCLUDED BY ITS PARENT'S Makefile.am -# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT - -# install these files -dist_node_DATA += named/named.node.js -# dist_nodeconfig_DATA += named/named.conf - -# do not install these files, but include them in the distribution -dist_noinst_DATA += named/README.md named/Makefile.inc - diff --git a/collectors/node.d.plugin/named/README.md b/collectors/node.d.plugin/named/README.md deleted file mode 100644 index acd03f687..000000000 --- a/collectors/node.d.plugin/named/README.md +++ /dev/null @@ -1,348 +0,0 @@ -<!-- -title: "ISC BIND monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/named/README.md -sidebar_label: "ISC BIND" ---> - -# ISC BIND monitoring with Netdata - -Monitor one or more ISC Bind servers. - -## Example Netdata charts - -Depending on the number of views your bind has, you may get a large number of charts. -Here this is with just one view: - -![image](https://cloud.githubusercontent.com/assets/2662304/12765473/879b8e04-ca07-11e5-817d-b0651996c42b.png) -![image](https://cloud.githubusercontent.com/assets/2662304/12766538/12b272fa-ca0d-11e5-81e1-6a9f8ff488ff.png) - -## How it works - -The plugin will execute (from within node.js) the equivalent of: - -```sh -curl "http://localhost:8888/json/v1/server" -``` - -Here is a sample of the output this command produces. - -```js -{ - "json-stats-version":"1.0", - "boot-time":"2016-01-31T08:20:48Z", - "config-time":"2016-01-31T09:28:03Z", - "current-time":"2016-02-02T22:22:20Z", - "opcodes":{ - "QUERY":247816, - "IQUERY":0, - "STATUS":0, - "RESERVED3":0, - "NOTIFY":0, - "UPDATE":3813, - "RESERVED6":0, - "RESERVED7":0, - "RESERVED8":0, - "RESERVED9":0, - "RESERVED10":0, - "RESERVED11":0, - "RESERVED12":0, - "RESERVED13":0, - "RESERVED14":0, - "RESERVED15":0 - }, - "qtypes":{ - "A":89519, - "NS":863, - "CNAME":1, - "SOA":1, - "PTR":116779, - "MX":276, - "TXT":198, - "AAAA":39324, - "SRV":850, - "ANY":5 - }, - "nsstats":{ - "Requestv4":251630, - "ReqEdns0":1255, - "ReqTSIG":3813, - "ReqTCP":57, - "AuthQryRej":1455, - "RecQryRej":122, - "Response":245918, - "TruncatedResp":44, - "RespEDNS0":1255, - "RespTSIG":3813, - "QrySuccess":205159, - "QryAuthAns":119495, - "QryNoauthAns":120770, - "QryNxrrset":32711, - "QrySERVFAIL":262, - "QryNXDOMAIN":2395, - "QryRecursion":40885, - "QryDuplicate":5712, - "QryFailure":1577, - "UpdateDone":2514, - "UpdateFail":1299, - "UpdateBadPrereq":1276, - "QryUDP":246194, - "QryTCP":45, - "OtherOpt":101 - }, - "views":{ - "local":{ - "resolver":{ - "stats":{ - "Queryv4":74577, - "Responsev4":67032, - "NXDOMAIN":601, - "SERVFAIL":5, - "FORMERR":7, - "EDNS0Fail":7, - "Truncated":3071, - "Lame":4, - "Retry":11826, - "QueryTimeout":1838, - "GlueFetchv4":6864, - "GlueFetchv4Fail":30, - "QryRTT10":112, - "QryRTT100":42900, - "QryRTT500":23275, - "QryRTT800":534, - "QryRTT1600":97, - "QryRTT1600+":20, - "BucketSize":31, - "REFUSED":13 - }, - "qtypes":{ - "A":64931, - "NS":870, - "CNAME":185, - "PTR":5, - "MX":49, - "TXT":149, - "AAAA":7972, - "SRV":416 - }, - "cache":{ - "A":40356, - "NS":8032, - "CNAME":14477, - "PTR":2, - "MX":21, - "TXT":32, - "AAAA":3301, - "SRV":94, - "DS":237, - "RRSIG":2301, - "NSEC":126, - "!A":52, - "!NS":4, - "!TXT":1, - "!AAAA":3797, - "!SRV":9, - "NXDOMAIN":590 - }, - "cachestats":{ - "CacheHits":1085188, - "CacheMisses":109, - "QueryHits":464755, - "QueryMisses":55624, - "DeleteLRU":0, - "DeleteTTL":42615, - "CacheNodes":5188, - "CacheBuckets":2079, - "TreeMemTotal":2326026, - "TreeMemInUse":1508075, - "HeapMemMax":132096, - "HeapMemTotal":393216, - "HeapMemInUse":132096 - }, - "adb":{ - "nentries":1021, - "entriescnt":3157, - "nnames":1021, - "namescnt":3022 - } - } - }, - "public":{ - "resolver":{ - "stats":{ - "BucketSize":31 - }, - "qtypes":{ - }, - "cache":{ - }, - "cachestats":{ - "CacheHits":0, - "CacheMisses":0, - "QueryHits":0, - "QueryMisses":0, - "DeleteLRU":0, - "DeleteTTL":0, - "CacheNodes":0, - "CacheBuckets":64, - "TreeMemTotal":287392, - "TreeMemInUse":29608, - "HeapMemMax":1024, - "HeapMemTotal":262144, - "HeapMemInUse":1024 - }, - "adb":{ - "nentries":1021, - "nnames":1021 - } - } - }, - "_bind":{ - "resolver":{ - "stats":{ - "BucketSize":31 - }, - "qtypes":{ - }, - "cache":{ - }, - "cachestats":{ - "CacheHits":0, - "CacheMisses":0, - "QueryHits":0, - "QueryMisses":0, - "DeleteLRU":0, - "DeleteTTL":0, - "CacheNodes":0, - "CacheBuckets":64, - "TreeMemTotal":287392, - "TreeMemInUse":29608, - "HeapMemMax":1024, - "HeapMemTotal":262144, - "HeapMemInUse":1024 - }, - "adb":{ - "nentries":1021, - "nnames":1021 - } - } - } - } -} -``` - -From this output it collects: - -- Global Received Requests by IP version (IPv4, IPv6) -- Global Successful Queries -- Current Recursive Clients -- Global Queries by IP Protocol (TCP, UDP) -- Global Queries Analysis -- Global Received Updates -- Global Query Failures -- Global Query Failures Analysis -- Other Global Server Statistics -- Global Incoming Requests by OpCode -- Global Incoming Requests by Query Type -- 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) -- Per View Statistics (the following set will be added for each bind view): - - View, Resolver Active Queries - - View, Resolver Statistics - - View, Resolver Round Trip Timings - - View, Requests by Query Type - -## Configuration - -The collector (optionally) reads a configuration file named `/etc/netdata/node.d/named.conf`, with the following contents: - -```js -{ - "enable_autodetect": true, - "update_every": 5, - "servers": [ - { - "name": "bind1", - "url": "http://127.0.0.1:8888/json/v1/server", - "update_every": 1 - }, - { - "name": "bind2", - "url": "http://10.1.2.3:8888/json/v1/server", - "update_every": 2 - } - ] -} -``` - -You can add any number of bind servers. - -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. - -### XML instead of JSON, from bind - -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. - -In such cases, use a URL like this: - -```sh -curl "http://localhost:8888/xml/v3/server" -``` - -Only `xml` and `v3` has been tested. - -Keep in mind though, that XML parsing is done using javascript code, which requires a triple conversion: - -1. from XML to JSON using a javascript XML parser (**CPU intensive**), -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), -3. which is then processed to generate the data for the charts (this will happen even if bind is producing JSON). - -In general, expect XML parsing to be 2 to 3 times more CPU intensive than JSON. - -**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. - -The XML interface of bind is not autodetected. -You will have to provide the config file `/etc/netdata/node.d/named.conf`, like this: - -```js -{ - "enable_autodetect": false, - "update_every": 1, - "servers": [ - { - "name": "local", - "url": "http://localhost:8888/xml/v3/server", - "update_every": 1 - } - ] -} -``` - -Of course, you can monitor more than one bind servers. Each one can be configured with either JSON or XML output. - -## Auto-detection - -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. - -## Bind (named) configuration - -To use this plugin, you have to have bind v9.10+ properly compiled to provide statistics in `JSON` format. - -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). - -Normally, you will need something like this in your `named.conf`: - -``` -statistics-channels { - inet 127.0.0.1 port 8888 allow { 127.0.0.1; }; - inet ::1 port 8888 allow { ::1; }; -}; -``` - -(use the IPv4 or IPv6 line depending on what you are using, you can also use both) - -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): - -```sh -curl "http://localhost:8888/json/v1/server" -``` - -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2Fnamed%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/node.d.plugin/named/named.node.js b/collectors/node.d.plugin/named/named.node.js deleted file mode 100644 index 668a044c7..000000000 --- a/collectors/node.d.plugin/named/named.node.js +++ /dev/null @@ -1,610 +0,0 @@ -'use strict'; -// SPDX-License-Identifier: GPL-3.0-or-later - -// collect statistics from bind (named) v9.10+ -// -// bind statistics documentation at: -// http://jpmens.net/2013/03/18/json-in-bind-9-s-statistics-server/ -// https://ftp.isc.org/isc/bind/9.10.3/doc/arm/Bv9ARM.ch06.html#statistics - -// example configuration in /etc/netdata/node.d/named.conf -// the module supports auto-detection if bind is running at localhost - -/* -{ - "enable_autodetect": true, - "update_every": 5, - "servers": [ - { - "name": "bind1", - "url": "http://127.0.0.1:8888/json/v1/server", - "update_every": 1 - }, - { - "name": "bind2", - "url": "http://10.0.0.1:8888/xml/v3/server", - "update_every": 2 - } - ] -} -*/ - -// the following is the bind named.conf configuration required - -/* -statistics-channels { - inet 127.0.0.1 port 8888 allow { 127.0.0.1; }; -}; -*/ - -require('url'); -require('http'); -var XML = require('pixl-xml'); -var netdata = require('netdata'); - -if(netdata.options.DEBUG === true) netdata.debug('loaded', __filename, 'plugin'); - -var named = { - name: __filename, - enable_autodetect: true, - update_every: 1, - base_priority: 60000, - charts: {}, - - chartFromMembersCreate: function(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) { - var chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' ' + title_suffix, // the title of the chart - units: units, // the units of the chart dimensions - family: family, // the family of the chart - context: context, // the context of the chart - type: type, // the type of the chart - priority: priority, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: {} - }; - - var found = 0; - var dims = Object.keys(obj); - var len = dims.length; - for(var i = 0; i < len ;i++) { - var x = dims[i]; - - if(typeof(obj[x]) !== 'undefined' && obj[x] !== 0) { - found++; - chart.dimensions[x] = { - id: x, // the unique id of the dimension - name: x, // the name of the dimension - algorithm: algorithm, // the id of the netdata algorithm - multiplier: multiplier, // the multiplier - divisor: divisor, // the divisor - hidden: false // is hidden (boolean) - }; - } - } - - if(!found) - return null; - - chart = service.chart(id, chart); - this.charts[id] = chart; - return chart; - }, - - chartFromMembers: function(service, obj, id_suffix, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor) { - var id = 'named_' + service.name + '.' + id_suffix; - var chart = this.charts[id]; - var dims, len, x, i; - - if(typeof chart === 'undefined') { - chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor); - if(chart === null) return false; - } - else { - // check if we need to re-generate the chart - dims = Object.keys(obj); - len = dims.length; - for(i = 0; i < len ;i++) { - x = dims[i]; - if(typeof(chart.dimensions[x]) === 'undefined') { - chart = this.chartFromMembersCreate(service, obj, id, title_suffix, units, family, context, type, priority, algorithm, multiplier, divisor); - if(chart === null) return false; - break; - } - } - } - - service.begin(chart); - - var found = 0; - dims = Object.keys(obj); - len = dims.length; - for(i = 0; i < len ;i++) { - x = dims[i]; - if(typeof(chart.dimensions[x]) !== 'undefined') { - found++; - service.set(x, obj[x]); - } - } - - service.end(); - - return (found > 0); - }, - - // an index to map values to different charts - lookups: { - nsstats: {}, - resolver_stats: {}, - numfetch: {} - }, - - // transform the XML response of bind - // to the JSON response of bind - xml2js: function(service, data_xml) { - var d = XML.parse(data_xml); - if(d === null) return null; - - var a, aa, alen, alen2; - - var data = {}; - var len = d.server.counters.length; - while(len--) { - a = d.server.counters[len]; - if(typeof a.counter === 'undefined') continue; - if(a.type === 'opcode') a.type = 'opcodes'; - else if(a.type === 'qtype') a.type = 'qtypes'; - else if(a.type === 'nsstat') a.type = 'nsstats'; - aa = data[a.type] = {}; - alen = 0; - alen2 = a.counter.length; - while(alen < alen2) { - aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data, 10); - alen++; - } - } - - data.views = {}; - var vlen = d.views.view.length; - while(vlen--) { - var vname = d.views.view[vlen].name; - data.views[vname] = { resolver: {} }; - len = d.views.view[vlen].counters.length; - while(len--) { - a = d.views.view[vlen].counters[len]; - if(typeof a.counter === 'undefined') continue; - if(a.type === 'resstats') a.type = 'stats'; - else if(a.type === 'resqtype') a.type = 'qtypes'; - else if(a.type === 'adbstat') a.type = 'adb'; - aa = data.views[vname].resolver[a.type] = {}; - alen = 0; - alen2 = a.counter.length; - while(alen < alen2) { - aa[a.counter[alen].name] = parseInt(a.counter[alen]._Data, 10); - alen++; - } - } - } - - return data; - }, - - processResponse: function(service, data) { - if(data !== null) { - var r, x, look, id, chart, keys, len; - - // parse XML or JSON - // pepending on the URL given - if(service.request.path.match(/^\/xml/) !== null) - r = named.xml2js(service, data); - else - r = JSON.parse(data); - - if(typeof r === 'undefined' || r === null) { - service.error("Cannot parse these data: " + data.toString()); - return; - } - - if(service.added !== true) - service.commit(); - - if(typeof r.nsstats !== 'undefined') { - // we split the nsstats object to several others - var global_requests = {}, global_requests_enable = false; - var global_failures = {}, global_failures_enable = false; - var global_failures_detail = {}, global_failures_detail_enable = false; - var global_updates = {}, global_updates_enable = false; - var protocol_queries = {}, protocol_queries_enable = false; - var global_queries = {}, global_queries_enable = false; - var global_queries_success = {}, global_queries_success_enable = false; - var default_enable = false; - var RecursClients = 0; - - // RecursClients is an absolute value - if(typeof r.nsstats['RecursClients'] !== 'undefined') { - RecursClients = r.nsstats['RecursClients']; - delete r.nsstats['RecursClients']; - } - - keys = Object.keys(r.nsstats); - len = keys.length; - while(len--) { - x = keys[len]; - - // we maintain an index of the values found - // mapping them to objects split - - look = named.lookups.nsstats[x]; - if(typeof look === 'undefined') { - // a new value, not found in the index - // index it: - if(x === 'Requestv4') { - named.lookups.nsstats[x] = { - name: 'IPv4', - type: 'global_requests' - }; - } - else if(x === 'Requestv6') { - named.lookups.nsstats[x] = { - name: 'IPv6', - type: 'global_requests' - }; - } - else if(x === 'QryFailure') { - named.lookups.nsstats[x] = { - name: 'failures', - type: 'global_failures' - }; - } - else if(x === 'QryUDP') { - named.lookups.nsstats[x] = { - name: 'UDP', - type: 'protocol_queries' - }; - } - else if(x === 'QryTCP') { - named.lookups.nsstats[x] = { - name: 'TCP', - type: 'protocol_queries' - }; - } - else if(x === 'QrySuccess') { - named.lookups.nsstats[x] = { - name: 'queries', - type: 'global_queries_success' - }; - } - else if(x.match(/QryRej$/) !== null) { - named.lookups.nsstats[x] = { - name: x, - type: 'global_failures_detail' - }; - } - else if(x.match(/^Qry/) !== null) { - named.lookups.nsstats[x] = { - name: x, - type: 'global_queries' - }; - } - else if(x.match(/^Update/) !== null) { - named.lookups.nsstats[x] = { - name: x, - type: 'global_updates' - }; - } - else { - // values not mapped, will remain - // in the default map - named.lookups.nsstats[x] = { - name: x, - type: 'default' - }; - } - - look = named.lookups.nsstats[x]; - // netdata.error('lookup nsstats value: ' + x + ' >>> ' + named.lookups.nsstats[x].type); - } - - switch(look.type) { - case 'global_requests': global_requests[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_requests_enable = true; break; - case 'global_queries': global_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_enable = true; break; - case 'global_queries_success': global_queries_success[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_queries_success_enable = true; break; - case 'global_updates': global_updates[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_updates_enable = true; break; - case 'protocol_queries': protocol_queries[look.name] = r.nsstats[x]; delete r.nsstats[x]; protocol_queries_enable = true; break; - case 'global_failures': global_failures[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_enable = true; break; - case 'global_failures_detail': global_failures_detail[look.name] = r.nsstats[x]; delete r.nsstats[x]; global_failures_detail_enable = true; break; - default: default_enable = true; break; - } - } - - if(global_requests_enable === true) - 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); - - if(global_queries_success_enable === true) - 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); - - if(protocol_queries_enable === true) - 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); - - if(global_queries_enable === true) - 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); - - if(global_updates_enable === true) - 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); - - if(global_failures_enable === true) - 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); - - if(global_failures_detail_enable === true) - 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); - - if(default_enable === true) - 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); - - // RecursClients chart - id = 'named_' + service.name + '.recursive_clients'; - chart = named.charts[id]; - - if(typeof chart === 'undefined') { - chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' Bind, Current Recursive Clients', // the title of the chart - units: 'clients', // the units of the chart dimensions - family: 'clients', // the family of the chart - context: 'named.recursive_clients', // the context of the chart - type: netdata.chartTypes.line, // the type of the chart - priority: named.base_priority + 1, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: { - 'clients': { - id: 'clients', // the unique id of the dimension - name: '', // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: 1, // the divisor - hidden: false // is hidden (boolean) - } - } - }; - - chart = service.chart(id, chart); - named.charts[id] = chart; - } - - service.begin(chart); - service.set('clients', RecursClients); - service.end(); - } - - if(typeof r.opcodes !== 'undefined') - 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); - - if(typeof r.qtypes !== 'undefined') - 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); - - if(typeof r.sockstats !== 'undefined') - 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); - - if(typeof r.views !== 'undefined') { - keys = Object.keys(r.views); - len = keys.length; - while(len--) { - x = keys[len]; - var resolver = r.views[x].resolver; - - if(typeof resolver !== 'undefined') { - if(typeof resolver.stats !== 'undefined') { - var NumFetch = 0; - var key = service.name + '.' + x; - var rtt = {}, rtt_enable = false; - default_enable = false; - - // NumFetch is an absolute value - if(typeof resolver.stats['NumFetch'] !== 'undefined') { - named.lookups.numfetch[key] = true; - NumFetch = resolver.stats['NumFetch']; - delete resolver.stats['NumFetch']; - } - if(typeof resolver.stats['BucketSize'] !== 'undefined') { - delete resolver.stats['BucketSize']; - } - - // split the QryRTT* from the main chart - var ykeys = Object.keys(resolver.stats); - var ylen = ykeys.length; - while(ylen--) { - var y = ykeys[ylen]; - - // we maintain an index of the values found - // mapping them to objects split - - look = named.lookups.resolver_stats[y]; - if(typeof look === 'undefined') { - if(y.match(/^QryRTT/) !== null) { - named.lookups.resolver_stats[y] = { - name: y, - type: 'rtt' - }; - } - else { - named.lookups.resolver_stats[y] = { - name: y, - type: 'default' - }; - } - - look = named.lookups.resolver_stats[y]; - // netdata.error('lookup resolver stats value: ' + y + ' >>> ' + look.type); - } - - switch(look.type) { - case 'rtt': rtt[look.name] = resolver.stats[y]; delete resolver.stats[y]; rtt_enable = true; break; - default: default_enable = true; break; - } - } - - if(rtt_enable) - 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); - - if(default_enable) - 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); - - // NumFetch chart - if(typeof named.lookups.numfetch[key] !== 'undefined') { - id = 'named_' + service.name + '.view_resolver_numfetch_' + x; - chart = named.charts[id]; - - if(typeof chart === 'undefined') { - chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' Bind, ' + x + ' View, Resolver Active Queries', // the title of the chart - units: 'queries', // the units of the chart dimensions - family: 'view_' + x, // the family of the chart - context: 'named.resolver_active_queries', // the context of the chart - type: netdata.chartTypes.line, // the type of the chart - priority: named.base_priority + 1001, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: { - 'queries': { - id: 'queries', // the unique id of the dimension - name: '', // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: 1, // the divisor - hidden: false // is hidden (boolean) - } - } - }; - - chart = service.chart(id, chart); - named.charts[id] = chart; - } - - service.begin(chart); - service.set('queries', NumFetch); - service.end(); - } - } - } - - if(typeof resolver.qtypes !== 'undefined') - 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); - - //if(typeof resolver.cache !== 'undefined') - // 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); - - if(typeof resolver.cachestats['CacheHits'] !== 'undefined' && resolver.cachestats['CacheHits'] > 0) { - id = 'named_' + service.name + '.view_resolver_cachehits_' + x; - chart = named.charts[id]; - - if(typeof chart === 'undefined') { - chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' Bind, ' + x + ' View, Resolver Cache Hits', // the title of the chart - units: 'operations/s', // the units of the chart dimensions - family: 'view_' + x, // the family of the chart - context: 'named.resolver_cache_hits', // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: named.base_priority + 1100, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: { - 'CacheHits': { - id: 'CacheHits', // the unique id of the dimension - name: 'hits', // the name of the dimension - algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: 1, // the divisor - hidden: false // is hidden (boolean) - }, - 'CacheMisses': { - id: 'CacheMisses', // the unique id of the dimension - name: 'misses', // the name of the dimension - algorithm: netdata.chartAlgorithms.incremental,// the id of the netdata algorithm - multiplier: -1, // the multiplier - divisor: 1, // the divisor - hidden: false // is hidden (boolean) - } - } - }; - - chart = service.chart(id, chart); - named.charts[id] = chart; - } - - service.begin(chart); - service.set('CacheHits', resolver.cachestats['CacheHits']); - service.set('CacheMisses', resolver.cachestats['CacheMisses']); - service.end(); - } - - // this is wrong, it contains many types of info: - // 1. CacheHits, CacheMisses - incremental (added above) - // 2. QueryHits, QueryMisses - incremental - // 3. DeleteLRU, DeleteTTL - incremental - // 4. CacheNodes, CacheBuckets - absolute - // 5. TreeMemTotal, TreeMemInUse - absolute - // 6. HeapMemMax, HeapMemTotal, HeapMemInUse - absolute - //if(typeof resolver.cachestats !== 'undefined') - // 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); - - //if(typeof resolver.adb !== 'undefined') - // 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); - } - } - } - }, - - // module.serviceExecute() - // this function is called only from this module - // its purpose is to prepare the request and call - // netdata.serviceExecute() - serviceExecute: function(name, a_url, update_every) { - if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': url: ' + a_url + ', update_every: ' + update_every); - var service = netdata.service({ - name: name, - request: netdata.requestFromURL(a_url), - update_every: update_every, - module: this - }); - - service.execute(this.processResponse); - }, - - configure: function(config) { - var added = 0; - - if(this.enable_autodetect === true) { - this.serviceExecute('local', 'http://localhost:8888/json/v1/server', this.update_every); - added++; - } - - if(typeof(config.servers) !== 'undefined') { - var len = config.servers.length; - while(len--) { - if(typeof config.servers[len].update_every === 'undefined') - config.servers[len].update_every = this.update_every; - - this.serviceExecute(config.servers[len].name, config.servers[len].url, config.servers[len].update_every); - added++; - } - } - - return added; - }, - - // module.update() - // this is called repeatedly to collect data, by calling - // netdata.serviceExecute() - update: function(service, callback) { - service.execute(function(serv, data) { - service.module.processResponse(serv, data); - callback(); - }); - } -}; - -module.exports = named; diff --git a/collectors/node.d.plugin/node.d.conf b/collectors/node.d.plugin/node.d.conf index 95aec99ce..c79274a5e 100644 --- a/collectors/node.d.plugin/node.d.conf +++ b/collectors/node.d.plugin/node.d.conf @@ -14,12 +14,6 @@ "___help_modules": "Enable/disable the following modules. Give only XXX for node.d/XXX.node.js",
"modules": {
- "named": {
- "enabled": true
- },
- "sma_webbox": {
- "enabled": true
- },
"snmp": {
"enabled": true
}
diff --git a/collectors/node.d.plugin/sma_webbox/Makefile.inc b/collectors/node.d.plugin/sma_webbox/Makefile.inc deleted file mode 100644 index 38f2fe97a..000000000 --- a/collectors/node.d.plugin/sma_webbox/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# THIS IS NOT A COMPLETE Makefile -# IT IS INCLUDED BY ITS PARENT'S Makefile.am -# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT - -# install these files -dist_node_DATA += sma_webbox/sma_webbox.node.js -# dist_nodeconfig_DATA += sma_webbox/sma_webbox.conf - -# do not install these files, but include them in the distribution -dist_noinst_DATA += sma_webbox/README.md sma_webbox/Makefile.inc - diff --git a/collectors/node.d.plugin/sma_webbox/README.md b/collectors/node.d.plugin/sma_webbox/README.md deleted file mode 100644 index 99e093b70..000000000 --- a/collectors/node.d.plugin/sma_webbox/README.md +++ /dev/null @@ -1,33 +0,0 @@ -<!-- -title: "SMA Sunny WebBox monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/sma_webbox/README.md -sidebar_label: "SMA Sunny WebBox" ---> - -# SMA Sunny WebBox monitoring with Netdata - -Monitoring for the [SMA Sunny -WebBox](https://www.sma-sunny.com/en/questions-and-answers-on-discontinuation-of-the-sunny-webbox/). - -The module supports any number of name servers: - -```json -{ - "enable_autodetect": false, - "update_every": 5, - "servers": [ - { - "name": "plant1", - "hostname": "10.0.1.1", - "update_every": 10 - }, - { - "name": "plant2", - "hostname": "10.0.2.1", - "update_every": 15 - } - ] -} -``` - -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2Fsma_webbox%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/node.d.plugin/sma_webbox/sma_webbox.node.js b/collectors/node.d.plugin/sma_webbox/sma_webbox.node.js deleted file mode 100644 index f32b65714..000000000 --- a/collectors/node.d.plugin/sma_webbox/sma_webbox.node.js +++ /dev/null @@ -1,239 +0,0 @@ -'use strict'; -// SPDX-License-Identifier: GPL-3.0-or-later - -// This program will connect to one or more SMA Sunny Webboxes -// to get the Solar Power Generated (current, today, total). - -// example configuration in /etc/netdata/node.d/sma_webbox.conf -/* -{ - "enable_autodetect": false, - "update_every": 5, - "servers": [ - { - "name": "plant1", - "hostname": "10.0.1.1", - "update_every": 10 - }, - { - "name": "plant2", - "hostname": "10.0.2.1", - "update_every": 15 - } - ] -} -*/ - -require('url'); -require('http'); -var netdata = require('netdata'); - -if(netdata.options.DEBUG === true) netdata.debug('loaded ' + __filename + ' plugin'); - -var webbox = { - name: __filename, - enable_autodetect: true, - update_every: 1, - base_priority: 60000, - charts: {}, - - processResponse: function(service, data) { - if(data !== null) { - var r = JSON.parse(data); - - var d = { - 'GriPwr': { - unit: null, - value: null - }, - 'GriEgyTdy': { - unit: null, - value: null - }, - 'GriEgyTot': { - unit: null, - value: null - } - }; - - // parse the webbox response - // and put it in our d object - var found = 0; - var len = r.result.overview.length; - while(len--) { - var e = r.result.overview[len]; - if(typeof(d[e.meta]) !== 'undefined') { - found++; - d[e.meta].value = e.value; - d[e.meta].unit = e.unit; - } - } - - // add the service - if(found > 0 && service.added !== true) - service.commit(); - - - // Grid Current Power Chart - if(d['GriPwr'].value !== null) { - const id = 'smawebbox_' + service.name + '.current'; - let chart = webbox.charts[id]; - - if(typeof chart === 'undefined') { - chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' Current Grid Power', // the title of the chart - units: d['GriPwr'].unit, // the units of the chart dimensions - family: 'now', // the family of the chart - context: 'smawebbox.grid_power', // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: webbox.base_priority + 1, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: { - 'GriPwr': { - id: 'GriPwr', // the unique id of the dimension - name: 'power', // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: 1, // the divisor - hidden: false // is hidden (boolean) - } - } - }; - - chart = service.chart(id, chart); - webbox.charts[id] = chart; - } - - service.begin(chart); - service.set('GriPwr', Math.round(d['GriPwr'].value)); - service.end(); - } - - if(d['GriEgyTdy'].value !== null) { - const id = 'smawebbox_' + service.name + '.today'; - let chart = webbox.charts[id]; - - if(typeof chart === 'undefined') { - chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' Today Grid Power', // the title of the chart - units: d['GriEgyTdy'].unit, // the units of the chart dimensions - family: 'today', // the family of the chart - context: 'smawebbox.grid_power_today', // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: webbox.base_priority + 2, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: { - 'GriEgyTdy': { - id: 'GriEgyTdy', // the unique id of the dimension - name: 'power', // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: 1000, // the divisor - hidden: false // is hidden (boolean) - } - } - }; - - chart = service.chart(id, chart); - webbox.charts[id] = chart; - } - - service.begin(chart); - service.set('GriEgyTdy', Math.round(d['GriEgyTdy'].value * 1000)); - service.end(); - } - - if(d['GriEgyTot'].value !== null) { - const id = 'smawebbox_' + service.name + '.total'; - let chart = webbox.charts[id]; - - if(typeof chart === 'undefined') { - chart = { - id: id, // the unique id of the chart - name: '', // the unique name of the chart - title: service.name + ' Total Grid Power', // the title of the chart - units: d['GriEgyTot'].unit, // the units of the chart dimensions - family: 'total', // the family of the chart - context: 'smawebbox.grid_power_total', // the context of the chart - type: netdata.chartTypes.area, // the type of the chart - priority: webbox.base_priority + 3, // the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: { - 'GriEgyTot': { - id: 'GriEgyTot', // the unique id of the dimension - name: 'power', // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: 1, // the multiplier - divisor: 1000, // the divisor - hidden: false // is hidden (boolean) - } - } - }; - - chart = service.chart(id, chart); - webbox.charts[id] = chart; - } - - service.begin(chart); - service.set('GriEgyTot', Math.round(d['GriEgyTot'].value * 1000)); - service.end(); - } - } - }, - - // module.serviceExecute() - // this function is called only from this module - // its purpose is to prepare the request and call - // netdata.serviceExecute() - serviceExecute: function(name, hostname, update_every) { - if(netdata.options.DEBUG === true) netdata.debug(this.name + ': ' + name + ': hostname: ' + hostname + ', update_every: ' + update_every); - - var service = netdata.service({ - name: name, - request: netdata.requestFromURL('http://' + hostname + '/rpc'), - update_every: update_every, - module: this - }); - service.postData = 'RPC={"proc":"GetPlantOverview","format":"JSON","version":"1.0","id":"1"}'; - service.request.method = 'POST'; - service.request.headers['Content-Length'] = service.postData.length; - - service.execute(this.processResponse); - }, - - configure: function(config) { - var added = 0; - - if(typeof(config.servers) !== 'undefined') { - var len = config.servers.length; - while(len--) { - if(typeof config.servers[len].update_every === 'undefined') - config.servers[len].update_every = this.update_every; - - if(config.servers[len].update_every < 5) - config.servers[len].update_every = 5; - - this.serviceExecute(config.servers[len].name, config.servers[len].hostname, config.servers[len].update_every); - added++; - } - } - - return added; - }, - - // module.update() - // this is called repeatedly to collect data, by calling - // netdata.serviceExecute() - update: function(service, callback) { - service.execute(function(serv, data) { - service.module.processResponse(serv, data); - callback(); - }); - }, -}; - -module.exports = webbox; diff --git a/collectors/node.d.plugin/snmp/README.md b/collectors/node.d.plugin/snmp/README.md index df6d7eaca..2df94c7b5 100644 --- a/collectors/node.d.plugin/snmp/README.md +++ b/collectors/node.d.plugin/snmp/README.md @@ -442,4 +442,4 @@ This switch has a very slow SNMP processors. To respond, it needs about 8 second } ``` -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2Fsnmp%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) + diff --git a/collectors/node.d.plugin/stiebeleltron/Makefile.inc b/collectors/node.d.plugin/stiebeleltron/Makefile.inc deleted file mode 100644 index 0c6e1e213..000000000 --- a/collectors/node.d.plugin/stiebeleltron/Makefile.inc +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later - -# THIS IS NOT A COMPLETE Makefile -# IT IS INCLUDED BY ITS PARENT'S Makefile.am -# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT - -# install these files -dist_node_DATA += stiebeleltron/stiebeleltron.node.js -# dist_nodeconfig_DATA += stiebeleltron/stiebeleltron.conf - -# do not install these files, but include them in the distribution -dist_noinst_DATA += stiebeleltron/README.md stiebeleltron/Makefile.inc - diff --git a/collectors/node.d.plugin/stiebeleltron/README.md b/collectors/node.d.plugin/stiebeleltron/README.md deleted file mode 100644 index 59bbf703c..000000000 --- a/collectors/node.d.plugin/stiebeleltron/README.md +++ /dev/null @@ -1,525 +0,0 @@ -<!-- -title: "Stiebel Eltron ISG monitoring with Netdata" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/node.d.plugin/stiebeleltron/README.md -sidebar_label: "Stiebel Eltron ISG" ---> - -# Stiebel Eltron ISG monitoring with Netdata - -Collects metrics from the configured heat pump and hot water installation from Stiebel Eltron ISG web. - -**Requirements** - -- Configuration file `stiebeleltron.conf` in the node.d Netdata config dir (default: `/etc/netdata/node.d/stiebeleltron.conf`) -- Stiebel Eltron ISG web with network access (http), without password login - -The charts are configurable, however, the provided default configuration collects the following: - -1. **General** - - - Outside temperature in C - - Condenser temperature in C - - Heating circuit pressure in bar - - Flow rate in l/min - - Output of water and heat pumps in % - -2. **Heating** - - - Heat circuit 1 temperature in C (set/actual) - - Heat circuit 2 temperature in C (set/actual) - - Flow temperature in C (set/actual) - - Buffer temperature in C (set/actual) - - Pre-flow temperature in C - -3. **Hot Water** - - - Hot water temperature in C (set/actual) - -4. **Room Temperature** - - - Heat circuit 1 room temperature in C (set/actual) - - Heat circuit 2 room temperature in C (set/actual) - -5. **Electric Reheating** - - - Dual Mode Reheating temperature in C (hot water/heating) - -6. **Process Data** - - - Remaining compressor rest time in s - -7. **Runtime** - - - Compressor runtime hours (hot water/heating) - - Reheating runtime hours (reheating 1/reheating 2) - -8. **Energy** - - - Compressor today in kWh (hot water/heating) - - Compressor Total in kWh (hot water/heating) - -## configuration - -If no configuration is given, the module will be disabled. Each `update_every` is optional, the default is `10`. - ---- - -[Stiebel Eltron Heat pump system with ISG](https://www.stiebel-eltron.com/en/home/products-solutions/renewables/controller_energymanagement/internet_servicegateway/isg_web.html) - -Original author: BrainDoctor (github) - -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. - -### Testing - -This plugin has been tested within the following environment: - -- ISG version: 8.5.6 -- MFG version: 12 -- Controller version: 9 -- July (summer time, not much activity) -- Interface language: English -- login- and password-less ISG web access (without HTTPS it's useless anyway) -- Heatpump model: WPL 25 I-2 -- Hot water boiler model: 820 WT 1 - -So, if the language is set to english, copy the following configuration into `/etc/netdata/node.d/stiebeleltron.conf` and change the `url`s. - -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. - -### How to update the config - -- The dimensions support variable digits, the default is `1`. Most of the values printed by ISG are using 1 digit, some use 2. -- The dimensions also support the `multiplier` and `divisor` attributes, however the divisor gets overridden by `digits`, if specified. Default is `1`. -- 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. - 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. - -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. - -### Configuration template - -```json -{ - "enable_autodetect": false, - "update_every": 10, - "pages": [ - { - "name": "System", - "id": "system", - "url": "http://machine.ip.or.dns/?s=1,0", - "update_every": 10, - "categories": [ - { - "id": "eletricreheating", - "name": "electric reheating", - "charts": [ - { - "title": "Dual Mode Reheating Temperature", - "id": "reheatingtemp", - "unit": "Celsius", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Heating", - "id": "dualmodeheatingtemp", - "regex": "DUAL MODE TEMP HEATING<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - }, - { - "name": "Hot Water", - "id" : "dualmodehotwatertemp", - "regex": "DUAL MODE TEMP DHW<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - } - ] - }, - { - "id": "roomtemp", - "name": "room temperature", - "charts": [ - { - "title": "Heat Circuit 1", - "id": "hc1", - "unit": "Celsius", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Actual", - "id": "actual", - "regex": "<tr class=\"even\">\\s*<td.*>ACTUAL TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - }, - { - "name": "Set", - "id" : "set", - "regex": "<tr class=\"odd\">\\s*<td.*>SET TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - } - ] - }, - { - "title": "Heat Circuit 2", - "id": "hc2", - "unit": "Celsius", - "type": "line", - "prio": 2, - "dimensions": [ - { - "name": "Actual", - "id": "actual", - "regex": "<tr class=\"even\">\\s*<td.*>ACTUAL TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - }, - { - "name": "Set", - "id" : "set", - "regex": "<tr class=\"odd\">\\s*<td.*>SET TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - } - ] - } - ] - }, - { - "id": "heating", - "name": "heating", - "charts": [ - { - "title": "Heat Circuit 1", - "id": "hc1", - "unit": "Celsius", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Actual", - "id": "actual", - "regex": "<tr class=\"odd\">\\s*<td.*>ACTUAL TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - }, - { - "name": "Set", - "id" : "set", - "regex": "<tr class=\"even\">\\s*<td.*>SET TEMPERATURE HC 1<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - } - ] - }, - { - "title": "Heat Circuit 2", - "id": "hc2", - "unit": "Celsius", - "type": "line", - "prio": 2, - "dimensions": [ - { - "name": "Actual", - "id": "actual", - "regex": "<tr class=\"odd\">\\s*<td.*>ACTUAL TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - }, - { - "name": "Set", - "id" : "set", - "regex": "<tr class=\"even\">\\s*<td.*>SET TEMPERATURE HC 2<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - } - ] - }, - { - "title": "Flow Temperature", - "id": "flowtemp", - "unit": "Celsius", - "type": "line", - "prio": 3, - "dimensions": [ - { - "name": "Heating", - "id": "heating", - "regex": "ACTUAL FLOW TEMPERATURE WP<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - }, - { - "name": "Reheating", - "id" : "reheating", - "regex": "ACTUAL FLOW TEMPERATURE NHZ<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - }, - { - "title": "Buffer Temperature", - "id": "buffertemp", - "unit": "Celsius", - "type": "line", - "prio": 4, - "dimensions": [ - { - "name": "Actual", - "id": "actual", - "regex": "ACTUAL BUFFER TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - }, - { - "name": "Set", - "id" : "set", - "regex": "SET BUFFER TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - }, - { - "title": "Fixed Temperature", - "id": "fixedtemp", - "unit": "Celsius", - "type": "line", - "prio": 5, - "dimensions": [ - { - "name": "Set", - "id" : "setfixed", - "regex": "SET FIXED TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - }, - { - "title": "Pre-flow Temperature", - "id": "preflowtemp", - "unit": "Celsius", - "type": "line", - "prio": 6, - "dimensions": [ - { - "name": "Actual", - "id": "actualreturn", - "regex": "ACTUAL RETURN TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - } - ] - }, - { - "id": "hotwater", - "name": "hot water", - "charts": [ - { - "title": "Hot Water Temperature", - "id": "hotwatertemp", - "unit": "Celsius", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Actual", - "id": "actual", - "regex": "ACTUAL TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - }, - { - "name": "Set", - "id" : "set", - "regex": "SET TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - } - ] - }, - { - "id": "general", - "name": "general", - "charts": [ - { - "title": "Outside Temperature", - "id": "outside", - "unit": "Celsius", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Outside temperature", - "id": "outsidetemp", - "regex": "OUTSIDE TEMPERATURE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>\\s*<\\\/tr>" - } - ] - }, - { - "title": "Condenser Temperature", - "id": "condenser", - "unit": "Celsius", - "type": "line", - "prio": 2, - "dimensions": [ - { - "name": "Condenser", - "id": "condenser", - "regex": "CONDENSER TEMP\\.<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - }, - { - "title": "Heating Circuit Pressure", - "id": "heatingcircuit", - "unit": "bar", - "type": "line", - "prio": 3, - "dimensions": [ - { - "name": "Heating Circuit", - "id": "heatingcircuit", - "digits": 2, - "regex": "PRESSURE HTG CIRC<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]*).*<\\\/td>" - } - ] - }, - { - "title": "Flow Rate", - "id": "flowrate", - "unit": "liters/min", - "type": "line", - "prio": 4, - "dimensions": [ - { - "name": "Flow Rate", - "id": "flowrate", - "digits": 2, - "regex": "FLOW RATE<\\\/td>\\s*<td.*>(-?[0-9]+,[0-9]+).*<\\\/td>" - } - ] - }, - { - "title": "Output", - "id": "output", - "unit": "%", - "type": "line", - "prio": 5, - "dimensions": [ - { - "name": "Heat Pump", - "id": "outputheatpump", - "regex": "OUTPUT HP<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*).*<\\\/td>" - }, - { - "name": "Water Pump", - "id": "intpumprate", - "regex": "INT PUMP RATE<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*).*<\\\/td>" - } - ] - } - ] - } - ] - }, - { - "name": "Heat Pump", - "id": "heatpump", - "url": "http://machine.ip.or.dns/?s=1,1", - "update_every": 10, - "categories": [ - { - "id": "runtime", - "name": "runtime", - "charts": [ - { - "title": "Compressor", - "id": "compressor", - "unit": "h", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Heating", - "id": "heating", - "regex": "RNT COMP 1 HEA<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - }, - { - "name": "Hot Water", - "id" : "hotwater", - "regex": "RNT COMP 1 DHW<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - } - ] - }, - { - "title": "Reheating", - "id": "reheating", - "unit": "h", - "type": "line", - "prio": 2, - "dimensions": [ - { - "name": "Reheating 1", - "id": "rh1", - "regex": "BH 1<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - }, - { - "name": "Reheating 2", - "id" : "rh2", - "regex": "BH 2<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - } - ] - } - ] - }, - { - "id": "processdata", - "name": "process data", - "charts": [ - { - "title": "Remaining Compressor Rest Time", - "id": "remaincomp", - "unit": "s", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Timer", - "id": "timer", - "regex": "COMP DLAY CNTR<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - } - ] - } - ] - }, - { - "id": "energy", - "name": "energy", - "charts": [ - { - "title": "Compressor Today", - "id": "compressorday", - "unit": "kWh", - "type": "line", - "prio": 1, - "dimensions": [ - { - "name": "Heating", - "id": "heating", - "digits": 3, - "regex": "COMPRESSOR HEATING DAY<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - }, - { - "name": "Hot Water", - "id": "hotwater", - "digits": 3, - "regex": "COMPRESSOR DHW DAY<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - } - ] - }, - { - "title": "Compressor Total", - "id": "compressortotal", - "unit": "MWh", - "type": "line", - "prio": 2, - "dimensions": [ - { - "name": "Heating", - "id": "heating", - "digits": 3, - "regex": "COMPRESSOR HEATING TOTAL<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - }, - { - "name": "Hot Water", - "id": "hotwater", - "digits": 3, - "regex": "COMPRESSOR DHW TOTAL<\\\/td>\\s*<td.*>(-?[0-9]+,?[0-9]*)" - } - ] - } - ] - } - ] - } - ] -} -``` - -[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fnode.d.plugin%2Fstiebeleltron%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/collectors/node.d.plugin/stiebeleltron/stiebeleltron.node.js b/collectors/node.d.plugin/stiebeleltron/stiebeleltron.node.js deleted file mode 100644 index 250c26540..000000000 --- a/collectors/node.d.plugin/stiebeleltron/stiebeleltron.node.js +++ /dev/null @@ -1,197 +0,0 @@ -'use strict'; -// SPDX-License-Identifier: GPL-3.0-or-later - -// This program will connect to one Stiebel Eltron ISG for heatpump heating -// to get the heat pump metrics. - -// example configuration in netdata/conf.d/node.d/stiebeleltron.conf.md - -require("url"); -require("http"); -var netdata = require("netdata"); - -netdata.debug("loaded " + __filename + " plugin"); - -var stiebeleltron = { - name: "Stiebel Eltron", - enable_autodetect: false, - update_every: 10, - base_priority: 60000, - charts: {}, - pages: {}, - - createBasicDimension: function (id, name, multiplier, divisor) { - return { - id: id, // the unique id of the dimension - name: name, // the name of the dimension - algorithm: netdata.chartAlgorithms.absolute,// the id of the netdata algorithm - multiplier: multiplier, // the multiplier - divisor: divisor, // the divisor - hidden: false // is hidden (boolean) - }; - }, - - processResponse: function (service, html) { - if (html === null) return; - - // add the service - service.commit(); - - var page = stiebeleltron.pages[service.name]; - var categories = page.categories; - var categoriesCount = categories.length; - while (categoriesCount--) { - var context = { - html: html, - service: service, - category: categories[categoriesCount], - page: page, - chartDefinition: null, - dimension: null - }; - stiebeleltron.processCategory(context); - - } - }, - - processCategory: function (context) { - var charts = context.category.charts; - var chartCount = charts.length; - while (chartCount--) { - context.chartDefinition = charts[chartCount]; - stiebeleltron.processChart(context); - } - }, - - processChart: function (context) { - var dimensions = context.chartDefinition.dimensions; - var dimensionCount = dimensions.length; - context.service.begin(stiebeleltron.getChartFromContext(context)); - - while (dimensionCount--) { - context.dimension = dimensions[dimensionCount]; - stiebeleltron.processDimension(context); - } - context.service.end(); - }, - - processDimension: function (context) { - var dimension = context.dimension; - var match = new RegExp(dimension.regex).exec(context.html); - if (match === null) return; - var value = match[1].replace(",", "."); - // most values have a single digit by default, which requires the values to be multiplied. can be overridden. - if (stiebeleltron.isDefined(dimension.digits)) { - value *= Math.pow(10, dimension.digits); - } else { - value *= 10; - } - context.service.set(stiebeleltron.getDimensionId(context), value); - }, - - getChartFromContext: function (context) { - var chartId = this.getChartId(context); - var chart = stiebeleltron.charts[chartId]; - if (stiebeleltron.isDefined(chart)) return chart; - - var chartDefinition = context.chartDefinition; - var service = context.service; - var dimensions = {}; - - var dimCount = chartDefinition.dimensions.length; - while (dimCount--) { - var dim = chartDefinition.dimensions[dimCount]; - var multiplier = 1; - var divisor = 10; - if (stiebeleltron.isDefined(dim.digits)) divisor = Math.pow(10, Math.max(0, dim.digits)); - if (stiebeleltron.isDefined(dim.multiplier)) multiplier = dim.multiplier; - if (stiebeleltron.isDefined(dim.divisor)) divisor = dim.divisor; - context.dimension = dim; - var dimId = this.getDimensionId(context); - dimensions[dimId] = this.createBasicDimension(dimId, dim.name, multiplier, divisor); - } - - chart = { - id: chartId, - name: '', - title: chartDefinition.title, - units: chartDefinition.unit, - family: context.category.name, - context: 'stiebeleltron.' + context.category.id + '.' + chartDefinition.id, - type: chartDefinition.type, - priority: stiebeleltron.base_priority + chartDefinition.prio,// the priority relative to others in the same family - update_every: service.update_every, // the expected update frequency of the chart - dimensions: dimensions - }; - chart = service.chart(chartId, chart); - stiebeleltron.charts[chartId] = chart; - - return chart; - }, - - // module.serviceExecute() - // this function is called only from this module - // its purpose is to prepare the request and call - // netdata.serviceExecute() - serviceExecute: function (name, uri, update_every) { - netdata.debug(this.name + ': ' + name + ': url: ' + uri + ', update_every: ' + update_every); - - var service = netdata.service({ - name: name, - request: netdata.requestFromURL(uri), - update_every: update_every, - module: this - }); - service.execute(this.processResponse); - }, - - - configure: function (config) { - if (stiebeleltron.isUndefined(config.pages)) return 0; - var added = 0; - var pageCount = config.pages.length; - while (pageCount--) { - var page = config.pages[pageCount]; - // some validation - if (stiebeleltron.isUndefined(page.categories) || page.categories.length < 1) { - netdata.error("Your Stiebel Eltron config is invalid. Disabling plugin."); - return 0; - } - if (stiebeleltron.isUndefined(page.update_every)) page.update_every = this.update_every; - this.pages[page.name] = page; - this.serviceExecute(page.name, page.url, page.update_every); - added++; - } - return added; - }, - - // module.update() - // this is called repeatedly to collect data, by calling - // netdata.serviceExecute() - update: function (service, callback) { - service.execute(function (serv, data) { - service.module.processResponse(serv, data); - callback(); - }); - }, - - getChartId: function (context) { - return "stiebeleltron_" + context.page.id + - "." + context.category.id + - "." + context.chartDefinition.id; - }, - - getDimensionId: function (context) { - return context.dimension.id; - }, - - isUndefined: function (value) { - return typeof value === 'undefined'; - }, - - isDefined: function (value) { - return typeof value !== 'undefined'; - } -}; - -module.exports = stiebeleltron; |