From: Costa Tsaousis Date: Sun, 26 Feb 2017 19:05:09 +0000 (+0200) Subject: Merge pull request #1815 from lfdominguez/master X-Git-Tag: ab-debian_0.20170227.01-0ab1~1^2~6 X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cacc1a70bcb6926a7b56f9f3a2e8948aea29e145;hp=672aed6aaae1e310751600c3463e9d48e8a1bce0;p=netdata.git Merge pull request #1815 from lfdominguez/master New JSON backend --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 893af806..979144e0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ set(NETDATA_SOURCE_FILES src/dictionary.h src/eval.c src/eval.h + src/freebsd_sysctl.c src/global_statistics.c src/global_statistics.h src/health.c @@ -123,7 +124,7 @@ set(NETDATA_SOURCE_FILES src/web_client.h src/web_server.c src/web_server.h - ) + src/rrdhost.c src/rrdfamily.c src/rrdset.c src/rrddim.c src/health_log.c src/health_config.c src/health_json.c src/rrdcalc.c src/rrdcalctemplate.c src/rrdvar.c src/rrddimvar.c src/rrdsetvar.c src/rrdpush.c src/rrdpush.h src/web_api_old.c src/web_api_old.h src/web_api_v1.c src/web_api_v1.h) set(APPS_PLUGIN_SOURCE_FILES src/appconfig.c diff --git a/README.md b/README.md index faf72a07..240ab32b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# netdata [![Build Status](https://travis-ci.org/firehol/netdata.svg?branch=master)](https://travis-ci.org/firehol/netdata) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9140/badge.svg)](https://scan.coverity.com/projects/firehol-netdata) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a994873f30d045b9b4b83606c3eb3498)](https://www.codacy.com/app/netdata/netdata?utm_source=github.com&utm_medium=referral&utm_content=firehol/netdata&utm_campaign=Badge_Grade) [![Code Climate](https://codeclimate.com/github/firehol/netdata/badges/gpa.svg)](https://codeclimate.com/github/firehol/netdata) [![Docker Pulls](https://img.shields.io/docker/pulls/titpetric/netdata.svg)](https://hub.docker.com/r/titpetric/netdata/) +# netdata [![Build Status](https://travis-ci.org/firehol/netdata.svg?branch=master)](https://travis-ci.org/firehol/netdata) [![Coverity Scan Build Status](https://scan.coverity.com/projects/9140/badge.svg)](https://scan.coverity.com/projects/firehol-netdata) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a994873f30d045b9b4b83606c3eb3498)](https://www.codacy.com/app/netdata/netdata?utm_source=github.com&utm_medium=referral&utm_content=firehol/netdata&utm_campaign=Badge_Grade) [![Code Climate](https://codeclimate.com/github/firehol/netdata/badges/gpa.svg)](https://codeclimate.com/github/firehol/netdata) [![Docker Pulls](https://img.shields.io/docker/pulls/titpetric/netdata.svg)](https://hub.docker.com/r/titpetric/netdata/) [![Twitter Follow](https://img.shields.io/twitter/follow/linuxnetdata.svg?style=social&label=netdata%20on%20twitter)](https://twitter.com/linuxnetdata) > *New to netdata? Here is a live demo: [http://my-netdata.io](http://my-netdata.io)* **netdata** is a system for **distributed real-time performance and health monitoring**. @@ -62,7 +62,7 @@ Netdata is featured at /dev/null 2>&1 + "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/apps.plugin" -t >/dev/null 2>&1 setcap_ret=$? fi fi diff --git a/plugins.d/alarm-notify.sh b/plugins.d/alarm-notify.sh index 997ff96a..45d90563 100755 --- a/plugins.d/alarm-notify.sh +++ b/plugins.d/alarm-notify.sh @@ -214,6 +214,7 @@ DEFAULT_RECIPIENT_TWILIO= declare -A role_recipients_twilio=() # hipchat configs +HIPCHAT_SERVER= HIPCHAT_AUTH_TOKEN= DEFAULT_RECIPIENT_HIPCHAT= declare -A role_recipients_hipchat=() @@ -854,16 +855,15 @@ send_twilio() { send_hipchat() { local authtoken="${1}" recipients="${2}" message="${3}" httpcode sent=0 room color sender msg_format notify - if [ "${SEND_HIPCHAT}" = "YES" -a ! -z "${authtoken}" -a ! -z "${recipients}" -a ! -z "${message}" ] - then - + if [ "${SEND_HIPCHAT}" = "YES" -a ! -z "${HIPCHAT_SERVER}" -a ! -z "${authtoken}" -a ! -z "${recipients}" -a ! -z "${message}" ] + then # A label to be shown in addition to the sender's name # Valid length range: 0 - 64. sender="netdata" # Valid values: html, text. # Defaults to 'html'. - msg_format="text" + msg_format="html" # Background color for message. Valid values: yellow, green, red, purple, gray, random. Defaults to 'yellow'. case "${status}" in @@ -884,7 +884,7 @@ send_hipchat() { -H "Content-type: application/json" \ -H "Authorization: Bearer ${authtoken}" \ -d "{\"color\": \"${color}\", \"from\": \"${netdata}\", \"message_format\": \"${msg_format}\", \"message\": \"${message}\", \"notify\": \"${notify}\"}" \ - "https://api.hipchat.com/v2/room/${room}/notification") + "https://${HIPCHAT_SERVER}/v2/room/${room}/notification") if [ "${httpcode}" == "204" ] then diff --git a/plugins.d/python.d.plugin b/plugins.d/python.d.plugin index 126041ab..4fdfae34 100755 --- a/plugins.d/python.d.plugin +++ b/plugins.d/python.d.plugin @@ -73,10 +73,16 @@ try: DICT = OrderedDict msg.info('YAML output is ordered') except ImportError: - ORDERED = False - DICT = dict - msg.info('YAML output is unordered') -else: + try: + from ordereddict import OrderedDict + ORDERED = True + DICT = OrderedDict + msg.info('YAML output is ordered') + except ImportError: + ORDERED = False + DICT = dict + msg.info('YAML output is unordered') +if ORDERED: def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict): class OrderedLoader(Loader): pass diff --git a/python.d/bind_rndc.chart.py b/python.d/bind_rndc.chart.py index 1757598c..357834ff 100644 --- a/python.d/bind_rndc.chart.py +++ b/python.d/bind_rndc.chart.py @@ -50,15 +50,15 @@ class Service(SimpleService): if not run_rndc.returncode: # 'rndc' was found, stats file is exist and readable and we can run 'rndc stats'. Lets go! self.create_charts() - + # BIND APPEND dump on every run 'rndc stats' # that is why stats file size can be VERY large if update_interval too small dump_size_24hr = round(86400 / self.update_every * (int(size_after) - int(size_before)) / 1048576, 3) - + # If update_every too small we should WARN user if self.update_every < 30: self.info('Update_every %s is NOT recommended for use. Increase the value to > 30' % self.update_every) - + self.info('With current update_interval it will be + %s MB every 24hr. ' 'Don\'t forget to create logrotate conf file for %s' % (dump_size_24hr, self.named_stats_path)) @@ -77,12 +77,11 @@ class Service(SimpleService): named.stats file size ) """ - try: current_size = getsize(self.named_stats_path) except OSError: return None, None - + run_rndc = Popen([self.rndc, 'stats'], shell=False) run_rndc.wait() @@ -110,7 +109,7 @@ class Service(SimpleService): return None rndc_stats = dict() - + # Result: dict. # topic = Cache DB RRsets; body = A 178303 NS 86790 ... ; desc = A; value = 178303 # {'Cache DB RRsets': [('A', 178303), ('NS', 286790), ...], @@ -119,14 +118,14 @@ class Service(SimpleService): for regex in self.regex_options: rndc_stats.update({topic: [(desc, int(value)) for value, desc in self.regex_values.findall(body)] for topic, body in findall(regex, raw_data)}) - + nms = dict(rndc_stats.get('Name Server Statistics', [])) - inc_queries = {'i' + k: 0 for k in QUERIES} - inc_queries.update({'i' + k: v for k, v in rndc_stats.get('Incoming Queries', [])}) - out_queries = {'o' + k: 0 for k in QUERIES} - out_queries.update({'o' + k: v for k, v in rndc_stats.get('Outgoing Queries', [])}) - + inc_queries = dict([('i' + k, 0) for k in QUERIES]) + inc_queries.update(dict([('i' + k, v) for k, v in rndc_stats.get('Incoming Queries', [])])) + out_queries = dict([('o' + k, 0) for k in QUERIES]) + out_queries.update(dict([('o' + k, v) for k, v in rndc_stats.get('Outgoing Queries', [])])) + to_netdata = dict() to_netdata['requests'] = sum([v for k, v in nms.items() if 'request' in k and 'received' in k]) to_netdata['responses'] = sum([v for k, v in nms.items() if 'responses' in k and 'sent' in k]) @@ -140,7 +139,7 @@ class Service(SimpleService): to_netdata['duplicate'] = nms.get('duplicate queries received', 0) to_netdata['rejections'] = nms.get('recursive queries rejected', 0) to_netdata['stats_size'] = size - + to_netdata.update(inc_queries) to_netdata.update(out_queries) return to_netdata diff --git a/python.d/fail2ban.chart.py b/python.d/fail2ban.chart.py index 2d80282c..c7d24e8c 100644 --- a/python.d/fail2ban.chart.py +++ b/python.d/fail2ban.chart.py @@ -4,16 +4,18 @@ from base import LogService from re import compile + try: from itertools import filterfalse except ImportError: from itertools import ifilterfalse as filterfalse from os import access as is_accessible, R_OK +from os.path import isdir +from glob import glob priority = 60000 retries = 60 -regex = compile(r'([A-Za-z-]+\]) enabled = ([a-z]+)') - +REGEX = compile(r'\[([A-Za-z-_]+)][^\[\]]*?(? 0) active_leases = [k for k, v in all_leases.items() if is_binding_active(all_leases[k])] @@ -132,9 +131,9 @@ class Service(SimpleService): for pool in self.pools} # Bulding dicts to send to netdata - final_count = {''.join(['le_', k]): v for k, v in pools_count.items()} - final_util = {''.join(['ut_', k]): v for k, v in pools_util.items()} - + final_count = dict([(''.join(['le_', k]), v) for k, v in pools_count.items()]) + final_util = dict([(''.join(['ut_', k]), v) for k, v in pools_util.items()]) + to_netdata = {'total': len(active_leases)} to_netdata.update({'lsize': int(stat(self.leases_path)[6] / 1024)}) to_netdata.update({'ptime': int(raw_leases[1])}) diff --git a/python.d/python_modules/base.py b/python.d/python_modules/base.py index cb3254fd..8fb82178 100644 --- a/python.d/python_modules/base.py +++ b/python.d/python_modules/base.py @@ -31,6 +31,7 @@ from subprocess import Popen, PIPE import threading import msg +import ssl try: PATH = os.getenv('PATH').split(':') @@ -460,7 +461,17 @@ class UrlService(SimpleService): def __add_openers(self): # TODO add error handling - self.opener = urllib2.build_opener() + if self.ss_cert: + try: + ctx = ssl.create_default_context() + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + self.opener = urllib2.build_opener(urllib2.HTTPSHandler(context=ctx)) + except Exception as error: + self.error(str(error)) + self.opener = urllib2.build_opener() + else: + self.opener = urllib2.build_opener() # Proxy handling # TODO currently self.proxies isn't parsed from configuration file @@ -535,7 +546,7 @@ class UrlService(SimpleService): self.password = str(self.configuration['pass']) except (KeyError, TypeError): pass - + self.ss_cert = self.configuration.get('ss_cert') self.__add_openers() test = self._get_data() diff --git a/python.d/smartd_log.chart.py b/python.d/smartd_log.chart.py index c4f855da..e8037237 100644 --- a/python.d/smartd_log.chart.py +++ b/python.d/smartd_log.chart.py @@ -113,7 +113,7 @@ class Service(SimpleService): if not disks: self.error('Can\'t locate any smartd log files in %s' % self.log_path) return False - + # List of namedtuples to track smartd log file size self.disks = [NAMED_DISKS(name=disks[i], size=0, number=i) for i in range(len(disks))] @@ -138,7 +138,7 @@ class Service(SimpleService): break result = f.readline() - result = result.decode(encoding='utf-8') + result = result.decode() result = self.regex.findall(result) queue.put([basename(disk), result]) @@ -147,7 +147,7 @@ class Service(SimpleService): threads, result = list(), list() queue = Queue() to_netdata = dict() - + # If the size has not changed there is no reason to poll log files. disks = [disk for disk in self.disks if self.size_changed(disk)] if disks: @@ -166,7 +166,7 @@ class Service(SimpleService): for elem in result: for a, n, r in elem[1]: to_netdata.update({'_'.join([elem[0], a]): r if self.raw_values else n}) - + self.previous_data.update(to_netdata) return to_netdata or None @@ -185,7 +185,7 @@ class Service(SimpleService): except OSError: # Remove unreadable/nonexisting log files from list of disks and previous_data self.disks.remove(disk) - self.previous_data = {k: v for k, v in self.previous_data.items() if basename(disk.name) not in k} + self.previous_data = dict([(k, v) for k, v in self.previous_data.items() if basename(disk.name) not in k]) return False def create_charts(self): @@ -206,7 +206,7 @@ class Service(SimpleService): self.definitions = dict() units = 'raw' if self.raw_values else 'normalized' - for k, v in {k: v for k, v in SMART_ATTR.items() if k in ORDER}.items(): + for k, v in dict([(k, v) for k, v in SMART_ATTR.items() if k in ORDER]).items(): self.definitions.update({''.join(['attrid', k]): { 'options': [None, v, units, v, 'smartd.attrid' + k, 'line'], 'lines': create_lines(k)}}) diff --git a/python.d/varnish.chart.py b/python.d/varnish.chart.py index 9c1b8de2..2665bb38 100644 --- a/python.d/varnish.chart.py +++ b/python.d/varnish.chart.py @@ -152,10 +152,10 @@ class Service(SimpleService): return None # 1. ALL data from 'varnishstat -1'. t - type(MAIN, MEMPOOL etc) - to_netdata = {k: int(v) for t, k, v in data_all} + to_netdata = dict([(k, int(v)) for t, k, v in data_all]) # 2. ADD backend statistics - to_netdata.update({'_'.join([n, k]): int(v) for n, k, v in data_backend}) + to_netdata.update(dict([('_'.join([n, k]), int(v)) for n, k, v in data_backend])) # 3. ADD additional keys to dict # 3.1 Cache hit/miss/hitpass OVERALL in percent diff --git a/python.d/web_log.chart.py b/python.d/web_log.chart.py index c8b43595..afe45531 100644 --- a/python.d/web_log.chart.py +++ b/python.d/web_log.chart.py @@ -14,7 +14,7 @@ priority = 60000 retries = 60 ORDER = ['response_statuses', 'response_codes', 'bandwidth', 'response_time', 'requests_per_url', 'http_method', - 'requests_per_ipproto', 'clients', 'clients_all'] + 'http_version', 'requests_per_ipproto', 'clients', 'clients_all'] CHARTS = { 'response_codes': { 'options': [None, 'Response Codes', 'requests/s', 'responses', 'web_log.response_codes', 'stacked'], @@ -57,6 +57,10 @@ CHARTS = { 'lines': [ ['GET', 'GET', 'incremental', 1, 1] ]}, + 'http_version': { + 'options': [None, 'Requests Per HTTP Version', 'requests/s', 'http versions', + 'web_log.http_version', 'stacked'], + 'lines': []}, 'requests_per_ipproto': { 'options': [None, 'Requests Per IP Protocol', 'requests/s', 'ip protocols', 'web_log.requests_per_ipproto', 'stacked'], @@ -234,7 +238,8 @@ class Service(LogService): 'method': r'[A-Z]+', 'bytes_sent': r'\d+|-'} optional_dict = {'resp_length': r'\d+', - 'resp_time': r'[\d.]+'} + 'resp_time': r'[\d.]+', + 'http_version': r'\d\.\d'} mandatory_values = set(mandatory_dict) - set(match_dict) if mandatory_values: @@ -275,13 +280,15 @@ class Service(LogService): # 5. Bytes sent 6. Response length 7. Response process time acs_default = re.compile(r'(?P
[\da-f.:]+)' r' -.*?"(?P[A-Z]+)' - r' (?P.*?)"' + r' (?P[^ ]+)' + r' [A-Z]+/(?P\d\.\d)"' r' (?P[1-9]\d{2})' r' (?P\d+|-)') acs_apache_ext_insert = re.compile(r'(?P
[\da-f.:]+)' r' -.*?"(?P[A-Z]+)' - r' (?P.*?)"' + r' (?P[^ ]+)' + r' [A-Z]+/(?P\d\.\d)"' r' (?P[1-9]\d{2})' r' (?P\d+|-)' r' (?P\d+)' @@ -289,7 +296,8 @@ class Service(LogService): acs_apache_ext_append = re.compile(r'(?P
[\da-f.:]+)' r' -.*?"(?P[A-Z]+)' - r' (?P.*?)"' + r' (?P[^ ]+)' + r' [A-Z]+/(?P\d\.\d)"' r' (?P[1-9]\d{2})' r' (?P\d+|-)' r' .*?' @@ -299,7 +307,8 @@ class Service(LogService): acs_nginx_ext_insert = re.compile(r'(?P
[\da-f.:]+)' r' -.*?"(?P[A-Z]+)' - r' (?P.*?)"' + r' (?P[^ ]+)' + r' [A-Z]+/(?P\d\.\d)"' r' (?P[1-9]\d{2})' r' (?P\d+)' r' (?P\d+)' @@ -307,7 +316,8 @@ class Service(LogService): acs_nginx_ext_append = re.compile(r'(?P
[\da-f.:]+)' r' -.*?"(?P[A-Z]+)' - r' (?P.*?)"' + r' (?P[^ ]+)' + r' [A-Z]+/(?P\d\.\d)"' r' (?P[1-9]\d{2})' r' (?P\d+)' r' .*?' @@ -369,6 +379,9 @@ class Service(LogService): ' "" "Requests Per HTTP Method" requests/s "http methods"' \ ' web_log.http_method stacked 2 %s\n' \ 'DIMENSION GET GET incremental\n' % (job_name, self.update_every) + self.http_version_chart = 'CHART %s.http_version' \ + ' "" "Requests Per HTTP Version" requests/s "http versions"' \ + ' web_log.http_version stacked 3 %s\n' % (job_name, self.update_every) # Remove 'request_time' chart from ORDER if resp_time not in match_dict if 'resp_time' not in match_dict: @@ -448,6 +461,9 @@ class Service(LogService): self._get_data_per_url(match_dict['url']) # requests per http method self._get_data_http_method(match_dict['method']) + # requests per http version + if 'http_version' in match_dict: + self._get_data_http_version(match_dict['http_version']) # bandwidth sent bytes_sent = match_dict['bytes_sent'] if '-' not in match_dict['bytes_sent'] else 0 self.data['bytes_sent'] += int(bytes_sent) @@ -503,6 +519,20 @@ class Service(LogService): chart_string_copy, 'http_method') self.data[method] += 1 + def _get_data_http_version(self, http_version): + """ + :param http_version: str: METHOD from parsed line. Ex.: '1.1', '1.0' + :return: + Calls add_new_dimension method If the value is found for the first time + """ + http_version_dim_id = http_version.replace('.', '_') + if http_version_dim_id not in self.data: + chart_string_copy = self.http_version_chart + self.http_version_chart = self.add_new_dimension(http_version_dim_id, + [http_version_dim_id, http_version, 'incremental'], + chart_string_copy, 'http_version') + self.data[http_version_dim_id] += 1 + def _get_data_per_url(self, url): """ :param url: str: URL from parsed line diff --git a/src/Makefile.am b/src/Makefile.am index bec3ef92..a87cd7a8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,7 +39,7 @@ netdata_SOURCES = \ dictionary.c dictionary.h \ eval.c eval.h \ global_statistics.c global_statistics.h \ - health.c health.h \ + health.c health.h health_log.c health_config.c health_json.c \ inlined.h \ log.c log.h \ main.c main.h \ @@ -65,10 +65,22 @@ netdata_SOURCES = \ registry_db.c \ registry_log.c \ rrd.c rrd.h \ + rrddim.c \ + rrdfamily.c \ + rrdhost.c \ + rrdset.c \ + rrdcalc.c \ + rrdcalctemplate.c \ + rrdvar.c \ + rrddimvar.c \ + rrdsetvar.c \ rrd2json.c rrd2json.h \ + rrdpush.c rrdpush.h \ storage_number.c storage_number.h \ unit_test.c unit_test.h \ url.c url.h \ + web_api_old.c web_api_old.h \ + web_api_v1.c web_api_v1.h \ web_buffer.c web_buffer.h \ web_buffer_svg.c web_buffer_svg.h \ web_client.c web_client.h \ @@ -146,19 +158,3 @@ apps_plugin_LDADD = \ $(OPTIONAL_CAP_LIBS) \ $(NULL) -install-data-hook: - if [ `id -u` == 0 ]; then \ - chown root '$(DESTDIR)$(pluginsdir)/apps.plugin' && \ - chmod 0755 '$(DESTDIR)$(pluginsdir)/apps.plugin' && \ - ( setcap cap_dac_read_search,cap_sys_ptrace+ep '$(DESTDIR)$(pluginsdir)/apps.plugin' || \ - chmod 4755 '$(DESTDIR)$(pluginsdir)/apps.plugin' ); \ - else \ - echo; \ - echo "ATTENTION"; \ - echo; \ - echo "$(pluginsdir)/apps.plugin requires escalated capabilities:"; \ - echo "sudo chown root '$(DESTDIR)$(pluginsdir)/apps.plugin'"; \ - echo "sudo chmod 0755 '$(DESTDIR)$(pluginsdir)/apps.plugin'"; \ - echo "sudo setcap cap_dac_read_search,cap_sys_ptrace+ep '$(DESTDIR)$(pluginsdir)/apps.plugin'"; \ - echo; \ - fi diff --git a/src/adaptive_resortable_list.c b/src/adaptive_resortable_list.c index ac525dc6..7ae8ba14 100644 --- a/src/adaptive_resortable_list.c +++ b/src/adaptive_resortable_list.c @@ -65,6 +65,7 @@ void arl_begin(ARL_BASE *base) { info("ARL '%s' has %zu fast searches and %zu slow searches. Is the source really changing so fast?" , base->name, base->fast, base->slow); + /* if(unlikely(base->iteration % 60 == 0)) { info("ARL '%s' statistics: iteration %zu, expected %zu, wanted %zu, allocated %zu, fred %zu, relinkings %zu, found %zu, added %zu, fast %zu, slow %zu" , base->name @@ -82,6 +83,7 @@ void arl_begin(ARL_BASE *base) { // for(e = base->head; e; e = e->next) fprintf(stderr, "%s ", e->name); // fprintf(stderr, "\n"); } + */ } #endif diff --git a/src/appconfig.c b/src/appconfig.c index 81ab01be..50e4c31f 100644 --- a/src/appconfig.c +++ b/src/appconfig.c @@ -2,8 +2,6 @@ #define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2) -pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER; - // ---------------------------------------------------------------------------- // definitions @@ -12,7 +10,7 @@ pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER; #define CONFIG_VALUE_CHANGED 0x04 // has been changed from the loaded value #define CONFIG_VALUE_CHECKED 0x08 // has been checked if the value is different from the default -struct config_value { +struct config_option { avl avl; // the index - this has to be first! uint8_t flags; @@ -22,10 +20,10 @@ struct config_value { char *name; char *value; - struct config_value *next; // config->mutex protects just this + struct config_option *next; // config->mutex protects just this }; -struct config { +struct section { avl avl; uint32_t hash; // a simple hash to speed up searching @@ -33,32 +31,51 @@ struct config { char *name; - struct config *next; // gloabl config_mutex protects just this + struct section *next; // gloabl config_mutex protects just this - struct config_value *values; + struct config_option *values; avl_tree_lock values_index; pthread_mutex_t mutex; // this locks only the writers, to ensure atomic updates // readers are protected using the rwlock in avl_tree_lock -} *config_root = NULL; +}; + +static int appconfig_section_compare(void *a, void *b); + +struct config netdata_config = { + .sections = NULL, + .mutex = PTHREAD_MUTEX_INITIALIZER, + .index = { + { NULL, appconfig_section_compare }, + AVL_LOCK_INITIALIZER + } +}; +struct config stream_config = { + .sections = NULL, + .mutex = PTHREAD_MUTEX_INITIALIZER, + .index = { + { NULL, appconfig_section_compare }, + AVL_LOCK_INITIALIZER + } +}; // ---------------------------------------------------------------------------- // locking -static inline void config_global_write_lock(void) { - pthread_mutex_lock(&config_mutex); +static inline void appconfig_wrlock(struct config *root) { + pthread_mutex_lock(&root->mutex); } -static inline void config_global_unlock(void) { - pthread_mutex_unlock(&config_mutex); +static inline void appconfig_unlock(struct config *root) { + pthread_mutex_unlock(&root->mutex); } -static inline void config_section_write_lock(struct config *co) { +static inline void config_section_wrlock(struct section *co) { pthread_mutex_lock(&co->mutex); } -static inline void config_section_unlock(struct config *co) { +static inline void config_section_unlock(struct section *co) { pthread_mutex_unlock(&co->mutex); } @@ -66,78 +83,72 @@ static inline void config_section_unlock(struct config *co) { // ---------------------------------------------------------------------------- // config name-value index -static int config_value_compare(void* a, void* b) { - if(((struct config_value *)a)->hash < ((struct config_value *)b)->hash) return -1; - else if(((struct config_value *)a)->hash > ((struct config_value *)b)->hash) return 1; - else return strcmp(((struct config_value *)a)->name, ((struct config_value *)b)->name); +static int appconfig_option_compare(void *a, void *b) { + if(((struct config_option *)a)->hash < ((struct config_option *)b)->hash) return -1; + else if(((struct config_option *)a)->hash > ((struct config_option *)b)->hash) return 1; + else return strcmp(((struct config_option *)a)->name, ((struct config_option *)b)->name); } -#define config_value_index_add(co, cv) (struct config_value *)avl_insert_lock(&((co)->values_index), (avl *)(cv)) -#define config_value_index_del(co, cv) (struct config_value *)avl_remove_lock(&((co)->values_index), (avl *)(cv)) +#define appconfig_option_index_add(co, cv) (struct config_option *)avl_insert_lock(&((co)->values_index), (avl *)(cv)) +#define appconfig_option_index_del(co, cv) (struct config_option *)avl_remove_lock(&((co)->values_index), (avl *)(cv)) -static struct config_value *config_value_index_find(struct config *co, const char *name, uint32_t hash) { - struct config_value tmp; +static struct config_option *appconfig_option_index_find(struct section *co, const char *name, uint32_t hash) { + struct config_option tmp; tmp.hash = (hash)?hash:simple_hash(name); tmp.name = (char *)name; - return (struct config_value *)avl_search_lock(&(co->values_index), (avl *) &tmp); + return (struct config_option *)avl_search_lock(&(co->values_index), (avl *) &tmp); } // ---------------------------------------------------------------------------- // config sections index -static int config_compare(void* a, void* b) { - if(((struct config *)a)->hash < ((struct config *)b)->hash) return -1; - else if(((struct config *)a)->hash > ((struct config *)b)->hash) return 1; - else return strcmp(((struct config *)a)->name, ((struct config *)b)->name); +static int appconfig_section_compare(void *a, void *b) { + if(((struct section *)a)->hash < ((struct section *)b)->hash) return -1; + else if(((struct section *)a)->hash > ((struct section *)b)->hash) return 1; + else return strcmp(((struct section *)a)->name, ((struct section *)b)->name); } -avl_tree_lock config_root_index = { - { NULL, config_compare }, - AVL_LOCK_INITIALIZER -}; - -#define config_index_add(cfg) (struct config *)avl_insert_lock(&config_root_index, (avl *)(cfg)) -#define config_index_del(cfg) (struct config *)avl_remove_lock(&config_root_index, (avl *)(cfg)) +#define appconfig_index_add(root, cfg) (struct section *)avl_insert_lock(&root->index, (avl *)(cfg)) +#define appconfig_index_del(root, cfg) (struct section *)avl_remove_lock(&root->index, (avl *)(cfg)) -static struct config *config_index_find(const char *name, uint32_t hash) { - struct config tmp; +static struct section *appconfig_index_find(struct config *root, const char *name, uint32_t hash) { + struct section tmp; tmp.hash = (hash)?hash:simple_hash(name); tmp.name = (char *)name; - return (struct config *)avl_search_lock(&config_root_index, (avl *) &tmp); + return (struct section *)avl_search_lock(&root->index, (avl *) &tmp); } // ---------------------------------------------------------------------------- // config section methods -static inline struct config *config_section_find(const char *section) { - return config_index_find(section, 0); +static inline struct section *appconfig_section_find(struct config *root, const char *section) { + return appconfig_index_find(root, section, 0); } -static inline struct config *config_section_create(const char *section) -{ +static inline struct section *appconfig_section_create(struct config *root, const char *section) { debug(D_CONFIG, "Creating section '%s'.", section); - struct config *co = callocz(1, sizeof(struct config)); + struct section *co = callocz(1, sizeof(struct section)); co->name = strdupz(section); co->hash = simple_hash(co->name); - avl_init_lock(&co->values_index, config_value_compare); + avl_init_lock(&co->values_index, appconfig_option_compare); - if(unlikely(config_index_add(co) != co)) + if(unlikely(appconfig_index_add(root, co) != co)) error("INTERNAL ERROR: indexing of section '%s', already exists.", co->name); - config_global_write_lock(); - struct config *co2 = config_root; + appconfig_wrlock(root); + struct section *co2 = root->sections; if(co2) { while (co2->next) co2 = co2->next; co2->next = co; } - else config_root = co; - config_global_unlock(); + else root->sections = co; + appconfig_unlock(root); return co; } @@ -146,20 +157,25 @@ static inline struct config *config_section_create(const char *section) // ---------------------------------------------------------------------------- // config name-value methods -static inline struct config_value *config_value_create(struct config *co, const char *name, const char *value) -{ +static inline struct config_option *appconfig_value_create(struct section *co, const char *name, const char *value) { debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name); - struct config_value *cv = callocz(1, sizeof(struct config_value)); + struct config_option *cv = callocz(1, sizeof(struct config_option)); cv->name = strdupz(name); cv->hash = simple_hash(cv->name); cv->value = strdupz(value); - if(unlikely(config_value_index_add(co, cv) != cv)) - error("INTERNAL ERROR: indexing of config '%s' in section '%s': already exists.", cv->name, co->name); + struct config_option *found = appconfig_option_index_add(co, cv); + if(found != cv) { + error("indexing of config '%s' in section '%s': already exists - using the existing one.", cv->name, co->name); + freez(cv->value); + freez(cv->name); + freez(cv); + return found; + } - config_section_write_lock(co); - struct config_value *cv2 = co->values; + config_section_wrlock(co); + struct config_option *cv2 = co->values; if(cv2) { while (cv2->next) cv2 = cv2->next; cv2->next = cv; @@ -170,66 +186,87 @@ static inline struct config_value *config_value_create(struct config *co, const return cv; } -int config_exists(const char *section, const char *name) { - struct config_value *cv; +int appconfig_exists(struct config *root, const char *section, const char *name) { + struct config_option *cv; debug(D_CONFIG, "request to get config in section '%s', name '%s'", section, name); - struct config *co = config_section_find(section); + struct section *co = appconfig_section_find(root, section); if(!co) return 0; - cv = config_value_index_find(co, name, 0); + cv = appconfig_option_index_find(co, name, 0); if(!cv) return 0; return 1; } -int config_rename(const char *section, const char *old, const char *new) { - struct config_value *cv, *cv2; +int appconfig_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new) { + struct config_option *cv_old, *cv_new; + int ret = -1; - debug(D_CONFIG, "request to rename config in section '%s', old name '%s', new name '%s'", section, old, new); + debug(D_CONFIG, "request to rename config in section '%s', old name '%s', to section '%s', new name '%s'", section_old, name_old, section_new, name_new); - struct config *co = config_section_find(section); - if(!co) return -1; + struct section *co_old = appconfig_section_find(root, section_old); + if(!co_old) return ret; - config_section_write_lock(co); + struct section *co_new = appconfig_section_find(root, section_new); + if(!co_new) co_new = appconfig_section_create(root, section_new); - cv = config_value_index_find(co, old, 0); - if(!cv) goto cleanup; + config_section_wrlock(co_old); + config_section_wrlock(co_new); - cv2 = config_value_index_find(co, new, 0); - if(cv2) goto cleanup; + cv_old = appconfig_option_index_find(co_old, name_old, 0); + if(!cv_old) goto cleanup; - if(unlikely(config_value_index_del(co, cv) != cv)) - error("INTERNAL ERROR: deletion of config '%s' from section '%s', deleted tge wrong config entry.", cv->name, co->name); + cv_new = appconfig_option_index_find(co_new, name_new, 0); + if(cv_new) goto cleanup; - freez(cv->name); - cv->name = strdupz(new); - cv->hash = simple_hash(cv->name); - if(unlikely(config_value_index_add(co, cv) != cv)) - error("INTERNAL ERROR: indexing of config '%s' in section '%s', already exists.", cv->name, co->name); + if(unlikely(appconfig_option_index_del(co_old, cv_old) != cv_old)) + error("INTERNAL ERROR: deletion of config '%s' from section '%s', deleted tge wrong config entry.", cv_old->name, co_old->name); - config_section_unlock(co); + if(co_old->values == cv_old) { + co_old->values = cv_old->next; + } + else { + struct config_option *t; + for(t = co_old->values; t && t->next != cv_old ;t = t->next) ; + if(!t || t->next != cv_old) + error("INTERNAL ERROR: cannot find variable '%s' in section '%s' of the config - but it should be there.", cv_old->name, co_old->name); + else + t->next = cv_old->next; + } - return 0; + freez(cv_old->name); + cv_old->name = strdupz(name_new); + cv_old->hash = simple_hash(cv_old->name); + + cv_new = cv_old; + cv_new->next = co_new->values; + co_new->values = cv_new; + + if(unlikely(appconfig_option_index_add(co_new, cv_old) != cv_old)) + error("INTERNAL ERROR: re-indexing of config '%s' in section '%s', already exists.", cv_old->name, co_new->name); + + ret = 0; cleanup: - config_section_unlock(co); - return -1; + config_section_unlock(co_new); + config_section_unlock(co_old); + return ret; } -char *config_get(const char *section, const char *name, const char *default_value) +char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value) { - struct config_value *cv; + struct config_option *cv; debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value); - struct config *co = config_section_find(section); - if(!co) co = config_section_create(section); + struct section *co = appconfig_section_find(root, section); + if(!co) co = appconfig_section_create(root, section); - cv = config_value_index_find(co, name, 0); + cv = appconfig_option_index_find(co, name, 0); if(!cv) { - cv = config_value_create(co, name, default_value); + cv = appconfig_value_create(co, name, default_value); if(!cv) return NULL; } cv->flags |= CONFIG_VALUE_USED; @@ -246,67 +283,67 @@ char *config_get(const char *section, const char *name, const char *default_valu return(cv->value); } -long long config_get_number(const char *section, const char *name, long long value) +long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value) { char buffer[100], *s; sprintf(buffer, "%lld", value); - s = config_get(section, name, buffer); + s = appconfig_get(root, section, name, buffer); if(!s) return value; return strtoll(s, NULL, 0); } -int config_get_boolean(const char *section, const char *name, int value) +int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value) { char *s; if(value) s = "yes"; else s = "no"; - s = config_get(section, name, s); + s = appconfig_get(root, section, name, s); if(!s) return value; if(!strcmp(s, "yes") || !strcmp(s, "auto") || !strcmp(s, "on demand")) return 1; return 0; } -int config_get_boolean_ondemand(const char *section, const char *name, int value) +int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value) { char *s; - if(value == CONFIG_ONDEMAND_ONDEMAND) + if(value == CONFIG_BOOLEAN_AUTO) s = "auto"; - else if(value == CONFIG_ONDEMAND_NO) + else if(value == CONFIG_BOOLEAN_NO) s = "no"; else s = "yes"; - s = config_get(section, name, s); + s = appconfig_get(root, section, name, s); if(!s) return value; if(!strcmp(s, "yes")) - return CONFIG_ONDEMAND_YES; + return CONFIG_BOOLEAN_YES; else if(!strcmp(s, "no")) - return CONFIG_ONDEMAND_NO; + return CONFIG_BOOLEAN_NO; else if(!strcmp(s, "auto") || !strcmp(s, "on demand")) - return CONFIG_ONDEMAND_ONDEMAND; + return CONFIG_BOOLEAN_AUTO; return value; } -const char *config_set_default(const char *section, const char *name, const char *value) +const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value) { - struct config_value *cv; + struct config_option *cv; debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value); - struct config *co = config_section_find(section); - if(!co) return config_set(section, name, value); + struct section *co = appconfig_section_find(root, section); + if(!co) return appconfig_set(root, section, name, value); - cv = config_value_index_find(co, name, 0); - if(!cv) return config_set(section, name, value); + cv = appconfig_option_index_find(co, name, 0); + if(!cv) return appconfig_set(root, section, name, value); cv->flags |= CONFIG_VALUE_USED; @@ -323,17 +360,17 @@ const char *config_set_default(const char *section, const char *name, const char return cv->value; } -const char *config_set(const char *section, const char *name, const char *value) +const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value) { - struct config_value *cv; + struct config_option *cv; debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value); - struct config *co = config_section_find(section); - if(!co) co = config_section_create(section); + struct section *co = appconfig_section_find(root, section); + if(!co) co = appconfig_section_create(root, section); - cv = config_value_index_find(co, name, 0); - if(!cv) cv = config_value_create(co, name, value); + cv = appconfig_option_index_find(co, name, 0); + if(!cv) cv = appconfig_value_create(co, name, value); cv->flags |= CONFIG_VALUE_USED; if(strcmp(cv->value, value) != 0) { @@ -346,23 +383,23 @@ const char *config_set(const char *section, const char *name, const char *value) return value; } -long long config_set_number(const char *section, const char *name, long long value) +long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value) { char buffer[100]; sprintf(buffer, "%lld", value); - config_set(section, name, buffer); + appconfig_set(root, section, name, buffer); return value; } -int config_set_boolean(const char *section, const char *name, int value) +int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value) { char *s; if(value) s = "yes"; else s = "no"; - config_set(section, name, s); + appconfig_set(root, section, name, s); return value; } @@ -371,10 +408,10 @@ int config_set_boolean(const char *section, const char *name, int value) // ---------------------------------------------------------------------------- // config load/save -int load_config(char *filename, int overwrite_used) +int appconfig_load(struct config *root, char *filename, int overwrite_used) { int line = 0; - struct config *co = NULL; + struct section *co = NULL; char buffer[CONFIG_FILE_LINE_MAX + 1], *s; @@ -404,8 +441,8 @@ int load_config(char *filename, int overwrite_used) s[len - 1] = '\0'; s++; - co = config_section_find(s); - if(!co) co = config_section_create(s); + co = appconfig_section_find(root, s); + if(!co) co = appconfig_section_create(root, s); continue; } @@ -437,9 +474,9 @@ int load_config(char *filename, int overwrite_used) continue; } - struct config_value *cv = config_value_index_find(co, name, 0); + struct config_option *cv = appconfig_option_index_find(co, name, 0); - if(!cv) cv = config_value_create(co, name, value); + if(!cv) cv = appconfig_value_create(co, name, value); else { if(((cv->flags & CONFIG_VALUE_USED) && overwrite_used) || !(cv->flags & CONFIG_VALUE_USED)) { debug(D_CONFIG, "Line %d, overwriting '%s/%s'.", line, co->name, cv->name); @@ -457,11 +494,11 @@ int load_config(char *filename, int overwrite_used) return 1; } -void generate_config(BUFFER *wb, int only_changed) +void appconfig_generate(struct config *root, BUFFER *wb, int only_changed) { int i, pri; - struct config *co; - struct config_value *cv; + struct section *co; + struct config_option *cv; for(i = 0; i < 3 ;i++) { switch(i) { @@ -490,13 +527,16 @@ void generate_config(BUFFER *wb, int only_changed) break; } - config_global_write_lock(); - for(co = config_root; co ; co = co->next) { - if(!strcmp(co->name, "global") || - !strcmp(co->name, "plugins") || - !strcmp(co->name, "registry") || - !strcmp(co->name, "health") || - !strcmp(co->name, "backend")) + appconfig_wrlock(root); + for(co = root->sections; co ; co = co->next) { + if(!strcmp(co->name, CONFIG_SECTION_GLOBAL) + || !strcmp(co->name, CONFIG_SECTION_WEB) + || !strcmp(co->name, CONFIG_SECTION_PLUGINS) + || !strcmp(co->name, CONFIG_SECTION_REGISTRY) + || !strcmp(co->name, CONFIG_SECTION_HEALTH) + || !strcmp(co->name, CONFIG_SECTION_BACKEND) + || !strcmp(co->name, CONFIG_SECTION_STREAM) + ) pri = 0; else if(!strncmp(co->name, "plugin:", 7)) pri = 1; else pri = 2; @@ -506,7 +546,7 @@ void generate_config(BUFFER *wb, int only_changed) int changed = 0; int count = 0; - config_section_write_lock(co); + config_section_wrlock(co); for(cv = co->values; cv ; cv = cv->next) { used += (cv->flags & CONFIG_VALUE_USED)?1:0; changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0; @@ -523,7 +563,7 @@ void generate_config(BUFFER *wb, int only_changed) buffer_sprintf(wb, "\n[%s]\n", co->name); - config_section_write_lock(co); + config_section_wrlock(co); for(cv = co->values; cv ; cv = cv->next) { if(used && !(cv->flags & CONFIG_VALUE_USED)) { @@ -534,6 +574,6 @@ void generate_config(BUFFER *wb, int only_changed) config_section_unlock(co); } } - config_global_unlock(); + appconfig_unlock(root); } } diff --git a/src/appconfig.h b/src/appconfig.h index 08aae834..15bba807 100644 --- a/src/appconfig.h +++ b/src/appconfig.h @@ -3,30 +3,67 @@ #define CONFIG_FILENAME "netdata.conf" +#define CONFIG_SECTION_GLOBAL "global" +#define CONFIG_SECTION_WEB "web" +#define CONFIG_SECTION_PLUGINS "plugins" +#define CONFIG_SECTION_REGISTRY "registry" +#define CONFIG_SECTION_HEALTH "health" +#define CONFIG_SECTION_BACKEND "backend" +#define CONFIG_SECTION_STREAM "stream" + // these are used to limit the configuration names and values lengths // they are not enforced by config.c functions (they will strdup() all strings, no matter of their length) #define CONFIG_MAX_NAME 1024 #define CONFIG_MAX_VALUE 2048 -extern int load_config(char *filename, int overwrite_used); +struct config { + struct section *sections; + pthread_mutex_t mutex; + avl_tree_lock index; +}; + +extern struct config + netdata_config, + stream_config; + +#define CONFIG_BOOLEAN_NO 0 +#define CONFIG_BOOLEAN_YES 1 +#define CONFIG_BOOLEAN_AUTO 2 + +extern int appconfig_load(struct config *root, char *filename, int overwrite_used); + +extern char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value); +extern long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value); +extern int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value); +extern int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value); + +extern const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value); +extern const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value); +extern long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value); +extern int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value); + +extern int appconfig_exists(struct config *root, const char *section, const char *name); +extern int appconfig_move(struct config *root, const char *section_old, const char *name_old, const char *section_new, const char *name_new); + +extern void appconfig_generate(struct config *root, BUFFER *wb, int only_changed); -extern char *config_get(const char *section, const char *name, const char *default_value); -extern long long config_get_number(const char *section, const char *name, long long value); -extern int config_get_boolean(const char *section, const char *name, int value); +// ---------------------------------------------------------------------------- +// shortcuts for the default netdata configuration -#define CONFIG_ONDEMAND_NO 0 -#define CONFIG_ONDEMAND_YES 1 -#define CONFIG_ONDEMAND_ONDEMAND 2 -extern int config_get_boolean_ondemand(const char *section, const char *name, int value); +#define config_load(filename, overwrite_used) appconfig_load(&netdata_config, filename, overwrite_used) +#define config_get(section, name, default_value) appconfig_get(&netdata_config, section, name, default_value) +#define config_get_number(section, name, value) appconfig_get_number(&netdata_config, section, name, value) +#define config_get_boolean(section, name, value) appconfig_get_boolean(&netdata_config, section, name, value) +#define config_get_boolean_ondemand(section, name, value) appconfig_get_boolean_ondemand(&netdata_config, section, name, value) -extern const char *config_set(const char *section, const char *name, const char *value); -extern const char *config_set_default(const char *section, const char *name, const char *value); -extern long long config_set_number(const char *section, const char *name, long long value); -extern int config_set_boolean(const char *section, const char *name, int value); +#define config_set(section, name, default_value) appconfig_get(&netdata_config, section, name, default_value) +#define config_set_default(section, name, value) appconfig_set_default(&netdata_config, section, name, value) +#define config_set_number(section, name, value) appconfig_set_number(&netdata_config, section, name, value) +#define config_set_boolean(section, name, value) appconfig_set_boolean(&netdata_config, section, name, value) -extern int config_exists(const char *section, const char *name); -extern int config_rename(const char *section, const char *old, const char *new); +#define config_exists(section, name) appconfig_exists(&netdata_config, section, name) +#define config_move(section_old, name_old, section_new, name_new) appconfig_move(&netdata_config, section_old, name_old, section_new, name_new) -extern void generate_config(BUFFER *wb, int only_changed); +#define config_generate(buffer, only_changed) appconfig_generate(&netdata_config, buffer, only_changed) #endif /* NETDATA_CONFIG_H */ diff --git a/src/apps_plugin.c b/src/apps_plugin.c index 103bc143..f5c25c73 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -64,6 +64,7 @@ static int static size_t global_iterations_counter = 1, + calls_counter = 0, file_counter = 0; @@ -831,7 +832,7 @@ static inline int read_proc_pid_stat(struct pid_stat *p) { p->last_stat_collected_usec = p->stat_collected_usec; p->stat_collected_usec = now_monotonic_usec(); - file_counter++; + calls_counter++; // p->pid = str2pid_t(procfile_lineword(ff, 0, 0)); char *comm = procfile_lineword(ff, 0, 1); @@ -983,7 +984,7 @@ static inline int read_proc_pid_statm(struct pid_stat *p) { ff = procfile_readall(ff); if(unlikely(!ff)) goto cleanup; - file_counter++; + calls_counter++; p->statm_size = str2kernel_uint_t(procfile_lineword(ff, 0, 0)); p->statm_resident = str2kernel_uint_t(procfile_lineword(ff, 0, 1)); @@ -1022,7 +1023,7 @@ static inline int read_proc_pid_io(struct pid_stat *p) { ff = procfile_readall(ff); if(unlikely(!ff)) goto cleanup; - file_counter++; + calls_counter++; p->last_io_collected_usec = p->io_collected_usec; p->io_collected_usec = now_monotonic_usec(); @@ -1098,7 +1099,7 @@ static inline int read_proc_stat() { last_collected_usec = collected_usec; collected_usec = now_monotonic_usec(); - file_counter++; + calls_counter++; kernel_uint_t last; @@ -1387,8 +1388,9 @@ static inline void make_all_pid_fds_negative(struct pid_stat *p) { } static inline void cleanup_negative_pid_fds(struct pid_stat *p) { - int *fd = p->fds, *end = &p->fds[p->fds_size]; - while(fd < end) { + int *fd = p->fds, *fdend = &p->fds[p->fds_size]; + + while(fd < fdend) { if(unlikely(*fd < 0)) { file_descriptor_not_used(-(*fd)); *fd++ = 0; @@ -1429,7 +1431,7 @@ static inline int read_pid_file_descriptors(struct pid_stat *p) { continue; // get its number - int fdid = (int)str2l(de->d_name); + int fdid = (int) str2l(de->d_name); if(unlikely(fdid < 0)) continue; // check if the fds array is small @@ -1437,7 +1439,12 @@ static inline int read_pid_file_descriptors(struct pid_stat *p) { // it is small, extend it if(unlikely(debug)) - fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS); + fprintf(stderr + , "apps.plugin: extending fd memory slots for %s from %d to %d\n" + , p->comm + , p->fds_size + , fdid + MAX_SPARE_FDS + ); p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int)); @@ -1468,9 +1475,10 @@ static inline int read_pid_file_descriptors(struct pid_stat *p) { p->fds[fdid] = file_descriptor_find_or_add(linkname); } - // else make it positive again, we need it - // of course, the actual file may have changed, but we don't care so much - // FIXME: we could compare the inode as returned by readdir dirent structure + // else make it positive again, we need it + // of course, the actual file may have changed, but we don't care so much + // FIXME: we could compare the inode as returned by readdir dirent structure + // UPDATE: no we cannot use inodes - under /proc inodes don't change when the link is changed else p->fds[fdid] = -p->fds[fdid]; @@ -1952,10 +1960,11 @@ static void cleanup_exited_pids(void) { if(unlikely(debug && (p->keep || p->keeploops))) fprintf(stderr, " > CLEANUP cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm); - for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] > 0) { - file_descriptor_not_used(p->fds[c]); - p->fds[c] = 0; - } + for(c = 0; c < p->fds_size; c++) + if(p->fds[c] > 0) { + file_descriptor_not_used(p->fds[c]); + p->fds[c] = 0; + } pid_t r = p->pid; p = p->next; @@ -2398,6 +2407,7 @@ static usec_t send_resource_usage_to_netdata() { "DIMENSION user '' incremental 1 1000\n" "DIMENSION system '' incremental 1 1000\n" "CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_files line 140001 %1$d\n" + "DIMENSION calls '' incremental 1 1\n" "DIMENSION files '' incremental 1 1\n" "DIMENSION pids '' absolute 1 1\n" "DIMENSION fds '' absolute 1 1\n" @@ -2431,6 +2441,7 @@ static usec_t send_resource_usage_to_netdata() { "SET system = %llu\n" "END\n" "BEGIN netdata.apps_files %llu\n" + "SET calls = %zu\n" "SET files = %zu\n" "SET pids = %zu\n" "SET fds = %d\n" @@ -2447,6 +2458,7 @@ static usec_t send_resource_usage_to_netdata() { , cpuuser , cpusyst , usec + , calls_counter , file_counter , all_pids_count , all_files_len @@ -2890,6 +2902,22 @@ static void send_charts_updates_to_netdata(struct target *root, const char *type // ---------------------------------------------------------------------------- // parse command line arguments +int check_proc_1_io() { + int ret = 0; + + procfile *ff = procfile_open("/proc/1/io", NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO); + if(!ff) goto cleanup; + + ff = procfile_readall(ff); + if(!ff) goto cleanup; + + ret = 1; + +cleanup: + procfile_close(ff); + return ret; +} + static void parse_args(int argc, char **argv) { int i, freq = 0; @@ -2909,6 +2937,15 @@ static void parse_args(int argc, char **argv) exit(0); } + if(strcmp("test-permissions", argv[i]) == 0 || strcmp("-t", argv[i]) == 0) { + if(!check_proc_1_io()) { + perror("Tried to read /proc/1/io and it failed"); + exit(1); + } + printf("OK\n"); + exit(0); + } + if(strcmp("debug", argv[i]) == 0) { debug = 1; // debug_flags = 0xffffffff; @@ -3081,8 +3118,6 @@ int main(int argc, char **argv) { // set the name for logging program_name = "apps.plugin"; - info("started on pid %d", getpid()); - // disable syslog for apps.plugin error_log_syslog = 0; @@ -3124,27 +3159,27 @@ int main(int argc, char **argv) { parse_args(argc, argv); - if(!check_capabilities()) { - if(!am_i_running_as_root()) { - uid_t uid = getuid(), euid = geteuid(); + if(!check_capabilities() && !am_i_running_as_root() && !check_proc_1_io()) { + uid_t uid = getuid(), euid = geteuid(); #ifdef HAVE_CAPABILITY - error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. " - "Without these, apps.plugin cannot report disk I/O utilization of other processes. " - "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; " - "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; " - , uid, euid, argv[0], argv[0], argv[0] - ); + error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. " + "Without these, apps.plugin cannot report disk I/O utilization of other processes. " + "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; " + "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; " + , uid, euid, argv[0], argv[0], argv[0] + ); #else - error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. " - "Without these, apps.plugin cannot report disk I/O utilization of other processes. " - "Your system does not support capabilities. " - "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; " - , uid, euid, argv[0], argv[0] - ); + error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. " + "Without these, apps.plugin cannot report disk I/O utilization of other processes. " + "Your system does not support capabilities. " + "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; " + , uid, euid, argv[0], argv[0] + ); #endif - } } + info("started on pid %d", getpid()); + all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max); all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max); diff --git a/src/backends.c b/src/backends.c index de267de5..c7b08645 100644 --- a/src/backends.c +++ b/src/backends.c @@ -228,11 +228,13 @@ static inline int process_opentsdb_response(BUFFER *b) { } void *backends_main(void *ptr) { + int default_port = 0; + int sock = -1; struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; BUFFER *b = buffer_create(1), *response = buffer_create(1); - int (*backend_request_formatter)(BUFFER *b, const char *prefix, RRDHOST *host, const char *hostname, RRDSET *st, RRDDIM *rd, time_t after, time_t before, uint32_t options) = NULL; - int (*backend_response_checker)(BUFFER *b) = NULL; + int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL; + int (*backend_response_checker)(BUFFER *) = NULL; info("BACKEND thread created with task id %d", gettid()); @@ -249,22 +251,21 @@ void *backends_main(void *ptr) { .tv_sec = 0, .tv_usec = 0 }; - int default_port = 0; - int sock = -1; uint32_t options; - int enabled = config_get_boolean("backend", "enabled", 0); - const char *source = config_get("backend", "data source", "average"); - const char *type = config_get("backend", "type", "graphite"); - const char *destination = config_get("backend", "destination", "localhost"); - const char *prefix = config_get("backend", "prefix", "netdata"); - const char *hostname = config_get("backend", "hostname", localhost.hostname); - int frequency = (int)config_get_number("backend", "update every", 10); - int buffer_on_failures = (int)config_get_number("backend", "buffer on failures", 10); - long timeoutms = config_get_number("backend", "timeout ms", frequency * 2 * 1000); + int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0); + const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average"); + const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite"); + const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost"); + const char *prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata"); + const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname); + int frequency = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", 10); + int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10); + long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", frequency * 2 * 1000); // ------------------------------------------------------------------------ // validate configuration options // and prepare for sending data to our backend + if(!enabled || frequency < 1) goto cleanup; @@ -282,6 +283,17 @@ void *backends_main(void *ptr) { goto cleanup; } + if(timeoutms < 1) { + error("BACKED invalid timeout %ld ms given. Assuming %d ms.", timeoutms, frequency * 2 * 1000); + timeoutms = frequency * 2 * 1000; + } + timeout.tv_sec = (timeoutms * 1000) / 1000000; + timeout.tv_usec = (timeoutms * 1000) % 1000000; + + + // ------------------------------------------------------------------------ + // select the backend type + if(!strcmp(type, "graphite") || !strcmp(type, "graphite:plaintext")) { default_port = 2003; if(options == BACKEND_SOURCE_DATA_AS_COLLECTED) @@ -325,15 +337,9 @@ void *backends_main(void *ptr) { goto cleanup; } - if(timeoutms < 1) { - error("BACKED invalid timeout %ld ms given. Assuming %d ms.", timeoutms, frequency * 2 * 1000); - timeoutms = frequency * 2 * 1000; - } - timeout.tv_sec = (timeoutms * 1000) / 1000000; - timeout.tv_usec = (timeoutms * 1000) % 1000000; // ------------------------------------------------------------------------ - // prepare the charts for monitoring the backend + // prepare the charts for monitoring the backend operation struct rusage thread; @@ -352,32 +358,23 @@ void *backends_main(void *ptr) { chart_backend_reconnects = 0, chart_backend_latency = 0; - RRDSET *chart_metrics = rrdset_find("netdata.backend_metrics"); - if(!chart_metrics) { - chart_metrics = rrdset_create("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", 130600, frequency, RRDSET_TYPE_LINE); - rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRDDIM_ABSOLUTE); - } + RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", 130600, frequency, RRDSET_TYPE_LINE); + rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - RRDSET *chart_bytes = rrdset_find("netdata.backend_bytes"); - if(!chart_bytes) { - chart_bytes = rrdset_create("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", 130610, frequency, RRDSET_TYPE_AREA); - rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRDDIM_ABSOLUTE); - } + RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", 130610, frequency, RRDSET_TYPE_AREA); + rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); - RRDSET *chart_ops = rrdset_find("netdata.backend_ops"); - if(!chart_ops) { - chart_ops = rrdset_create("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", 130630, frequency, RRDSET_TYPE_LINE); - rrddim_add(chart_ops, "write", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(chart_ops, "discard", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(chart_ops, "failure", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(chart_ops, "read", NULL, 1, 1, RRDDIM_ABSOLUTE); - } + RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", 130630, frequency, RRDSET_TYPE_LINE); + rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_ops, "failure", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(chart_ops, "read", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); /* * this is misleading - we can only measure the time we need to send data @@ -386,19 +383,14 @@ void *backends_main(void *ptr) { * * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html * - RRDSET *chart_latency = rrdset_find("netdata.backend_latency"); - if(!chart_latency) { - chart_latency = rrdset_create("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", 130620, frequency, RRDSET_TYPE_AREA); - rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRDDIM_ABSOLUTE); - } + RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", 130620, frequency, RRDSET_TYPE_AREA); + rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); */ - RRDSET *chart_rusage = rrdset_find("netdata.backend_thread_cpu"); - if(!chart_rusage) { - chart_rusage = rrdset_create("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", 130630, frequency, RRDSET_TYPE_STACKED); - rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); - } + RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", 130630, frequency, RRDSET_TYPE_STACKED); + rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + // ------------------------------------------------------------------------ // prepare the backend main loop @@ -412,32 +404,43 @@ void *backends_main(void *ptr) { heartbeat_init(&hb); for(;;) { + // ------------------------------------------------------------------------ // Wait for the next iteration point. heartbeat_next(&hb, step_ut); time_t before = now_realtime_sec(); + // ------------------------------------------------------------------------ // add to the buffer the data we need to send to the backend - RRDSET *st; + int pthreadoldcancelstate; if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); - rrdhost_rdlock(&localhost); - for(st = localhost.rrdset_root; st ;st = st->next) { - pthread_rwlock_rdlock(&st->rwlock); + rrd_rdlock(); + RRDHOST *host; + rrdhost_foreach_read(host) { + if(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE) + continue; - RRDDIM *rd; - for(rd = st->dimensions; rd ;rd = rd->next) { - if(rd->last_collected_time.tv_sec >= after) - chart_buffered_metrics += backend_request_formatter(b, prefix, &localhost, hostname, st, rd, after, before, options); - } + rrdhost_rdlock(host); - pthread_rwlock_unlock(&st->rwlock); + RRDSET *st; + rrdset_foreach_read(st, host) { + rrdset_rdlock(st); + + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + if(rd->last_collected_time.tv_sec >= after) + chart_buffered_metrics += backend_request_formatter(b, prefix, host, (host == localhost)?hostname:host->hostname, st, rd, after, before, options); + } + rrdset_unlock(st); + } + rrdhost_unlock(host); } - rrdhost_unlock(&localhost); + rrd_unlock(); if(unlikely(pthread_setcancelstate(pthreadoldcancelstate, NULL) != 0)) error("Cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate); @@ -507,26 +510,11 @@ void *backends_main(void *ptr) { if(unlikely(sock == -1)) { usec_t start_ut = now_monotonic_usec(); - const char *s = destination; - while(*s) { - const char *e = s; - - // skip separators, moving both s(tart) and e(nd) - while(isspace(*e) || *e == ',') s = ++e; + size_t reconnects = 0; - // move e(nd) to the first separator - while(*e && !isspace(*e) && *e != ',') e++; + sock = connect_to_one_of(destination, default_port, &timeout, &reconnects, NULL, 0); - // is there anything? - if(!*s || s == e) break; - - char buf[e - s + 1]; - strncpyz(buf, s, e - s); - chart_backend_reconnects++; - sock = connect_to(buf, default_port, &timeout); - if(sock != -1) break; - s = e; - } + chart_backend_reconnects += reconnects; chart_backend_latency += now_monotonic_usec() - start_ut; } @@ -596,7 +584,7 @@ void *backends_main(void *ptr) { // ------------------------------------------------------------------------ // update the monitoring charts - if(chart_ops->counter_done) rrdset_next(chart_ops); + if(likely(chart_ops->counter_done)) rrdset_next(chart_ops); rrddim_set(chart_ops, "read", chart_receptions); rrddim_set(chart_ops, "write", chart_transmission_successes); rrddim_set(chart_ops, "discard", chart_data_lost_events); @@ -604,13 +592,13 @@ void *backends_main(void *ptr) { rrddim_set(chart_ops, "reconnect", chart_backend_reconnects); rrdset_done(chart_ops); - if(chart_metrics->counter_done) rrdset_next(chart_metrics); + if(likely(chart_metrics->counter_done)) rrdset_next(chart_metrics); rrddim_set(chart_metrics, "buffered", chart_buffered_metrics); rrddim_set(chart_metrics, "lost", chart_lost_metrics); rrddim_set(chart_metrics, "sent", chart_sent_metrics); rrdset_done(chart_metrics); - if(chart_bytes->counter_done) rrdset_next(chart_bytes); + if(likely(chart_bytes->counter_done)) rrdset_next(chart_bytes); rrddim_set(chart_bytes, "buffered", chart_buffered_bytes); rrddim_set(chart_bytes, "lost", chart_lost_bytes); rrddim_set(chart_bytes, "sent", chart_sent_bytes); @@ -618,13 +606,13 @@ void *backends_main(void *ptr) { rrdset_done(chart_bytes); /* - if(chart_latency->counter_done) rrdset_next(chart_latency); + if(likely(chart_latency->counter_done)) rrdset_next(chart_latency); rrddim_set(chart_latency, "latency", chart_backend_latency); rrdset_done(chart_latency); */ getrusage(RUSAGE_THREAD, &thread); - if(chart_rusage->counter_done) rrdset_next(chart_rusage); + if(likely(chart_rusage->counter_done)) rrdset_next(chart_rusage); rrddim_set(chart_rusage, "user", thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); rrddim_set(chart_rusage, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(chart_rusage); diff --git a/src/clocks.c b/src/clocks.c index 88d3783e..239b36e5 100644 --- a/src/clocks.c +++ b/src/clocks.c @@ -74,6 +74,14 @@ inline usec_t timeval_usec(struct timeval *tv) { return (usec_t)tv->tv_sec * USEC_PER_SEC + tv->tv_usec; } +inline susec_t dt_usec_signed(struct timeval *now, struct timeval *old) { + usec_t ts1 = timeval_usec(now); + usec_t ts2 = timeval_usec(old); + + if(likely(ts1 >= ts2)) return (susec_t)(ts1 - ts2); + return -((susec_t)(ts2 - ts1)); +} + inline usec_t dt_usec(struct timeval *now, struct timeval *old) { usec_t ts1 = timeval_usec(now); usec_t ts2 = timeval_usec(old); diff --git a/src/clocks.h b/src/clocks.h index 895f09ab..c410a052 100644 --- a/src/clocks.h +++ b/src/clocks.h @@ -13,6 +13,7 @@ typedef int clockid_t; #endif typedef unsigned long long usec_t; +typedef long long susec_t; typedef usec_t heartbeat_t; @@ -94,6 +95,7 @@ extern usec_t now_boottime_usec(void); extern usec_t timeval_usec(struct timeval *ts); extern usec_t dt_usec(struct timeval *now, struct timeval *old); +extern susec_t dt_usec_signed(struct timeval *now, struct timeval *old); extern void heartbeat_init(heartbeat_t *hb); diff --git a/src/common.c b/src/common.c index 5243e407..e46397c6 100644 --- a/src/common.c +++ b/src/common.c @@ -8,6 +8,7 @@ # define MADV_DONTFORK INHERIT_NONE #endif /* __FreeBSD__ || __APPLE__*/ +char *netdata_configured_hostname = NULL; char *netdata_configured_config_dir = NULL; char *netdata_configured_log_dir = NULL; char *netdata_configured_plugins_dir = NULL; diff --git a/src/common.h b/src/common.h index 5b9b65b0..3d864f42 100644 --- a/src/common.h +++ b/src/common.h @@ -199,12 +199,12 @@ #define NETDATA_OS_TYPE "linux" #endif /* __FreeBSD__, __APPLE__*/ -#include "plugin_tc.h" -#include "plugins_d.h" #include "socket.h" #include "eval.h" #include "health.h" #include "rrd.h" +#include "plugin_tc.h" +#include "plugins_d.h" #include "rrd2json.h" #include "web_client.h" #include "web_server.h" @@ -216,7 +216,11 @@ #include "backends.h" #include "inlined.h" #include "adaptive_resortable_list.h" +#include "rrdpush.h" +#include "web_api_v1.h" +#include "web_api_old.h" +extern char *netdata_configured_hostname; extern char *netdata_configured_config_dir; extern char *netdata_configured_log_dir; extern char *netdata_configured_plugins_dir; diff --git a/src/daemon.c b/src/daemon.c index e7f3b037..42b04c40 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -27,7 +27,7 @@ void sig_handler_save(int signo) if(signo) { error_log_limit_unlimited(); info("Received signal %d to save the database...", signo); - rrdset_save_all(); + rrdhost_save_all(); error_log_limit_reset(); } } @@ -156,7 +156,7 @@ int become_user(const char *username, int pid_fd) } static void oom_score_adj(void) { - int score = (int)config_get_number("global", "OOM score", 1000); + int score = (int)config_get_number(CONFIG_SECTION_GLOBAL, "OOM score", 1000); int done = 0; int fd = open("/proc/self/oom_score_adj", O_WRONLY); @@ -175,7 +175,7 @@ static void oom_score_adj(void) { static void process_nice_level(void) { #ifdef HAVE_NICE - int nice_level = (int)config_get_number("global", "process nice level", 19); + int nice_level = (int)config_get_number(CONFIG_SECTION_GLOBAL, "process nice level", 19); if(nice(nice_level) == -1) error("Cannot set netdata CPU nice level to %d.", nice_level); else debug(D_SYSTEM, "Set netdata nice level to %d.", nice_level); #endif // HAVE_NICE @@ -239,7 +239,7 @@ static void sched_setscheduler_set(void) { int found = 0; // read the configuration - name = config_get("global", "process scheduling policy", name); + name = config_get(CONFIG_SECTION_GLOBAL, "process scheduling policy", name); int i; for(i = 0 ; scheduler_defaults[i].name ; i++) { if(!strcmp(name, scheduler_defaults[i].name)) { @@ -251,7 +251,7 @@ static void sched_setscheduler_set(void) { return; if(flags & SCHED_FLAG_PRIORITY_CONFIGURABLE) - priority = (int)config_get_number("global", "process scheduling priority", priority); + priority = (int)config_get_number(CONFIG_SECTION_GLOBAL, "process scheduling priority", priority); #ifdef HAVE_SCHED_GET_PRIORITY_MIN if(priority < sched_get_priority_min(policy)) { diff --git a/src/freebsd_sysctl.c b/src/freebsd_sysctl.c index 4ad0d5e1..3fed51bb 100644 --- a/src/freebsd_sysctl.c +++ b/src/freebsd_sysctl.c @@ -93,10 +93,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_tcp_packets = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP packets", 1); do_tcp_errors = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP errors", 1); do_tcp_handshake = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP handshake issues", 1); - do_ecn = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_syscookies = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_ofo = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_connaborts = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND); + do_ecn = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ECN packets", CONFIG_BOOLEAN_AUTO); + do_tcpext_syscookies = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO); + do_tcpext_ofo = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO); + do_tcpext_connaborts = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP connection aborts", CONFIG_BOOLEAN_AUTO); do_udp_packets = config_get_boolean("plugin:freebsd:sysctl", "ipv4 UDP packets", 1); do_udp_errors = config_get_boolean("plugin:freebsd:sysctl", "ipv4 UDP errors", 1); do_icmp_packets = config_get_boolean("plugin:freebsd:sysctl", "ipv4 ICMP packets", 1); @@ -105,17 +105,17 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_ip_fragsout = config_get_boolean("plugin:freebsd:sysctl", "ipv4 fragments sent", 1); do_ip_fragsin = config_get_boolean("plugin:freebsd:sysctl", "ipv4 fragments assembly", 1); do_ip_errors = config_get_boolean("plugin:freebsd:sysctl", "ipv4 errors", 1); - do_ip6_packets = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND); - do_ip6_fragsout = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND); - do_ip6_fragsin = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND); - do_ip6_errors = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6 = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_redir = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_errors = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp errors", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_echos = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp echos", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_router = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp router", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_neighbor = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_types = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp types", CONFIG_ONDEMAND_ONDEMAND); + do_ip6_packets = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 packets", CONFIG_BOOLEAN_AUTO); + do_ip6_fragsout = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO); + do_ip6_fragsin = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO); + do_ip6_errors = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 errors", CONFIG_BOOLEAN_AUTO); + do_icmp6 = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp", CONFIG_BOOLEAN_AUTO); + do_icmp6_redir = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp redirects", CONFIG_BOOLEAN_AUTO); + do_icmp6_errors = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp errors", CONFIG_BOOLEAN_AUTO); + do_icmp6_echos = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp echos", CONFIG_BOOLEAN_AUTO); + do_icmp6_router = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp router", CONFIG_BOOLEAN_AUTO); + do_icmp6_neighbor = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp neighbor", CONFIG_BOOLEAN_AUTO); + do_icmp6_types = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp types", CONFIG_BOOLEAN_AUTO); do_space = config_get_boolean("plugin:freebsd:sysctl", "space usage for all disks", 1); do_inodes = config_get_boolean("plugin:freebsd:sysctl", "inodes usage for all disks", 1); do_uptime = config_get_boolean("plugin:freebsd:sysctl", "system uptime", 1); @@ -285,12 +285,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.load"); } else { - st = rrdset_find_bytype("system", "load"); + st = rrdset_find_bytype_localhost("system", "load"); if (unlikely(!st)) { - st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -318,10 +318,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { } else { if (likely(do_all_processes)) { - st = rrdset_find_bytype("system", "active_processes"); + st = rrdset_find_bytype_localhost("system", "active_processes"); if (unlikely(!st)) { - st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -333,12 +333,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { if (likely(do_processes)) { - st = rrdset_find_bytype("system", "processes"); + st = rrdset_find_bytype_localhost("system", "processes"); if (unlikely(!st)) { - st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -350,12 +350,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_committed)) { - st = rrdset_find("mem.committed"); + st = rrdset_find_localhost("mem.committed"); if (unlikely(!st)) { - st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "Committed_AS", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "Committed_AS", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -378,22 +378,22 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.cpu"); } else { - st = rrdset_find_bytype("system", "cpu"); + st = rrdset_find_bytype_localhost("system", "cpu"); if (unlikely(!st)) { - st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "nice", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "system", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "interrupt", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "idle", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "system", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "interrupt", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } else rrdset_next(st); - rrddim_set(st, "user", cp_time[0]); rrddim_set(st, "nice", cp_time[1]); rrddim_set(st, "system", cp_time[2]); + rrddim_set(st, "user", cp_time[0]); rrddim_set(st, "interrupt", cp_time[3]); rrddim_set(st, "idle", cp_time[4]); rrdset_done(st); @@ -420,23 +420,23 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { } else { for (i = 0; i < ncpus; i++) { snprintfz(cpuid, MAX_INT_DIGITS, "cpu%d", i); - st = rrdset_find_bytype("cpu", cpuid); + st = rrdset_find_bytype_localhost("cpu", cpuid); if (unlikely(!st)) { - st = rrdset_create("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", + st = rrdset_create_localhost("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", "percentage", 1000, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "nice", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "system", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "interrupt", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "idle", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "system", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "interrupt", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } else rrdset_next(st); - rrddim_set(st, "user", pcpu_cp_time[i * 5 + 0]); rrddim_set(st, "nice", pcpu_cp_time[i * 5 + 1]); rrddim_set(st, "system", pcpu_cp_time[i * 5 + 2]); + rrddim_set(st, "user", pcpu_cp_time[i * 5 + 0]); rrddim_set(st, "interrupt", pcpu_cp_time[i * 5 + 3]); rrddim_set(st, "idle", pcpu_cp_time[i * 5 + 4]); rrdset_done(st); @@ -463,12 +463,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { for (i = 0; i < nintr; i++) totalintr += intrcnt[i]; - st = rrdset_find_bytype("system", "intr"); + st = rrdset_find_bytype_localhost("system", "intr"); if (unlikely(!st)) { - st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Total Hardware Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("system", "intr", NULL, "interrupts", NULL, "Total Hardware Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -483,9 +483,9 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_interrupts = 0; error("DISABLED: system.intr"); } else { - st = rrdset_find_bytype("system", "interrupts"); + st = rrdset_find_bytype_localhost("system", "interrupts"); if (unlikely(!st)) - st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", + st = rrdset_create_localhost("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED); else rrdset_next(st); @@ -495,7 +495,7 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { if (unlikely((intrcnt[i] != 0) && (*(char*)p != 0))) { rd = rrddim_find(st, p); if (unlikely(!rd)) - rd = rrddim_add(st, p, NULL, 1, 1, RRDDIM_INCREMENTAL); + rd = rrddim_add(st, p, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, rd, intrcnt[i]); } } @@ -513,11 +513,11 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.dev_intr"); } else { - st = rrdset_find_bytype("system", "dev_intr"); + st = rrdset_find_bytype_localhost("system", "dev_intr"); if (unlikely(!st)) { - st = rrdset_create("system", "dev_intr", NULL, "interrupts", NULL, "Device Interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "dev_intr", NULL, "interrupts", NULL, "Device Interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -534,11 +534,11 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.dev_intr"); } else { - st = rrdset_find_bytype("system", "soft_intr"); + st = rrdset_find_bytype_localhost("system", "soft_intr"); if (unlikely(!st)) { - st = rrdset_create("system", "soft_intr", NULL, "interrupts", NULL, "Software Interrupts", "interrupts/s", 1100, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "soft_intr", NULL, "interrupts", NULL, "Software Interrupts", "interrupts/s", 1100, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -555,11 +555,11 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.ctxt"); } else { - st = rrdset_find_bytype("system", "ctxt"); + st = rrdset_find_bytype_localhost("system", "ctxt"); if (unlikely(!st)) { - st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -576,12 +576,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.forks"); } else { - st = rrdset_find_bytype("system", "forks"); + st = rrdset_find_bytype_localhost("system", "forks"); if (unlikely(!st)) { - st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -612,12 +612,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype(RRD_TYPE_DISK, disk); + st = rrdset_find_bytype_localhost(RRD_TYPE_DISK, disk); if (unlikely(!st)) { - st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost(RRD_TYPE_DISK, disk, NULL, disk, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -629,13 +629,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_ops", disk); + st = rrdset_find_bytype_localhost("disk_ops", disk); if (unlikely(!st)) { - st = rrdset_create("disk_ops", disk, NULL, disk, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_ops", disk, NULL, disk, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -645,12 +645,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_qops", disk); + st = rrdset_find_bytype_localhost("disk_qops", disk); if (unlikely(!st)) { - st = rrdset_create("disk_qops", disk, NULL, disk, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_qops", disk, NULL, disk, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -659,12 +659,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_util", disk); + st = rrdset_find_bytype_localhost("disk_util", disk); if (unlikely(!st)) { - st = rrdset_create("disk_util", disk, NULL, disk, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("disk_util", disk, NULL, disk, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL); + rrddim_add(st, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -674,13 +674,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_iotime", disk); + st = rrdset_find_bytype_localhost("disk_iotime", disk); if (unlikely(!st)) { - st = rrdset_create("disk_iotime", disk, NULL, disk, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_iotime", disk, NULL, disk, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -698,13 +698,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_await", disk); + st = rrdset_find_bytype_localhost("disk_await", disk); if (unlikely(!st)) { - st = rrdset_create("disk_await", disk, NULL, disk, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_await", disk, NULL, disk, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -716,13 +716,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_avgsz", disk); + st = rrdset_find_bytype_localhost("disk_avgsz", disk); if (unlikely(!st)) { - st = rrdset_create("disk_avgsz", disk, NULL, disk, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("disk_avgsz", disk, NULL, disk, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -734,12 +734,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_svctm", disk); + st = rrdset_find_bytype_localhost("disk_svctm", disk); if (unlikely(!st)) { - st = rrdset_create("disk_svctm", disk, NULL, disk, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_svctm", disk, NULL, disk, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -752,11 +752,11 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("system", "io"); + st = rrdset_find_bytype_localhost("system", "io"); if (unlikely(!st)) { - st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "in", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "out", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -798,13 +798,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { } if (likely(do_swap)) { - st = rrdset_find("system.swap"); + st = rrdset_find_localhost("system.swap"); if (unlikely(!st)) { - st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; + st = rrdset_create_localhost("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -829,18 +829,18 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_ram = 0; error("DISABLED: system.ram"); } else { - st = rrdset_find("system.ram"); + st = rrdset_find_localhost("system.ram"); if (unlikely(!st)) { - st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "active", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); - rrddim_add(st, "inactive", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); - rrddim_add(st, "wired", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "active", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "inactive", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "wired", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); #if __FreeBSD_version < 1200016 - rrddim_add(st, "cache", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "cache", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); #endif - rrddim_add(st, "buffers", NULL, 1, MEGA_FACTOR, RRDDIM_ABSOLUTE); - rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "buffers", NULL, 1, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "free", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -863,12 +863,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_swapio = 0; error("DISABLED: system.swapio"); } else { - st = rrdset_find("system.swapio"); + st = rrdset_find_localhost("system.swapio"); if (unlikely(!st)) { - st = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "in", NULL, system_pagesize, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "in", NULL, system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -889,16 +889,16 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_pgfaults = 0; error("DISABLED: mem.pgfaults"); } else { - st = rrdset_find("mem.pgfaults"); + st = rrdset_find_localhost("mem.pgfaults"); if (unlikely(!st)) { - st = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "memory", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "io_requiring", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "cow", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "cow_optimized", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "in_transit", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "memory", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "io_requiring", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "cow", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "cow_optimized", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "in_transit", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -934,10 +934,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_semaphores"); + st = rrdset_find_localhost("system.ipc_semaphores"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "semaphores", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -946,10 +946,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_semaphore_arrays"); + st = rrdset_find_localhost("system.ipc_semaphore_arrays"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "arrays", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -982,10 +982,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_shared_mem_segs"); + st = rrdset_find_localhost("system.ipc_shared_mem_segs"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_shared_mem_segs", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments", "segments", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "segments", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_shared_mem_segs", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments", "segments", 1000, localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -994,10 +994,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_shared_mem_size"); + st = rrdset_find_localhost("system.ipc_shared_mem_size"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_shared_mem_size", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments Size", "kilobytes", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "allocated", NULL, 1, 1024, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_shared_mem_size", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments Size", "kilobytes", 1000, localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "allocated", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -1034,10 +1034,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_msq_queues"); + st = rrdset_find_localhost("system.ipc_msq_queues"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 990, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "queues", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 990, localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "queues", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -1046,10 +1046,10 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_msq_messages"); + st = rrdset_find_localhost("system.ipc_msq_messages"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_msq_messages", NULL, "ipc message queues", NULL, "Number of Messages in IPC Message Queues", "messages", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "messages", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_msq_messages", NULL, "ipc message queues", NULL, "Number of Messages in IPC Message Queues", "messages", 1000, localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "messages", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -1058,11 +1058,11 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("system.ipc_msq_size"); + st = rrdset_find_localhost("system.ipc_msq_size"); if (unlikely(!st)) { - st = rrdset_create("system", "ipc_msq_size", NULL, "ipc message queues", NULL, "Size of IPC Message Queues", "bytes", 1100, rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "allocated", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ipc_msq_size", NULL, "ipc message queues", NULL, "Size of IPC Message Queues", "bytes", 1100, localhost->rrd_update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -1129,13 +1129,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_netisr)) { - st = rrdset_find_bytype("system", "softnet_stat"); + st = rrdset_find_bytype_localhost("system", "softnet_stat"); if (unlikely(!st)) { - st = rrdset_create("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat", "events/s", 955, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "qdrops", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "queued", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat", "events/s", 955, update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "qdrops", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "queued", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1152,13 +1152,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { for (i = 0; i < ncpus ;i++) { snprintfz(netstat_cpuid, 21, "cpu%d_softnet_stat", i); - st = rrdset_find_bytype("cpu", netstat_cpuid); + st = rrdset_find_bytype_localhost("cpu", netstat_cpuid); if (unlikely(!st)) { - st = rrdset_create("cpu", netstat_cpuid, NULL, "softnet_stat", NULL, "Per CPU netisr statistics", "events/s", 1101 + i, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "qdrops", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "queued", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("cpu", netstat_cpuid, NULL, "softnet_stat", NULL, "Per CPU netisr statistics", "events/s", 1101 + i, update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "qdrops", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "queued", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1186,12 +1186,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { iftot.ift_obytes += IFA_DATA(obytes); } - st = rrdset_find("system.ipv4"); + st = rrdset_find_localhost("system.ipv4"); if (unlikely(!st)) { - st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "InOctets", "received", 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutOctets", "sent", -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1209,12 +1209,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { iftot.ift_obytes += IFA_DATA(obytes); } - st = rrdset_find("system.ipv6"); + st = rrdset_find_localhost("system.ipv6"); if (unlikely(!st)) { - st = rrdset_create("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1228,12 +1228,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1243,15 +1243,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_packets", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_packets", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "multicast_received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "multicast_sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1263,13 +1263,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_errors", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_errors", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1279,14 +1279,14 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_drops", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_drops", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); #if __FreeBSD__ >= 11 - rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); #endif } else rrdset_next(st); @@ -1299,14 +1299,14 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_events", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_events", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1327,12 +1327,12 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.tcpsock"); } else { if (likely(do_tcp_sockets)) { - st = rrdset_find("ipv4.tcpsock"); + st = rrdset_find_localhost("ipv4.tcpsock"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections", + st = rrdset_create_localhost("ipv4", "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections", "active connections", 2500, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "CurrEstab", "connections", 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -1363,14 +1363,14 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.ecnpkts"); } else { if (likely(do_tcp_packets)) { - st = rrdset_find("ipv4.tcppackets"); + st = rrdset_find_localhost("ipv4.tcppackets"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", + st = rrdset_create_localhost("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", "packets/s", 2600, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1382,16 +1382,16 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_tcp_errors)) { - st = rrdset_find("ipv4.tcperrors"); + st = rrdset_find_localhost("ipv4.tcperrors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", + st = rrdset_create_localhost("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s", 2700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1408,17 +1408,17 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_tcp_handshake)) { - st = rrdset_find("ipv4.tcphandshake"); + st = rrdset_find_localhost("ipv4.tcphandshake"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL, + st = rrdset_create_localhost("ipv4", "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1431,17 +1431,17 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop || tcpstat.tcps_finwait2_drops))) { - do_tcpext_connaborts = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpconnaborts"); + if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop || tcpstat.tcps_finwait2_drops))) { + do_tcpext_connaborts = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpconnaborts"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnLinger", "linger", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1455,13 +1455,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) { - do_tcpext_ofo = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpofo"); + if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_rcvoopack)) { + do_tcpext_ofo = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpofo"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1471,16 +1471,16 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) { - do_tcpext_syscookies = CONFIG_ONDEMAND_YES; + if (do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) { + do_tcpext_syscookies = CONFIG_BOOLEAN_YES; - st = rrdset_find("ipv4.tcpsyncookies"); + st = rrdset_find_localhost("ipv4.tcpsyncookies"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1492,17 +1492,17 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_ce || tcpstat.tcps_ecn_ect0 || tcpstat.tcps_ecn_ect1))) { - do_ecn = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.ecnpkts"); + if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_ce || tcpstat.tcps_ecn_ect0 || tcpstat.tcps_ecn_ect1))) { + do_ecn = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.ecnpkts"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1527,13 +1527,13 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.udperrors"); } else { if (likely(do_udp_packets)) { - st = rrdset_find("ipv4.udppackets"); + st = rrdset_find_localhost("ipv4.udppackets"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", + st = rrdset_create_localhost("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", "packets/s", 2601, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1545,17 +1545,17 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_udp_errors)) { - st = rrdset_find("ipv4.udperrors"); + st = rrdset_find_localhost("ipv4.udperrors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", + st = rrdset_create_localhost("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", 2701, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1588,14 +1588,14 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_icmp_packets)) { - st = rrdset_find("ipv4.icmp"); + st = rrdset_find_localhost("ipv4.icmp"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s", + st = rrdset_create_localhost("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s", 2602, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1606,15 +1606,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("ipv4.icmp_errors"); + st = rrdset_find_localhost("ipv4.icmp_errors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors", + st = rrdset_create_localhost("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors", "packets/s", 2603, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1628,15 +1628,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_icmpmsg)) { - st = rrdset_find("ipv4.icmpmsg"); + st = rrdset_find_localhost("ipv4.icmpmsg"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages", + st = rrdset_create_localhost("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages", "packets/s", 2604, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InEchoReps", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InEchoReps", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1665,15 +1665,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.errors"); } else { if (likely(do_ip_packets)) { - st = rrdset_find("ipv4.packets"); + st = rrdset_find_localhost("ipv4.packets"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", + st = rrdset_create_localhost("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InReceives", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutRequests", "sent", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InDelivers", "delivered", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1687,15 +1687,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ip_fragsout)) { - st = rrdset_find("ipv4.fragsout"); + st = rrdset_find_localhost("ipv4.fragsout"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", + st = rrdset_create_localhost("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "FragOKs", "ok", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "FragFails", "failed", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "FragCreates", "created", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1708,16 +1708,16 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ip_fragsin)) { - st = rrdset_find("ipv4.fragsin"); + st = rrdset_find_localhost("ipv4.fragsin"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "fragsin", NULL, "fragments", NULL, + st = rrdset_create_localhost("ipv4", "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ReasmFails", "failed", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ReasmReqds", "all", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1730,21 +1730,21 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ip_errors)) { - st = rrdset_find("ipv4.errors"); + st = rrdset_find_localhost("ipv4.errors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", + st = rrdset_create_localhost("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1772,19 +1772,19 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { do_ip6_errors = 0; error("DISABLED: ipv6.errors"); } else { - if (do_ip6_packets == CONFIG_ONDEMAND_YES || (do_ip6_packets == CONFIG_ONDEMAND_ONDEMAND && + if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_localout || ip6stat.ip6s_total || ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) { - do_ip6_packets = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.packets"); + do_ip6_packets = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.packets"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, + st = rrdset_create_localhost("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1797,19 +1797,19 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ip6_fragsout == CONFIG_ONDEMAND_YES || (do_ip6_fragsout == CONFIG_ONDEMAND_ONDEMAND && + if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag || ip6stat.ip6s_ofragments))) { - do_ip6_fragsout = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.fragsout"); + do_ip6_fragsout = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.fragsout"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", + st = rrdset_create_localhost("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1821,20 +1821,20 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ip6_fragsin == CONFIG_ONDEMAND_YES || (do_ip6_fragsin == CONFIG_ONDEMAND_ONDEMAND && + if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped || ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) { - do_ip6_fragsin = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.fragsin"); + do_ip6_fragsin = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.fragsin"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", + st = rrdset_create_localhost("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1847,7 +1847,7 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ip6_errors == CONFIG_ONDEMAND_YES || (do_ip6_errors == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && ( ip6stat.ip6s_toosmall || ip6stat.ip6s_odropped || ip6stat.ip6s_badoptions || @@ -1857,22 +1857,22 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { ip6stat.ip6s_tooshort || ip6stat.ip6s_cantforward || ip6stat.ip6s_noroute))) { - do_ip6_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.errors"); + do_ip6_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.errors"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, + st = rrdset_create_localhost("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1903,15 +1903,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i]; } icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort; - if (do_icmp6 == CONFIG_ONDEMAND_YES || (do_icmp6 == CONFIG_ONDEMAND_ONDEMAND && (icmp6_total.msgs_in || icmp6_total.msgs_out))) { - do_icmp6 = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmp"); + if (do_icmp6 == CONFIG_BOOLEAN_YES || (do_icmp6 == CONFIG_BOOLEAN_AUTO && (icmp6_total.msgs_in || icmp6_total.msgs_out))) { + do_icmp6 = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmp"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", + st = rrdset_create_localhost("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s", 10000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1922,15 +1922,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_redir == CONFIG_ONDEMAND_YES || (do_icmp6_redir == CONFIG_ONDEMAND_ONDEMAND && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) { - do_icmp6_redir = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmpredir"); + if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) { + do_icmp6_redir = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmpredir"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", + st = rrdset_create_localhost("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1941,7 +1941,7 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_errors == CONFIG_ONDEMAND_YES || (do_icmp6_errors == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_badcode || icmp6stat.icp6s_badlen || icmp6stat.icp6s_checksum || @@ -1953,22 +1953,22 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] || icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] || icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) { - do_icmp6_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmperrors"); + do_icmp6_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmperrors"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1987,20 +1987,20 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_echos == CONFIG_ONDEMAND_YES || (do_icmp6_echos == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] || icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] || icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] || icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) { - do_icmp6_echos = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmpechos"); + do_icmp6_echos = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmpechos"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -2013,20 +2013,20 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_router == CONFIG_ONDEMAND_YES || (do_icmp6_router == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] || icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] || icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] || icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) { - do_icmp6_router = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmprouter"); + do_icmp6_router = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmprouter"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -2039,20 +2039,20 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_neighbor == CONFIG_ONDEMAND_YES || (do_icmp6_neighbor == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] || icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] || icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] || icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) { - do_icmp6_neighbor = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmpneighbor"); + do_icmp6_neighbor = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmpneighbor"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -2065,7 +2065,7 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_types == CONFIG_ONDEMAND_YES || (do_icmp6_types == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[1] || icmp6stat.icp6s_inhist[128] || icmp6stat.icp6s_inhist[129] || @@ -2076,22 +2076,22 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { icmp6stat.icp6s_outhist[133] || icmp6stat.icp6s_outhist[135] || icmp6stat.icp6s_outhist[136]))) { - do_icmp6_types = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmptypes"); + do_icmp6_types = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmptypes"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", + st = rrdset_create_localhost("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", "messages/s", 10700, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -2135,17 +2135,17 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------------- if (likely(do_space)) { - st = rrdset_find_bytype("disk_space", mntbuf[i].f_mntonname); + st = rrdset_find_bytype_localhost("disk_space", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); - st = rrdset_create("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.space", title, "GB", 2023, + st = rrdset_create_localhost("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, - RRDDIM_ABSOLUTE); + RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -2158,15 +2158,15 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------------- if (likely(do_inodes)) { - st = rrdset_find_bytype("disk_inodes", mntbuf[i].f_mntonname); + st = rrdset_find_bytype_localhost("disk_inodes", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); - st = rrdset_create("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.inodes", title, "Inodes", 2024, + st = rrdset_create_localhost("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -2186,11 +2186,11 @@ int do_freebsd_sysctl(int update_every, usec_t dt) { error("DISABLED: system.uptime"); } else { clock_gettime(CLOCK_REALTIME, &cur_time); - st = rrdset_find("system.uptime"); + st = rrdset_find_localhost("system.uptime"); if(unlikely(!st)) { - st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "uptime", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/global_statistics.c b/src/global_statistics.c index a698615f..c3d63043 100644 --- a/src/global_statistics.c +++ b/src/global_statistics.c @@ -129,14 +129,14 @@ void global_statistics_charts(void) { getrusage(RUSAGE_THREAD, &thread); getrusage(RUSAGE_SELF, &me); - if (!stcpu_thread) stcpu_thread = rrdset_find("netdata.plugin_proc_cpu"); + if (!stcpu_thread) stcpu_thread = rrdset_find_localhost("netdata.plugin_proc_cpu"); if (!stcpu_thread) { - stcpu_thread = rrdset_create("netdata", "plugin_proc_cpu", NULL, "proc", NULL, - "NetData Proc Plugin CPU usage", "milliseconds/s", 132000, rrd_update_every, - RRDSET_TYPE_STACKED); + stcpu_thread = rrdset_create_localhost("netdata", "plugin_proc_cpu", NULL, "proc", NULL + , "NetData Proc Plugin CPU usage", "milliseconds/s", 132000 + , localhost->rrd_update_every, RRDSET_TYPE_STACKED); - rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); + rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); rrddim_set(stcpu_thread, "user", thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); @@ -145,13 +145,13 @@ void global_statistics_charts(void) { // ---------------------------------------------------------------- - if (!stcpu) stcpu = rrdset_find("netdata.server_cpu"); + if (!stcpu) stcpu = rrdset_find_localhost("netdata.server_cpu"); if (!stcpu) { - stcpu = rrdset_create("netdata", "server_cpu", NULL, "netdata", NULL, "NetData CPU usage", "milliseconds/s", - 130000, rrd_update_every, RRDSET_TYPE_STACKED); + stcpu = rrdset_create_localhost("netdata", "server_cpu", NULL, "netdata", NULL, "NetData CPU usage" + , "milliseconds/s", 130000, localhost->rrd_update_every, RRDSET_TYPE_STACKED); - rrddim_add(stcpu, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rrddim_add(stcpu, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); + rrddim_add(stcpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(stcpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu); rrddim_set(stcpu, "user", me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec); @@ -160,12 +160,12 @@ void global_statistics_charts(void) { // ---------------------------------------------------------------- - if (!stclients) stclients = rrdset_find("netdata.clients"); + if (!stclients) stclients = rrdset_find_localhost("netdata.clients"); if (!stclients) { - stclients = rrdset_create("netdata", "clients", NULL, "netdata", NULL, "NetData Web Clients", - "connected clients", 130200, rrd_update_every, RRDSET_TYPE_LINE); + stclients = rrdset_create_localhost("netdata", "clients", NULL, "netdata", NULL, "NetData Web Clients" + , "connected clients", 130200, localhost->rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(stclients, "clients", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(stclients, "clients", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(stclients); rrddim_set(stclients, "clients", gs.connected_clients); @@ -173,12 +173,12 @@ void global_statistics_charts(void) { // ---------------------------------------------------------------- - if (!streqs) streqs = rrdset_find("netdata.requests"); + if (!streqs) streqs = rrdset_find_localhost("netdata.requests"); if (!streqs) { - streqs = rrdset_create("netdata", "requests", NULL, "netdata", NULL, "NetData Web Requests", "requests/s", - 130300, rrd_update_every, RRDSET_TYPE_LINE); + streqs = rrdset_create_localhost("netdata", "requests", NULL, "netdata", NULL, "NetData Web Requests" + , "requests/s", 130300, localhost->rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(streqs, "requests", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(streqs, "requests", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(streqs); rrddim_set(streqs, "requests", (collected_number) gs.web_requests); @@ -186,13 +186,13 @@ void global_statistics_charts(void) { // ---------------------------------------------------------------- - if (!stbytes) stbytes = rrdset_find("netdata.net"); + if (!stbytes) stbytes = rrdset_find_localhost("netdata.net"); if (!stbytes) { - stbytes = rrdset_create("netdata", "net", NULL, "netdata", NULL, "NetData Network Traffic", "kilobits/s", - 130000, rrd_update_every, RRDSET_TYPE_AREA); + stbytes = rrdset_create_localhost("netdata", "net", NULL, "netdata", NULL, "NetData Network Traffic" + , "kilobits/s", 130000, localhost->rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(stbytes, "in", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(stbytes, "out", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(stbytes, "in", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(stbytes, "out", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stbytes); rrddim_set(stbytes, "in", (collected_number) gs.bytes_received); @@ -201,13 +201,14 @@ void global_statistics_charts(void) { // ---------------------------------------------------------------- - if (!stduration) stduration = rrdset_find("netdata.response_time"); + if (!stduration) stduration = rrdset_find_localhost("netdata.response_time"); if (!stduration) { - stduration = rrdset_create("netdata", "response_time", NULL, "netdata", NULL, "NetData API Response Time", - "ms/request", 130400, rrd_update_every, RRDSET_TYPE_LINE); + stduration = rrdset_create_localhost("netdata", "response_time", NULL, "netdata", NULL + , "NetData API Response Time", "ms/request", 130400, localhost->rrd_update_every + , RRDSET_TYPE_LINE); - rrddim_add(stduration, "average", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(stduration, "max", NULL, 1, 1000, RRDDIM_ABSOLUTE); + rrddim_add(stduration, "average", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stduration, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(stduration); uint64_t gweb_usec = gs.web_usec; @@ -232,13 +233,13 @@ void global_statistics_charts(void) { // ---------------------------------------------------------------- - if (!stcompression) stcompression = rrdset_find("netdata.compression_ratio"); + if (!stcompression) stcompression = rrdset_find_localhost("netdata.compression_ratio"); if (!stcompression) { - stcompression = rrdset_create("netdata", "compression_ratio", NULL, "netdata", NULL, - "NetData API Responses Compression Savings Ratio", "percentage", 130500, - rrd_update_every, RRDSET_TYPE_LINE); + stcompression = rrdset_create_localhost("netdata", "compression_ratio", NULL, "netdata", NULL + , "NetData API Responses Compression Savings Ratio", "percentage" + , 130500, localhost->rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(stcompression, "savings", NULL, 1, 1000, RRDDIM_ABSOLUTE); + rrddim_add(stcompression, "savings", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(stcompression); // since we don't lock here to read the global statistics diff --git a/src/health.c b/src/health.c index 9df2e241..0c7983ec 100644 --- a/src/health.c +++ b/src/health.c @@ -1,2742 +1,84 @@ +#define NETDATA_HEALTH_INTERNALS #include "common.h" -#define RRDVAR_MAX_LENGTH 1024 +int default_health_enabled = 1; -struct health_options { - const char *health_default_exec; - const char *health_default_recipient; - const char *log_filename; - size_t log_entries_written; - FILE *log_fp; -}; - -static struct health_options health = { - .health_default_exec = NULL, - .health_default_recipient = "root", - .log_filename = NULL, - .log_entries_written = 0, - .log_fp = NULL -}; - -int health_enabled = 1; - -// ---------------------------------------------------------------------------- -// health alarm log load/save -// no need for locking - only one thread is reading / writing the alarms log - -static inline int health_alarm_log_open(void) { - if(health.log_fp) - fclose(health.log_fp); - - health.log_fp = fopen(health.log_filename, "a"); - - if(health.log_fp) { - if (setvbuf(health.log_fp, NULL, _IOLBF, 0) != 0) - error("Health: cannot set line buffering on health log file."); - return 0; - } - - error("Health: cannot open health log file '%s'. Health data will be lost in case of netdata or server crash.", health.log_filename); - return -1; -} - -static inline void health_alarm_log_close(void) { - if(health.log_fp) { - fclose(health.log_fp); - health.log_fp = NULL; - } -} - -static inline void health_log_rotate(void) { - static size_t rotate_every = 0; - - if(unlikely(rotate_every == 0)) { - rotate_every = (size_t)config_get_number("health", "rotate log every lines", 2000); - if(rotate_every < 100) rotate_every = 100; - } - - if(unlikely(health.log_entries_written > rotate_every)) { - health_alarm_log_close(); - - char old_filename[FILENAME_MAX + 1]; - snprintfz(old_filename, FILENAME_MAX, "%s.old", health.log_filename); - - if(unlink(old_filename) == -1 && errno != ENOENT) - error("Health: cannot remove old alarms log file '%s'", old_filename); - - if(link(health.log_filename, old_filename) == -1 && errno != ENOENT) - error("Health: cannot move file '%s' to '%s'.", health.log_filename, old_filename); - - if(unlink(health.log_filename) == -1 && errno != ENOENT) - error("Health: cannot remove old alarms log file '%s'", health.log_filename); - - // open it with truncate - health.log_fp = fopen(health.log_filename, "w"); - - if(health.log_fp) - fclose(health.log_fp); - else - error("Health: cannot truncate health log '%s'", health.log_filename); - - health.log_fp = NULL; - - health.log_entries_written = 0; - health_alarm_log_open(); - } -} - -static inline void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae) { - health_log_rotate(); - - if(likely(health.log_fp)) { - if(unlikely(fprintf(health.log_fp - , "%c\t%s" - "\t%08x\t%08x\t%08x\t%08x\t%08x" - "\t%08x\t%08x\t%08x" - "\t%08x\t%08x\t%08x" - "\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" - "\t%d\t%d\t%d\t%d" - "\t%Lf\t%Lf" - "\n" - , (ae->flags & HEALTH_ENTRY_FLAG_SAVED)?'U':'A' - , host->hostname - - , ae->unique_id - , ae->alarm_id - , ae->alarm_event_id - , ae->updated_by_id - , ae->updates_id - - , (uint32_t)ae->when - , (uint32_t)ae->duration - , (uint32_t)ae->non_clear_duration - , (uint32_t)ae->flags - , (uint32_t)ae->exec_run_timestamp - , (uint32_t)ae->delay_up_to_timestamp - - , (ae->name)?ae->name:"" - , (ae->chart)?ae->chart:"" - , (ae->family)?ae->family:"" - , (ae->exec)?ae->exec:"" - , (ae->recipient)?ae->recipient:"" - , (ae->source)?ae->source:"" - , (ae->units)?ae->units:"" - , (ae->info)?ae->info:"" - - , ae->exec_code - , ae->new_status - , ae->old_status - , ae->delay - - , (long double)ae->new_value - , (long double)ae->old_value - ) < 0)) - error("Health: failed to save alarm log entry. Health data may be lost in case of abnormal restart."); - else { - ae->flags |= HEALTH_ENTRY_FLAG_SAVED; - health.log_entries_written++; - } - } -} - -static inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename) { - static uint32_t max_unique_id = 0, max_alarm_id = 0; - - errno = 0; - - char *s, *buf = mallocz(65536 + 1); - size_t line = 0, len = 0; - ssize_t loaded = 0, updated = 0, errored = 0, duplicate = 0; - - pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); - - while((s = fgets_trim_len(buf, 65536, fp, &len))) { - health.log_entries_written++; - line++; - - int max_entries = 30, entries = 0; - char *pointers[max_entries]; - - pointers[entries++] = s++; - while(*s) { - if(unlikely(*s == '\t')) { - *s = '\0'; - pointers[entries++] = ++s; - if(entries >= max_entries) { - error("Health: line %zu of file '%s' has more than %d entries. Ignoring excessive entries.", line, filename, max_entries); - break; - } - } - else s++; - } - - if(likely(*pointers[0] == 'U' || *pointers[0] == 'A')) { - ALARM_ENTRY *ae = NULL; - - if(entries < 26) { - error("Health: line %zu of file '%s' should have at least 26 entries, but it has %d. Ignoring it.", line, filename, entries); - errored++; - continue; - } - - // check that we have valid ids - uint32_t unique_id = (uint32_t)strtoul(pointers[2], NULL, 16); - if(!unique_id) { - error("Health: line %zu of file '%s' states alarm entry with invalid unique id %u (%s). Ignoring it.", line, filename, unique_id, pointers[2]); - errored++; - continue; - } - - uint32_t alarm_id = (uint32_t)strtoul(pointers[3], NULL, 16); - if(!alarm_id) { - error("Health: line %zu of file '%s' states alarm entry for invalid alarm id %u (%s). Ignoring it.", line, filename, alarm_id, pointers[3]); - errored++; - continue; - } - - if(unlikely(*pointers[0] == 'A')) { - // make sure it is properly numbered - if(unlikely(host->health_log.alarms && unique_id < host->health_log.alarms->unique_id)) { - error("Health: line %zu of file '%s' has alarm log entry with %u in wrong order. Ignoring it.", line, filename, unique_id); - errored++; - continue; - } - - ae = callocz(1, sizeof(ALARM_ENTRY)); - } - else if(unlikely(*pointers[0] == 'U')) { - // find the original - for(ae = host->health_log.alarms; ae; ae = ae->next) { - if(unlikely(unique_id == ae->unique_id)) { - if(unlikely(*pointers[0] == 'A')) { - error("Health: line %zu of file '%s' adds duplicate alarm log entry with unique id %u. Using the later." - , line, filename, unique_id); - *pointers[0] = 'U'; - duplicate++; - } - break; - } - else if(unlikely(unique_id > ae->unique_id)) { - // no need to continue - // the linked list is sorted - ae = NULL; - break; - } - } - - // if not found, skip this line - if(!ae) { - // error("Health: line %zu of file '%s' updates alarm log entry with unique id %u, but it is not found.", line, filename, unique_id); - continue; - } - } - - // check for a possible host missmatch - //if(strcmp(pointers[1], host->hostname)) - // error("Health: line %zu of file '%s' provides an alarm for host '%s' but this is named '%s'.", line, filename, pointers[1], host->hostname); - - ae->unique_id = unique_id; - ae->alarm_id = alarm_id; - ae->alarm_event_id = (uint32_t)strtoul(pointers[4], NULL, 16); - ae->updated_by_id = (uint32_t)strtoul(pointers[5], NULL, 16); - ae->updates_id = (uint32_t)strtoul(pointers[6], NULL, 16); - - ae->when = (uint32_t)strtoul(pointers[7], NULL, 16); - ae->duration = (uint32_t)strtoul(pointers[8], NULL, 16); - ae->non_clear_duration = (uint32_t)strtoul(pointers[9], NULL, 16); - - ae->flags = (uint32_t)strtoul(pointers[10], NULL, 16); - ae->flags |= HEALTH_ENTRY_FLAG_SAVED; - - ae->exec_run_timestamp = (uint32_t)strtoul(pointers[11], NULL, 16); - ae->delay_up_to_timestamp = (uint32_t)strtoul(pointers[12], NULL, 16); - - freez(ae->name); - ae->name = strdupz(pointers[13]); - ae->hash_name = simple_hash(ae->name); - - freez(ae->chart); - ae->chart = strdupz(pointers[14]); - ae->hash_chart = simple_hash(ae->chart); - - freez(ae->family); - ae->family = strdupz(pointers[15]); - - freez(ae->exec); - ae->exec = strdupz(pointers[16]); - if(!*ae->exec) { freez(ae->exec); ae->exec = NULL; } - - freez(ae->recipient); - ae->recipient = strdupz(pointers[17]); - if(!*ae->recipient) { freez(ae->recipient); ae->recipient = NULL; } - - freez(ae->source); - ae->source = strdupz(pointers[18]); - if(!*ae->source) { freez(ae->source); ae->source = NULL; } - - freez(ae->units); - ae->units = strdupz(pointers[19]); - if(!*ae->units) { freez(ae->units); ae->units = NULL; } - - freez(ae->info); - ae->info = strdupz(pointers[20]); - if(!*ae->info) { freez(ae->info); ae->info = NULL; } - - ae->exec_code = str2i(pointers[21]); - ae->new_status = str2i(pointers[22]); - ae->old_status = str2i(pointers[23]); - ae->delay = str2i(pointers[24]); - - ae->new_value = str2l(pointers[25]); - ae->old_value = str2l(pointers[26]); - - static char value_string[100 + 1]; - freez(ae->old_value_string); - freez(ae->new_value_string); - ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1)); - ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1)); - - // add it to host if not already there - if(unlikely(*pointers[0] == 'A')) { - ae->next = host->health_log.alarms; - host->health_log.alarms = ae; - loaded++; - } - else updated++; - - if(unlikely(ae->unique_id > max_unique_id)) - max_unique_id = ae->unique_id; - - if(unlikely(ae->alarm_id >= max_alarm_id)) - max_alarm_id = ae->alarm_id; - } - else { - error("Health: line %zu of file '%s' is invalid (unrecognized entry type '%s').", line, filename, pointers[0]); - errored++; - } - } - - pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); - - freez(buf); - - if(!max_unique_id) max_unique_id = (uint32_t)now_realtime_sec(); - if(!max_alarm_id) max_alarm_id = (uint32_t)now_realtime_sec(); - - host->health_log.next_log_id = max_unique_id + 1; - host->health_log.next_alarm_id = max_alarm_id + 1; - - debug(D_HEALTH, "Health: loaded file '%s' with %zd new alarm entries, updated %zd alarms, errors %zd entries, duplicate %zd", filename, loaded, updated, errored, duplicate); - return loaded; -} - -static inline void health_alarm_log_load(RRDHOST *host) { - health_alarm_log_close(); - - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s.old", health.log_filename); - FILE *fp = fopen(filename, "r"); - if(!fp) - error("Health: cannot open health file: %s", filename); - else { - health_alarm_log_read(host, fp, filename); - fclose(fp); - } - - health.log_entries_written = 0; - fp = fopen(health.log_filename, "r"); - if(!fp) - error("Health: cannot open health file: %s", health.log_filename); - else { - health_alarm_log_read(host, fp, health.log_filename); - fclose(fp); - } - - health_alarm_log_open(); -} - - -// ---------------------------------------------------------------------------- -// health alarm log management - -static inline void health_alarm_log( - RRDHOST *host, - uint32_t alarm_id, - uint32_t alarm_event_id, - time_t when, - const char *name, - const char *chart, - const char *family, - const char *exec, - const char *recipient, - time_t duration, - calculated_number old_value, - calculated_number new_value, - int old_status, - int new_status, - const char *source, - const char *units, - const char *info, - int delay, - uint32_t flags -) { - debug(D_HEALTH, "Health adding alarm log entry with id: %u", host->health_log.next_log_id); - - ALARM_ENTRY *ae = callocz(1, sizeof(ALARM_ENTRY)); - ae->name = strdupz(name); - ae->hash_name = simple_hash(ae->name); - - if(chart) { - ae->chart = strdupz(chart); - ae->hash_chart = simple_hash(ae->chart); - } - - if(family) - ae->family = strdupz(family); - - if(exec) ae->exec = strdupz(exec); - if(recipient) ae->recipient = strdupz(recipient); - if(source) ae->source = strdupz(source); - if(units) ae->units = strdupz(units); - if(info) ae->info = strdupz(info); - - ae->unique_id = host->health_log.next_log_id++; - ae->alarm_id = alarm_id; - ae->alarm_event_id = alarm_event_id; - ae->when = when; - ae->old_value = old_value; - ae->new_value = new_value; - - static char value_string[100 + 1]; - ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1)); - ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1)); - - ae->old_status = old_status; - ae->new_status = new_status; - ae->duration = duration; - ae->delay = delay; - ae->delay_up_to_timestamp = when + delay; - - ae->flags |= flags; - - if(ae->old_status == RRDCALC_STATUS_WARNING || ae->old_status == RRDCALC_STATUS_CRITICAL) - ae->non_clear_duration += ae->duration; - - // link it - pthread_rwlock_wrlock(&host->health_log.alarm_log_rwlock); - ae->next = host->health_log.alarms; - host->health_log.alarms = ae; - host->health_log.count++; - pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); - - // match previous alarms - pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); - ALARM_ENTRY *t; - for(t = host->health_log.alarms ; t ; t = t->next) { - if(t != ae && t->alarm_id == ae->alarm_id) { - if(!(t->flags & HEALTH_ENTRY_FLAG_UPDATED) && !t->updated_by_id) { - t->flags |= HEALTH_ENTRY_FLAG_UPDATED; - t->updated_by_id = ae->unique_id; - ae->updates_id = t->unique_id; - - if((t->new_status == RRDCALC_STATUS_WARNING || t->new_status == RRDCALC_STATUS_CRITICAL) && - (t->old_status == RRDCALC_STATUS_WARNING || t->old_status == RRDCALC_STATUS_CRITICAL)) - ae->non_clear_duration += t->non_clear_duration; - - health_alarm_log_save(host, t); - } - - // no need to continue - break; - } - } - pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); - - health_alarm_log_save(host, ae); -} - -// ---------------------------------------------------------------------------- -// RRDVAR management - -static inline int rrdvar_fix_name(char *variable) { - int fixed = 0; - while(*variable) { - if (!isalnum(*variable) && *variable != '.' && *variable != '_') { - *variable++ = '_'; - fixed++; - } - else - variable++; - } - - return fixed; -} - -int rrdvar_compare(void* a, void* b) { - if(((RRDVAR *)a)->hash < ((RRDVAR *)b)->hash) return -1; - else if(((RRDVAR *)a)->hash > ((RRDVAR *)b)->hash) return 1; - else return strcmp(((RRDVAR *)a)->name, ((RRDVAR *)b)->name); -} - -static inline RRDVAR *rrdvar_index_add(avl_tree_lock *tree, RRDVAR *rv) { - RRDVAR *ret = (RRDVAR *)avl_insert_lock(tree, (avl *)(rv)); - if(ret != rv) - debug(D_VARIABLES, "Request to insert RRDVAR '%s' into index failed. Already exists.", rv->name); - - return ret; -} - -static inline RRDVAR *rrdvar_index_del(avl_tree_lock *tree, RRDVAR *rv) { - RRDVAR *ret = (RRDVAR *)avl_remove_lock(tree, (avl *)(rv)); - if(!ret) - error("Request to remove RRDVAR '%s' from index failed. Not Found.", rv->name); - - return ret; -} - -static inline RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) { - RRDVAR tmp; - tmp.name = (char *)name; - tmp.hash = (hash)?hash:simple_hash(tmp.name); - - return (RRDVAR *)avl_search_lock(tree, (avl *)&tmp); -} - -static inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) { - (void)host; - - if(!rv) return; - - if(tree) { - debug(D_VARIABLES, "Deleting variable '%s'", rv->name); - if(unlikely(!rrdvar_index_del(tree, rv))) - error("Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname); - } - - freez(rv->name); - freez(rv); -} - -static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, void *value) { - char *variable = strdupz(name); - rrdvar_fix_name(variable); - uint32_t hash = simple_hash(variable); - - RRDVAR *rv = rrdvar_index_find(tree, variable, hash); - if(unlikely(!rv)) { - debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", variable, scope); - - rv = callocz(1, sizeof(RRDVAR)); - rv->name = variable; - rv->hash = hash; - rv->type = type; - rv->value = value; - - RRDVAR *ret = rrdvar_index_add(tree, rv); - if(unlikely(ret != rv)) { - debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", variable, scope); - rrdvar_free(NULL, NULL, rv); - rv = NULL; - } - else - debug(D_VARIABLES, "Variable '%s' created in scope '%s'", variable, scope); - } - else { - debug(D_VARIABLES, "Variable '%s' is already found in scope '%s'.", variable, scope); - - // already exists - freez(variable); - - // this is important - // it must return NULL - not the existing variable - or double-free will happen - rv = NULL; - } - - return rv; -} - -// ---------------------------------------------------------------------------- -// CUSTOM VARIABLES - -RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) { - calculated_number *v = callocz(1, sizeof(calculated_number)); - *v = NAN; - RRDVAR *rv = rrdvar_create_and_index("host", &host->variables_root_index, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); - if(unlikely(!rv)) { - free(v); - error("Requested variable '%s' already exists - possibly 2 plugins will be updating it at the same time", name); - - char *variable = strdupz(name); - rrdvar_fix_name(variable); - uint32_t hash = simple_hash(variable); - - rv = rrdvar_index_find(&host->variables_root_index, variable, hash); - } - - return rv; -} - -void rrdvar_custom_host_variable_destroy(RRDHOST *host, const char *name) { - char *variable = strdupz(name); - rrdvar_fix_name(variable); - uint32_t hash = simple_hash(variable); - - RRDVAR *rv = rrdvar_index_find(&host->variables_root_index, variable, hash); - freez(variable); - - if(!rv) { - error("Attempted to remove variable '%s' from host '%s', but it does not exist.", name, host->hostname); - return; - } - - if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) { - error("Attempted to remove variable '%s' from host '%s', but it does not a custom allocated variable.", name, host->hostname); - return; - } - - if(!rrdvar_index_del(&host->variables_root_index, rv)) { - error("Attempted to remove variable '%s' from host '%s', but it cannot be found.", name, host->hostname); - return; - } - - freez(rv->name); - freez(rv->value); - freez(rv); -} - -void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value) { - if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) - error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value); - else { - calculated_number *v = rv->value; - *v = value; - } -} - -// ---------------------------------------------------------------------------- -// RRDVAR lookup - -static calculated_number rrdvar2number(RRDVAR *rv) { - switch(rv->type) { - case RRDVAR_TYPE_CALCULATED_ALLOCATED: - case RRDVAR_TYPE_CALCULATED: { - calculated_number *n = (calculated_number *)rv->value; - return *n; - } - - case RRDVAR_TYPE_TIME_T: { - time_t *n = (time_t *)rv->value; - return *n; - } - - case RRDVAR_TYPE_COLLECTED: { - collected_number *n = (collected_number *)rv->value; - return *n; - } - - case RRDVAR_TYPE_TOTAL: { - total_number *n = (total_number *)rv->value; - return *n; - } - - case RRDVAR_TYPE_INT: { - int *n = (int *)rv->value; - return *n; - } - - default: - error("I don't know how to convert RRDVAR type %d to calculated_number", rv->type); - return NAN; - } -} - -int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) { - RRDSET *st = rc->rrdset; - RRDVAR *rv; - - if(!st) return 0; - - rv = rrdvar_index_find(&st->variables_root_index, variable, hash); - if(rv) { - *result = rrdvar2number(rv); - return 1; - } - - rv = rrdvar_index_find(&st->rrdfamily->variables_root_index, variable, hash); - if(rv) { - *result = rrdvar2number(rv); - return 1; - } - - rv = rrdvar_index_find(&st->rrdhost->variables_root_index, variable, hash); - if(rv) { - *result = rrdvar2number(rv); - return 1; - } - - return 0; -} - -// ---------------------------------------------------------------------------- -// RRDVAR to JSON - -struct variable2json_helper { - BUFFER *buf; - size_t counter; -}; - -static int single_variable2json(void *entry, void *data) { - struct variable2json_helper *helper = (struct variable2json_helper *)data; - RRDVAR *rv = (RRDVAR *)entry; - calculated_number value = rrdvar2number(rv); - - if(unlikely(isnan(value) || isinf(value))) - buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": null", helper->counter?",":"", rv->name); - else - buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": %0.5Lf", helper->counter?",":"", rv->name, (long double)value); - - helper->counter++; - - return 0; -} - -void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) { - struct variable2json_helper helper = { - .buf = buf, - .counter = 0 - }; - - buffer_sprintf(buf, "{\n\t\"chart\": \"%s\",\n\t\"chart_name\": \"%s\",\n\t\"chart_context\": \"%s\",\n\t\"chart_variables\": {", st->id, st->name, st->context); - avl_traverse_lock(&st->variables_root_index, single_variable2json, (void *)&helper); - buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family); - helper.counter = 0; - avl_traverse_lock(&st->rrdfamily->variables_root_index, single_variable2json, (void *)&helper); - buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", st->rrdhost->hostname); - helper.counter = 0; - avl_traverse_lock(&st->rrdhost->variables_root_index, single_variable2json, (void *)&helper); - buffer_strcat(buf, "\n\t}\n}\n"); -} - - -// ---------------------------------------------------------------------------- -// RRDDIMVAR management -// DIMENSION VARIABLES - -#define RRDDIMVAR_ID_MAX 1024 - -static inline void rrddimvar_free_variables(RRDDIMVAR *rs) { - RRDDIM *rd = rs->rrddim; - RRDSET *st = rd->rrdset; - - // CHART VARIABLES FOR THIS DIMENSION - - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_id); - rs->var_local_id = NULL; - - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_name); - rs->var_local_name = NULL; - - // FAMILY VARIABLES FOR THIS DIMENSION - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_id); - rs->var_family_id = NULL; - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); - rs->var_family_name = NULL; - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextid); - rs->var_family_contextid = NULL; - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextname); - rs->var_family_contextname = NULL; - - // HOST VARIABLES FOR THIS DIMENSION - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidid); - rs->var_host_chartidid = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidname); - rs->var_host_chartidname = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnameid); - rs->var_host_chartnameid = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnamename); - rs->var_host_chartnamename = NULL; - - // KEYS - - freez(rs->key_id); - rs->key_id = NULL; - - freez(rs->key_name); - rs->key_name = NULL; - - freez(rs->key_fullidid); - rs->key_fullidid = NULL; - - freez(rs->key_fullidname); - rs->key_fullidname = NULL; - - freez(rs->key_contextid); - rs->key_contextid = NULL; - - freez(rs->key_contextname); - rs->key_contextname = NULL; - - freez(rs->key_fullnameid); - rs->key_fullnameid = NULL; - - freez(rs->key_fullnamename); - rs->key_fullnamename = NULL; -} - -static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { - rrddimvar_free_variables(rs); - - RRDDIM *rd = rs->rrddim; - RRDSET *st = rd->rrdset; - - char buffer[RRDDIMVAR_ID_MAX + 1]; - - // KEYS - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->id, rs->suffix); - rs->key_id = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix); - rs->key_name = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_id); - rs->key_fullidid = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_name); - rs->key_fullidname = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_id); - rs->key_contextid = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_name); - rs->key_contextname = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_id); - rs->key_fullnameid = strdupz(buffer); - - snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_name); - rs->key_fullnamename = strdupz(buffer); - - // CHART VARIABLES FOR THIS DIMENSION - // ----------------------------------- - // - // dimensions are available as: - // - $id - // - $name - - rs->var_local_id = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_id, rs->type, rs->value); - rs->var_local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_name, rs->type, rs->value); - - // FAMILY VARIABLES FOR THIS DIMENSION - // ----------------------------------- - // - // dimensions are available as: - // - $id (only the first, when multiple overlap) - // - $name (only the first, when multiple overlap) - // - $chart-context.id - // - $chart-context.name - - rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_id, rs->type, rs->value); - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_name, rs->type, rs->value); - rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextid, rs->type, rs->value); - rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextname, rs->type, rs->value); - - // HOST VARIABLES FOR THIS DIMENSION - // ----------------------------------- - // - // dimensions are available as: - // - $chart-id.id - // - $chart-id.name - // - $chart-name.id - // - $chart-name.name - - rs->var_host_chartidid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidid, rs->type, rs->value); - rs->var_host_chartidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidname, rs->type, rs->value); - rs->var_host_chartnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnameid, rs->type, rs->value); - rs->var_host_chartnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnamename, rs->type, rs->value); -} - -RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) { - RRDSET *st = rd->rrdset; - - debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:""); - - if(!prefix) prefix = ""; - if(!suffix) suffix = ""; - - RRDDIMVAR *rs = (RRDDIMVAR *)callocz(1, sizeof(RRDDIMVAR)); - - rs->prefix = strdupz(prefix); - rs->suffix = strdupz(suffix); - - rs->type = type; - rs->value = value; - rs->options = options; - rs->rrddim = rd; - - rs->next = rd->variables; - rd->variables = rs; - - rrddimvar_create_variables(rs); - - return rs; -} - -void rrddimvar_rename_all(RRDDIM *rd) { - RRDSET *st = rd->rrdset; - debug(D_VARIABLES, "RRDDIMSET rename for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); - - RRDDIMVAR *rs, *next = rd->variables; - while((rs = next)) { - next = rs->next; - rrddimvar_create_variables(rs); - } -} - -void rrddimvar_free(RRDDIMVAR *rs) { - RRDDIM *rd = rs->rrddim; - RRDSET *st = rd->rrdset; - debug(D_VARIABLES, "RRDDIMSET free for chart id '%s' name '%s', dimension id '%s', name '%s', prefix='%s', suffix='%s'", st->id, st->name, rd->id, rd->name, rs->prefix, rs->suffix); - - rrddimvar_free_variables(rs); - - if(rd->variables == rs) { - debug(D_VARIABLES, "RRDDIMSET removing first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); - rd->variables = rs->next; - } - else { - debug(D_VARIABLES, "RRDDIMSET removing non-first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); - RRDDIMVAR *t; - for (t = rd->variables; t && t->next != rs; t = t->next) ; - if(!t) error("RRDDIMVAR '%s' not found in dimension '%s/%s' variables linked list", rs->key_name, st->id, rd->id); - else t->next = rs->next; - } - - freez(rs->prefix); - freez(rs->suffix); - freez(rs); -} - -// ---------------------------------------------------------------------------- -// RRDSETVAR management -// CHART VARIABLES - -static inline void rrdsetvar_free_variables(RRDSETVAR *rs) { - RRDSET *st = rs->rrdset; - - // CHART - - rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local); - rs->var_local = NULL; - - // FAMILY - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family); - rs->var_family = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host); - rs->var_host = NULL; - - // HOST - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); - rs->var_family_name = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_name); - rs->var_host_name = NULL; - - // KEYS - - freez(rs->key_fullid); - rs->key_fullid = NULL; - - freez(rs->key_fullname); - rs->key_fullname = NULL; -} - -static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { - rrdsetvar_free_variables(rs); - - RRDSET *st = rs->rrdset; - - // KEYS - - char buffer[RRDVAR_MAX_LENGTH + 1]; - snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rs->variable); - rs->key_fullid = strdupz(buffer); - - snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable); - rs->key_fullname = strdupz(buffer); - - // CHART - - rs->var_local = rrdvar_create_and_index("local", &st->variables_root_index, rs->variable, rs->type, rs->value); - - // FAMILY - - rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullid, rs->type, rs->value); - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullname, rs->type, rs->value); - - // HOST - - rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullid, rs->type, rs->value); - rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullname, rs->type, rs->value); - -} - -RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) { - debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable); - RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR)); - - rs->variable = strdupz(variable); - rs->type = type; - rs->value = value; - rs->options = options; - rs->rrdset = st; - - rs->next = st->variables; - st->variables = rs; - - rrdsetvar_create_variables(rs); - - return rs; -} - -void rrdsetvar_rename_all(RRDSET *st) { - debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name); - - RRDSETVAR *rs, *next = st->variables; - while((rs = next)) { - next = rs->next; - rrdsetvar_create_variables(rs); - } - - rrdsetcalc_link_matching(st); -} - -void rrdsetvar_free(RRDSETVAR *rs) { - RRDSET *st = rs->rrdset; - debug(D_VARIABLES, "RRDSETVAR free for chart id '%s' name '%s', variable '%s'", st->id, st->name, rs->variable); - - if(st->variables == rs) { - st->variables = rs->next; - } - else { - RRDSETVAR *t; - for (t = st->variables; t && t->next != rs; t = t->next); - if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->key_fullname, st->id); - else t->next = rs->next; - } - - rrdsetvar_free_variables(rs); - - freez(rs->variable); - freez(rs); -} - -// ---------------------------------------------------------------------------- -// RRDCALC management - -inline const char *rrdcalc_status2string(int status) { - switch(status) { - case RRDCALC_STATUS_REMOVED: - return "REMOVED"; - - case RRDCALC_STATUS_UNDEFINED: - return "UNDEFINED"; - - case RRDCALC_STATUS_UNINITIALIZED: - return "UNINITIALIZED"; - - case RRDCALC_STATUS_CLEAR: - return "CLEAR"; - - case RRDCALC_STATUS_RAISED: - return "RAISED"; - - case RRDCALC_STATUS_WARNING: - return "WARNING"; - - case RRDCALC_STATUS_CRITICAL: - return "CRITICAL"; - - default: - error("Unknown alarm status %d", status); - return "UNKNOWN"; - } -} - -static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) { - debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, st->rrdhost->hostname); - - rc->last_status_change = now_realtime_sec(); - rc->rrdset = st; - - rc->rrdset_next = st->alarms; - rc->rrdset_prev = NULL; - - if(rc->rrdset_next) - rc->rrdset_next->rrdset_prev = rc; - - st->alarms = rc; - - if(rc->update_every < rc->rrdset->update_every) { - error("Health alarm '%s.%s' has update every %d, less than chart update every %d. Setting alarm update frequency to %d.", rc->rrdset->id, rc->name, rc->update_every, rc->rrdset->update_every, rc->rrdset->update_every); - rc->update_every = rc->rrdset->update_every; - } - - if(!isnan(rc->green) && isnan(st->green)) { - debug(D_HEALTH, "Health alarm '%s.%s' green threshold set from %Lf to %Lf.", rc->rrdset->id, rc->name, rc->rrdset->green, rc->green); - st->green = rc->green; - } - - if(!isnan(rc->red) && isnan(st->red)) { - debug(D_HEALTH, "Health alarm '%s.%s' red threshold set from %Lf to %Lf.", rc->rrdset->id, rc->name, rc->rrdset->red, rc->red); - st->red = rc->red; - } - - rc->local = rrdvar_create_and_index("local", &st->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); - rc->family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); - - char fullname[RRDVAR_MAX_LENGTH + 1]; - snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name); - rc->hostid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); - - snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name); - rc->hostname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); - - if(!rc->units) rc->units = strdupz(st->units); - - { - time_t now = now_realtime_sec(); - health_alarm_log( - st->rrdhost, - rc->id, - rc->next_event_id++, - now, - rc->name, - rc->rrdset->id, - rc->rrdset->family, - rc->exec, - rc->recipient, - now - rc->last_status_change, - rc->old_value, - rc->value, - rc->status, - RRDCALC_STATUS_UNINITIALIZED, - rc->source, - rc->units, - rc->info, - 0, - 0 - ); - } -} - -static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) { - if( (rc->hash_chart == st->hash && !strcmp(rc->chart, st->id)) || - (rc->hash_chart == st->hash_name && !strcmp(rc->chart, st->name))) - return 1; - - return 0; -} - -// this has to be called while the RRDHOST is locked -inline void rrdsetcalc_link_matching(RRDSET *st) { - // debug(D_HEALTH, "find matching alarms for chart '%s'", st->id); - - RRDCALC *rc; - for(rc = st->rrdhost->alarms; rc ; rc = rc->next) { - if(unlikely(rc->rrdset)) - continue; - - if(unlikely(rrdcalc_is_matching_this_rrdset(rc, st))) - rrdsetcalc_link(st, rc); - } -} - -// this has to be called while the RRDHOST is locked -inline void rrdsetcalc_unlink(RRDCALC *rc) { - RRDSET *st = rc->rrdset; - - if(!st) { - debug(D_HEALTH, "Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rc->chart?rc->chart:"NOCHART", rc->name); - error("Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rc->chart?rc->chart:"NOCHART", rc->name); - return; - } - - { - time_t now = now_realtime_sec(); - health_alarm_log( - st->rrdhost, - rc->id, - rc->next_event_id++, - now, - rc->name, - rc->rrdset->id, - rc->rrdset->family, - rc->exec, - rc->recipient, - now - rc->last_status_change, - rc->old_value, - rc->value, - rc->status, - RRDCALC_STATUS_REMOVED, - rc->source, - rc->units, - rc->info, - 0, - 0 - ); - } - - RRDHOST *host = st->rrdhost; - - debug(D_HEALTH, "Health unlinking alarm '%s.%s' from chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, host->hostname); - - // unlink it - if(rc->rrdset_prev) - rc->rrdset_prev->rrdset_next = rc->rrdset_next; - - if(rc->rrdset_next) - rc->rrdset_next->rrdset_prev = rc->rrdset_prev; - - if(st->alarms == rc) - st->alarms = rc->rrdset_next; - - rc->rrdset_prev = rc->rrdset_next = NULL; - - rrdvar_free(st->rrdhost, &st->variables_root_index, rc->local); - rc->local = NULL; - - rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rc->family); - rc->family = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostid); - rc->hostid = NULL; - - rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostname); - rc->hostname = NULL; - - rc->rrdset = NULL; - - // RRDCALC will remain in RRDHOST - // so that if the matching chart is found in the future - // it will be applied automatically -} - -RRDCALC *rrdcalc_find(RRDSET *st, const char *name) { - RRDCALC *rc; - uint32_t hash = simple_hash(name); - - for( rc = st->alarms; rc ; rc = rc->rrdset_next ) { - if(unlikely(rc->hash == hash && !strcmp(rc->name, name))) - return rc; - } - - return NULL; -} - -static inline int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name) { - RRDCALC *rc; - - if(unlikely(!chart)) { - error("attempt to find RRDCALC '%s' without giving a chart name", name); - return 1; - } - - if(unlikely(!hash_chart)) hash_chart = simple_hash(chart); - if(unlikely(!hash_name)) hash_name = simple_hash(name); - - // make sure it does not already exist - for(rc = host->alarms; rc ; rc = rc->next) { - if (unlikely(rc->chart && rc->hash == hash_name && rc->hash_chart == hash_chart && !strcmp(name, rc->name) && !strcmp(chart, rc->chart))) { - debug(D_HEALTH, "Health alarm '%s.%s' already exists in host '%s'.", chart, name, host->hostname); - error("Health alarm '%s.%s' already exists in host '%s'.", chart, name, host->hostname); - return 1; - } - } - - return 0; -} - -static inline uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id) { - if(chart && name) { - uint32_t hash_chart = simple_hash(chart); - uint32_t hash_name = simple_hash(name); - - // re-use old IDs, by looking them up in the alarm log - ALARM_ENTRY *ae; - for(ae = host->health_log.alarms; ae ;ae = ae->next) { - if(unlikely(ae->hash_name == hash_name && ae->hash_chart == hash_chart && !strcmp(name, ae->name) && !strcmp(chart, ae->chart))) { - if(next_event_id) *next_event_id = ae->alarm_event_id + 1; - return ae->alarm_id; - } - } - } - - return host->health_log.next_alarm_id++; -} - -static inline void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc) { - rrdhost_check_rdlock(host); - - if(rc->calculation) { - rc->calculation->status = &rc->status; - rc->calculation->this = &rc->value; - rc->calculation->after = &rc->db_after; - rc->calculation->before = &rc->db_before; - rc->calculation->rrdcalc = rc; - } - - if(rc->warning) { - rc->warning->status = &rc->status; - rc->warning->this = &rc->value; - rc->warning->after = &rc->db_after; - rc->warning->before = &rc->db_before; - rc->warning->rrdcalc = rc; - } - - if(rc->critical) { - rc->critical->status = &rc->status; - rc->critical->this = &rc->value; - rc->critical->after = &rc->db_after; - rc->critical->before = &rc->db_before; - rc->critical->rrdcalc = rc; - } - - // link it to the host - if(likely(host->alarms)) { - // append it - RRDCALC *t; - for(t = host->alarms; t && t->next ; t = t->next) ; - t->next = rc; - } - else { - host->alarms = rc; - } - - // link it to its chart - RRDSET *st; - for(st = host->rrdset_root; st ; st = st->next) { - if(rrdcalc_is_matching_this_rrdset(rc, st)) { - rrdsetcalc_link(st, rc); - break; - } - } -} - -static inline RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart) { - - debug(D_HEALTH, "Health creating dynamic alarm (from template) '%s.%s'", chart, rt->name); - - if(rrdcalc_exists(host, chart, rt->name, 0, 0)) - return NULL; - - RRDCALC *rc = callocz(1, sizeof(RRDCALC)); - rc->next_event_id = 1; - rc->id = rrdcalc_get_unique_id(host, chart, rt->name, &rc->next_event_id); - rc->name = strdupz(rt->name); - rc->hash = simple_hash(rc->name); - rc->chart = strdupz(chart); - rc->hash_chart = simple_hash(rc->chart); - - if(rt->dimensions) rc->dimensions = strdupz(rt->dimensions); - - rc->green = rt->green; - rc->red = rt->red; - rc->value = NAN; - rc->old_value = NAN; - - rc->delay_up_duration = rt->delay_up_duration; - rc->delay_down_duration = rt->delay_down_duration; - rc->delay_max_duration = rt->delay_max_duration; - rc->delay_multiplier = rt->delay_multiplier; - - rc->group = rt->group; - rc->after = rt->after; - rc->before = rt->before; - rc->update_every = rt->update_every; - rc->options = rt->options; - - if(rt->exec) rc->exec = strdupz(rt->exec); - if(rt->recipient) rc->recipient = strdupz(rt->recipient); - if(rt->source) rc->source = strdupz(rt->source); - if(rt->units) rc->units = strdupz(rt->units); - if(rt->info) rc->info = strdupz(rt->info); - - if(rt->calculation) { - rc->calculation = expression_parse(rt->calculation->source, NULL, NULL); - if(!rc->calculation) - error("Health alarm '%s.%s': failed to parse calculation expression '%s'", chart, rt->name, rt->calculation->source); - } - if(rt->warning) { - rc->warning = expression_parse(rt->warning->source, NULL, NULL); - if(!rc->warning) - error("Health alarm '%s.%s': failed to re-parse warning expression '%s'", chart, rt->name, rt->warning->source); - } - if(rt->critical) { - rc->critical = expression_parse(rt->critical->source, NULL, NULL); - if(!rc->critical) - error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", chart, rt->name, rt->critical->source); - } - - debug(D_HEALTH, "Health runtime added alarm '%s.%s': exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", - (rc->chart)?rc->chart:"NOCHART", - rc->name, - (rc->exec)?rc->exec:"DEFAULT", - (rc->recipient)?rc->recipient:"DEFAULT", - rc->green, - rc->red, - rc->group, - rc->after, - rc->before, - rc->options, - (rc->dimensions)?rc->dimensions:"NONE", - rc->update_every, - (rc->calculation)?rc->calculation->parsed_as:"NONE", - (rc->warning)?rc->warning->parsed_as:"NONE", - (rc->critical)?rc->critical->parsed_as:"NONE", - rc->source, - rc->delay_up_duration, - rc->delay_down_duration, - rc->delay_max_duration, - rc->delay_multiplier - ); - - rrdcalc_create_part2(host, rc); - return rc; -} - -void rrdcalc_free(RRDHOST *host, RRDCALC *rc) { - if(!rc) return; - - debug(D_HEALTH, "Health removing alarm '%s.%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); - - // unlink it from RRDSET - if(rc->rrdset) rrdsetcalc_unlink(rc); - - // unlink it from RRDHOST - if(unlikely(rc == host->alarms)) - host->alarms = rc->next; - - else if(likely(host->alarms)) { - RRDCALC *t, *last = host->alarms; - for(t = last->next; t && t != rc; last = t, t = t->next) ; - if(last->next == rc) - last->next = rc->next; - else - error("Cannot unlink alarm '%s.%s' from host '%s': not found", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); - } - else - error("Cannot unlink unlink '%s.%s' from host '%s': This host does not have any calculations", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); - - expression_free(rc->calculation); - expression_free(rc->warning); - expression_free(rc->critical); - - freez(rc->name); - freez(rc->chart); - freez(rc->family); - freez(rc->dimensions); - freez(rc->exec); - freez(rc->recipient); - freez(rc->source); - freez(rc->units); - freez(rc->info); - freez(rc); -} - -// ---------------------------------------------------------------------------- -// RRDCALCTEMPLATE management - -void rrdcalctemplate_link_matching(RRDSET *st) { - RRDCALCTEMPLATE *rt; - - for(rt = st->rrdhost->templates; rt ; rt = rt->next) { - if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) - && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) { - RRDCALC *rc = rrdcalc_create(st->rrdhost, rt, st->id); - if(unlikely(!rc)) - error("Health tried to create alarm from template '%s', but it failed", rt->name); - -#ifdef NETDATA_INTERNAL_CHECKS - else if(rc->rrdset != st) - error("Health alarm '%s.%s' should be linked to chart '%s', but it is not", rc->chart?rc->chart:"NOCHART", rc->name, st->id); -#endif - } - } -} - -static inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) { - debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname); - - if(host->templates) { - if(host->templates == rt) { - host->templates = rt->next; - } - else { - RRDCALCTEMPLATE *t, *last = host->templates; - for (t = last->next; t && t != rt; last = t, t = t->next ) ; - if(last && last->next == rt) { - last->next = rt->next; - rt->next = NULL; - } - else - error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname); - } - } - - expression_free(rt->calculation); - expression_free(rt->warning); - expression_free(rt->critical); - - freez(rt->family_match); - simple_pattern_free(rt->family_pattern); - - freez(rt->name); - freez(rt->exec); - freez(rt->recipient); - freez(rt->context); - freez(rt->source); - freez(rt->units); - freez(rt->info); - freez(rt->dimensions); - freez(rt); -} - -// ---------------------------------------------------------------------------- -// load health configuration - -#define HEALTH_CONF_MAX_LINE 4096 - -#define HEALTH_ALARM_KEY "alarm" -#define HEALTH_TEMPLATE_KEY "template" -#define HEALTH_ON_KEY "on" -#define HEALTH_FAMILIES_KEY "families" -#define HEALTH_LOOKUP_KEY "lookup" -#define HEALTH_CALC_KEY "calc" -#define HEALTH_EVERY_KEY "every" -#define HEALTH_GREEN_KEY "green" -#define HEALTH_RED_KEY "red" -#define HEALTH_WARN_KEY "warn" -#define HEALTH_CRIT_KEY "crit" -#define HEALTH_EXEC_KEY "exec" -#define HEALTH_RECIPIENT_KEY "to" -#define HEALTH_UNITS_KEY "units" -#define HEALTH_INFO_KEY "info" -#define HEALTH_DELAY_KEY "delay" -#define HEALTH_OPTIONS_KEY "options" - -static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { - if(!rc->chart) { - error("Health configuration for alarm '%s' does not have a chart", rc->name); - return 0; - } - - if(!rc->update_every) { - error("Health configuration for alarm '%s.%s' has no frequency (parameter 'every'). Ignoring it.", rc->chart?rc->chart:"NOCHART", rc->name); - return 0; - } - - if(!RRDCALC_HAS_DB_LOOKUP(rc) && !rc->warning && !rc->critical) { - error("Health configuration for alarm '%s.%s' is useless (no calculation, no warning and no critical evaluation)", rc->chart?rc->chart:"NOCHART", rc->name); - return 0; - } - - if (rrdcalc_exists(host, rc->chart, rc->name, rc->hash_chart, rc->hash)) - return 0; - - rc->id = rrdcalc_get_unique_id(&localhost, rc->chart, rc->name, &rc->next_event_id); - - debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", - rc->chart?rc->chart:"NOCHART", - rc->name, - rc->id, - (rc->exec)?rc->exec:"DEFAULT", - (rc->recipient)?rc->recipient:"DEFAULT", - rc->green, - rc->red, - rc->group, - rc->after, - rc->before, - rc->options, - (rc->dimensions)?rc->dimensions:"NONE", - rc->update_every, - (rc->calculation)?rc->calculation->parsed_as:"NONE", - (rc->warning)?rc->warning->parsed_as:"NONE", - (rc->critical)?rc->critical->parsed_as:"NONE", - rc->source, - rc->delay_up_duration, - rc->delay_down_duration, - rc->delay_max_duration, - rc->delay_multiplier - ); - - rrdcalc_create_part2(host, rc); - return 1; -} - -static inline int rrdcalctemplate_add_template_from_config(RRDHOST *host, RRDCALCTEMPLATE *rt) { - if(unlikely(!rt->context)) { - error("Health configuration for template '%s' does not have a context", rt->name); - return 0; - } - - if(unlikely(!rt->update_every)) { - error("Health configuration for template '%s' has no frequency (parameter 'every'). Ignoring it.", rt->name); - return 0; - } - - if(unlikely(!RRDCALCTEMPLATE_HAS_CALCULATION(rt) && !rt->warning && !rt->critical)) { - error("Health configuration for template '%s' is useless (no calculation, no warning and no critical evaluation)", rt->name); - return 0; - } - - RRDCALCTEMPLATE *t, *last = NULL; - for (t = host->templates; t ; last = t, t = t->next) { - if(unlikely(t->hash_name == rt->hash_name && !strcmp(t->name, rt->name))) { - error("Health configuration template '%s' already exists for host '%s'.", rt->name, host->hostname); - return 0; - } - } - - debug(D_HEALTH, "Health configuration adding template '%s': context '%s', exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", - rt->name, - (rt->context)?rt->context:"NONE", - (rt->exec)?rt->exec:"DEFAULT", - (rt->recipient)?rt->recipient:"DEFAULT", - rt->green, - rt->red, - rt->group, - rt->after, - rt->before, - rt->options, - (rt->dimensions)?rt->dimensions:"NONE", - rt->update_every, - (rt->calculation)?rt->calculation->parsed_as:"NONE", - (rt->warning)?rt->warning->parsed_as:"NONE", - (rt->critical)?rt->critical->parsed_as:"NONE", - rt->source, - rt->delay_up_duration, - rt->delay_down_duration, - rt->delay_max_duration, - rt->delay_multiplier - ); - - if(likely(last)) { - last->next = rt; - } - else { - rt->next = host->templates; - host->templates = rt; - } - - return 1; -} - -static inline int health_parse_duration(char *string, int *result) { - // make sure it is a number - if(!*string || !(isdigit(*string) || *string == '+' || *string == '-')) { - *result = 0; - return 0; - } - - char *e = NULL; - calculated_number n = strtold(string, &e); - if(e && *e) { - switch (*e) { - case 'Y': - *result = (int) (n * 86400 * 365); - break; - case 'M': - *result = (int) (n * 86400 * 30); - break; - case 'w': - *result = (int) (n * 86400 * 7); - break; - case 'd': - *result = (int) (n * 86400); - break; - case 'h': - *result = (int) (n * 3600); - break; - case 'm': - *result = (int) (n * 60); - break; - - default: - case 's': - *result = (int) (n); - break; - } - } - else - *result = (int)(n); - - return 1; -} - -static inline int health_parse_delay( - size_t line, const char *path, const char *file, char *string, - int *delay_up_duration, - int *delay_down_duration, - int *delay_max_duration, - float *delay_multiplier) { - - char given_up = 0; - char given_down = 0; - char given_max = 0; - char given_multiplier = 0; - - char *s = string; - while(*s) { - char *key = s; - - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - - if(!*key) break; - - char *value = s; - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - - if(!strcasecmp(key, "up")) { - if (!health_parse_duration(value, delay_up_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); - } - else given_up = 1; - } - else if(!strcasecmp(key, "down")) { - if (!health_parse_duration(value, delay_down_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); - } - else given_down = 1; - } - else if(!strcasecmp(key, "multiplier")) { - *delay_multiplier = strtof(value, NULL); - if(isnan(*delay_multiplier) || isinf(*delay_multiplier) || islessequal(*delay_multiplier, 0)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); - } - else given_multiplier = 1; - } - else if(!strcasecmp(key, "max")) { - if (!health_parse_duration(value, delay_max_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); - } - else given_max = 1; - } - else { - error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", - line, path, file, key); - } - } - - if(!given_up) - *delay_up_duration = 0; - - if(!given_down) - *delay_down_duration = 0; - - if(!given_multiplier) - *delay_multiplier = 1.0; - - if(!given_max) { - if((*delay_max_duration) < (*delay_up_duration) * (*delay_multiplier)) - *delay_max_duration = (*delay_up_duration) * (*delay_multiplier); - - if((*delay_max_duration) < (*delay_down_duration) * (*delay_multiplier)) - *delay_max_duration = (*delay_down_duration) * (*delay_multiplier); - } - - return 1; -} - -static inline uint32_t health_parse_options(const char *s) { - uint32_t options = 0; - char buf[100+1] = ""; - - while(*s) { - buf[0] = '\0'; - - // skip spaces - while(*s && isspace(*s)) - s++; - - // find the next space - size_t count = 0; - while(*s && count < 100 && !isspace(*s)) - buf[count++] = *s++; - - if(buf[0]) { - buf[count] = '\0'; - - if(!strcasecmp(buf, "no-clear-notification") || !strcasecmp(buf, "no-clear")) - options |= RRDCALC_FLAG_NO_CLEAR_NOTIFICATION; - else - error("Ignoring unknown alarm option '%s'", buf); - } - } - - return options; -} - -static inline int health_parse_db_lookup( - size_t line, const char *path, const char *file, char *string, - int *group_method, int *after, int *before, int *every, - uint32_t *options, char **dimensions -) { - debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s/%s: %s", line, path, file, string); - - if(*dimensions) freez(*dimensions); - *dimensions = NULL; - *after = 0; - *before = 0; - *every = 0; - *options = 0; - - char *s = string, *key; - - // first is the group method - key = s; - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - if(!*s) { - error("Health configuration invalid chart calculation at line %zu of file '%s/%s': expected group method followed by the 'after' time, but got '%s'", - line, path, file, key); - return 0; - } - - if((*group_method = web_client_api_request_v1_data_group(key, -1)) == -1) { - error("Health configuration at line %zu of file '%s/%s': invalid group method '%s'", - line, path, file, key); - return 0; - } - - // then is the 'after' time - key = s; - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - - if(!health_parse_duration(key, after)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' after group method", - line, path, file, key); - return 0; - } - - // sane defaults - *every = abs(*after); - - // now we may have optional parameters - while(*s) { - key = s; - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - if(!*key) break; - - if(!strcasecmp(key, "at")) { - char *value = s; - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - - if (!health_parse_duration(value, before)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", - line, path, file, value, key); - } - } - else if(!strcasecmp(key, HEALTH_EVERY_KEY)) { - char *value = s; - while(*s && !isspace(*s)) s++; - while(*s && isspace(*s)) *s++ = '\0'; - - if (!health_parse_duration(value, every)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", - line, path, file, value, key); - } - } - else if(!strcasecmp(key, "absolute") || !strcasecmp(key, "abs") || !strcasecmp(key, "absolute_sum")) { - *options |= RRDR_OPTION_ABSOLUTE; - } - else if(!strcasecmp(key, "min2max")) { - *options |= RRDR_OPTION_MIN2MAX; - } - else if(!strcasecmp(key, "null2zero")) { - *options |= RRDR_OPTION_NULL2ZERO; - } - else if(!strcasecmp(key, "percentage")) { - *options |= RRDR_OPTION_PERCENTAGE; - } - else if(!strcasecmp(key, "unaligned")) { - *options |= RRDR_OPTION_NOT_ALIGNED; - } - else if(!strcasecmp(key, "of")) { - if(*s && strcasecmp(s, "all")) - *dimensions = strdupz(s); - break; - } - else { - error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", - line, path, file, key); - } - } - - return 1; -} - -static inline char *trim_all_spaces(char *buffer) { - char *d = buffer, *s = buffer; - - // skip spaces - while(isspace(*s)) s++; - - while(*s) { - // copy the non-space part - while(*s && !isspace(*s)) *d++ = *s++; - - // add a space if we have to - if(*s && isspace(*s)) { - *d++ = ' '; - s++; - } - - // skip spaces - while(isspace(*s)) s++; - } - - *d = '\0'; - - if(d > buffer) { - d--; - if(isspace(*d)) *d = '\0'; - } - - if(!buffer[0]) return NULL; - return buffer; -} - -static inline char *health_source_file(size_t line, const char *path, const char *filename) { - char buffer[FILENAME_MAX + 1]; - snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename); - return strdupz(buffer); -} - -static inline void strip_quotes(char *s) { - while(*s) { - if(*s == '\'' || *s == '"') *s = ' '; - s++; - } -} - -int health_readfile(const char *path, const char *filename) { - debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename); - - static uint32_t - hash_alarm = 0, - hash_template = 0, - hash_on = 0, - hash_families = 0, - hash_calc = 0, - hash_green = 0, - hash_red = 0, - hash_warn = 0, - hash_crit = 0, - hash_exec = 0, - hash_every = 0, - hash_lookup = 0, - hash_units = 0, - hash_info = 0, - hash_recipient = 0, - hash_delay = 0, - hash_options = 0; - - char buffer[HEALTH_CONF_MAX_LINE + 1]; - - if(unlikely(!hash_alarm)) { - hash_alarm = simple_uhash(HEALTH_ALARM_KEY); - hash_template = simple_uhash(HEALTH_TEMPLATE_KEY); - hash_on = simple_uhash(HEALTH_ON_KEY); - hash_families = simple_uhash(HEALTH_FAMILIES_KEY); - hash_calc = simple_uhash(HEALTH_CALC_KEY); - hash_lookup = simple_uhash(HEALTH_LOOKUP_KEY); - hash_green = simple_uhash(HEALTH_GREEN_KEY); - hash_red = simple_uhash(HEALTH_RED_KEY); - hash_warn = simple_uhash(HEALTH_WARN_KEY); - hash_crit = simple_uhash(HEALTH_CRIT_KEY); - hash_exec = simple_uhash(HEALTH_EXEC_KEY); - hash_every = simple_uhash(HEALTH_EVERY_KEY); - hash_units = simple_hash(HEALTH_UNITS_KEY); - hash_info = simple_hash(HEALTH_INFO_KEY); - hash_recipient = simple_hash(HEALTH_RECIPIENT_KEY); - hash_delay = simple_uhash(HEALTH_DELAY_KEY); - hash_options = simple_uhash(HEALTH_OPTIONS_KEY); - } - - snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename); - FILE *fp = fopen(buffer, "r"); - if(!fp) { - error("Health configuration cannot read file '%s'.", buffer); - return 0; - } - - RRDCALC *rc = NULL; - RRDCALCTEMPLATE *rt = NULL; - - size_t line = 0, append = 0; - char *s; - while((s = fgets(&buffer[append], (int)(HEALTH_CONF_MAX_LINE - append), fp)) || append) { - int stop_appending = !s; - line++; - s = trim(buffer); - if(!s) continue; - - append = strlen(s); - if(!stop_appending && s[append - 1] == '\\') { - s[append - 1] = ' '; - append = &s[append] - buffer; - if(append < HEALTH_CONF_MAX_LINE) - continue; - else { - error("Health configuration has too long muli-line at line %zu of file '%s/%s'.", line, path, filename); - } - } - append = 0; - - char *key = s; - while(*s && *s != ':') s++; - if(!*s) { - error("Health configuration has invalid line %zu of file '%s/%s'. It does not contain a ':'. Ignoring it.", line, path, filename); - continue; - } - *s = '\0'; - s++; - - char *value = s; - key = trim_all_spaces(key); - value = trim_all_spaces(value); - - if(!key) { - error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename); - continue; - } - - if(!value) { - error("Health configuration has invalid line %zu of file '%s/%s'. value is empty. Ignoring it.", line, path, filename); - continue; - } - - uint32_t hash = simple_uhash(key); - - if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { - if(rc && !rrdcalc_add_alarm_from_config(&localhost, rc)) - rrdcalc_free(&localhost, rc); - - if(rt) { - if (!rrdcalctemplate_add_template_from_config(&localhost, rt)) - rrdcalctemplate_free(&localhost, rt); - rt = NULL; - } - - rc = callocz(1, sizeof(RRDCALC)); - rc->next_event_id = 1; - rc->name = strdupz(value); - rc->hash = simple_hash(rc->name); - rc->source = health_source_file(line, path, filename); - rc->green = NAN; - rc->red = NAN; - rc->value = NAN; - rc->old_value = NAN; - rc->delay_multiplier = 1.0; - - if(rrdvar_fix_name(rc->name)) - error("Health configuration renamed alarm '%s' to '%s'", value, rc->name); - } - else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) { - if(rc) { - if(!rrdcalc_add_alarm_from_config(&localhost, rc)) - rrdcalc_free(&localhost, rc); - rc = NULL; - } - - if(rt && !rrdcalctemplate_add_template_from_config(&localhost, rt)) - rrdcalctemplate_free(&localhost, rt); - - rt = callocz(1, sizeof(RRDCALCTEMPLATE)); - rt->name = strdupz(value); - rt->hash_name = simple_hash(rt->name); - rt->source = health_source_file(line, path, filename); - rt->green = NAN; - rt->red = NAN; - rt->delay_multiplier = 1.0; - - if(rrdvar_fix_name(rt->name)) - error("Health configuration renamed template '%s' to '%s'", value, rt->name); - } - else if(rc) { - if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { - if(rc->chart) { - if(strcmp(rc->chart, value)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->chart, value, value); - - freez(rc->chart); - } - rc->chart = strdupz(value); - rc->hash_chart = simple_hash(rc->chart); - } - else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { - health_parse_db_lookup(line, path, filename, value, &rc->group, &rc->after, &rc->before, - &rc->update_every, - &rc->options, &rc->dimensions); - } - else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { - if(!health_parse_duration(value, &rc->update_every)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", - line, path, filename, rc->name, key, value); - } - else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { - char *e; - rc->green = strtold(value, &e); - if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rc->name, key, e); - } - } - else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { - char *e; - rc->red = strtold(value, &e); - if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rc->name, key, e); - } - } - else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { - const char *failed_at = NULL; - int error = 0; - rc->calculation = expression_parse(value, &failed_at, &error); - if(!rc->calculation) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); - } - } - else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { - const char *failed_at = NULL; - int error = 0; - rc->warning = expression_parse(value, &failed_at, &error); - if(!rc->warning) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); - } - } - else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { - const char *failed_at = NULL; - int error = 0; - rc->critical = expression_parse(value, &failed_at, &error); - if(!rc->critical) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); - } - } - else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { - if(rc->exec) { - if(strcmp(rc->exec, value)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->exec, value, value); - - freez(rc->exec); - } - rc->exec = strdupz(value); - } - else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { - if(rc->recipient) { - if(strcmp(rc->recipient, value)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->recipient, value, value); - - freez(rc->recipient); - } - rc->recipient = strdupz(value); - } - else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { - if(rc->units) { - if(strcmp(rc->units, value)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->units, value, value); - - freez(rc->units); - } - rc->units = strdupz(value); - strip_quotes(rc->units); - } - else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { - if(rc->info) { - if(strcmp(rc->info, value)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rc->name, key, rc->info, value, value); - - freez(rc->info); - } - rc->info = strdupz(value); - strip_quotes(rc->info); - } - else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { - health_parse_delay(line, path, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier); - } - else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { - rc->options |= health_parse_options(value); - } - else { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.", - line, path, filename, rc->name, key); - } - } - else if(rt) { - if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { - if(rt->context) { - if(strcmp(rt->context, value)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->context, value, value); - - freez(rt->context); - } - rt->context = strdupz(value); - rt->hash_context = simple_hash(rt->context); - } - else if(hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) { - freez(rt->family_match); - simple_pattern_free(rt->family_pattern); - - rt->family_match = strdupz(value); - rt->family_pattern = simple_pattern_create(rt->family_match, SIMPLE_PATTERN_EXACT); - } - else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { - health_parse_db_lookup(line, path, filename, value, &rt->group, &rt->after, &rt->before, - &rt->update_every, &rt->options, &rt->dimensions); - } - else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { - if(!health_parse_duration(value, &rt->update_every)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' cannot parse duration: '%s'.", - line, path, filename, rt->name, key, value); - } - else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { - char *e; - rt->green = strtold(value, &e); - if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rt->name, key, e); - } - } - else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { - char *e; - rt->red = strtold(value, &e); - if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rt->name, key, e); - } - } - else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { - const char *failed_at = NULL; - int error = 0; - rt->calculation = expression_parse(value, &failed_at, &error); - if(!rt->calculation) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); - } - } - else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { - const char *failed_at = NULL; - int error = 0; - rt->warning = expression_parse(value, &failed_at, &error); - if(!rt->warning) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); - } - } - else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { - const char *failed_at = NULL; - int error = 0; - rt->critical = expression_parse(value, &failed_at, &error); - if(!rt->critical) { - error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); - } - } - else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { - if(rt->exec) { - if(strcmp(rt->exec, value)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->exec, value, value); - - freez(rt->exec); - } - rt->exec = strdupz(value); - } - else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { - if(rt->recipient) { - if(strcmp(rt->recipient, value)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->recipient, value, value); - - freez(rt->recipient); - } - rt->recipient = strdupz(value); - } - else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { - if(rt->units) { - if(strcmp(rt->units, value)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->units, value, value); - - freez(rt->units); - } - rt->units = strdupz(value); - strip_quotes(rt->units); - } - else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { - if(rt->info) { - if(strcmp(rt->info, value)) - error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", - line, path, filename, rt->name, key, rt->info, value, value); - - freez(rt->info); - } - rt->info = strdupz(value); - strip_quotes(rt->info); - } - else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { - health_parse_delay(line, path, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier); - } - else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { - rt->options |= health_parse_options(value); - } - else { - error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.", - line, path, filename, rt->name, key); - } - } - else { - error("Health configuration at line %zu of file '%s/%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.", - line, path, filename, key); - } - } - - if(rc && !rrdcalc_add_alarm_from_config(&localhost, rc)) - rrdcalc_free(&localhost, rc); - - if(rt && !rrdcalctemplate_add_template_from_config(&localhost, rt)) - rrdcalctemplate_free(&localhost, rt); - - fclose(fp); - return 1; -} - -void health_readdir(const char *path) { - size_t pathlen = strlen(path); - - debug(D_HEALTH, "Health configuration reading directory '%s'", path); - - DIR *dir = opendir(path); - if (!dir) { - error("Health configuration cannot open directory '%s'.", path); - return; - } - - struct dirent *de = NULL; - while ((de = readdir(dir))) { - size_t len = strlen(de->d_name); - - if(de->d_type == DT_DIR - && ( - (de->d_name[0] == '.' && de->d_name[1] == '\0') - || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') - )) { - debug(D_HEALTH, "Ignoring directory '%s'", de->d_name); - continue; - } - - else if(de->d_type == DT_DIR) { - char *s = mallocz(pathlen + strlen(de->d_name) + 2); - strcpy(s, path); - strcat(s, "/"); - strcat(s, de->d_name); - health_readdir(s); - freez(s); - continue; - } - - else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) && - len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { - health_readfile(path, de->d_name); - } - - else debug(D_HEALTH, "Ignoring file '%s'", de->d_name); - } - - closedir(dir); -} +// ---------------------------------------------------------------------------- +// health initialization -static inline char *health_config_dir(void) { +inline char *health_config_dir(void) { char buffer[FILENAME_MAX + 1]; snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_config_dir); - return config_get("health", "health configuration directory", buffer); + return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer); } void health_init(void) { debug(D_HEALTH, "Health configuration initializing"); - if(!(health_enabled = config_get_boolean("health", "enabled", 1))) { + if(!(default_health_enabled = config_get_boolean(CONFIG_SECTION_HEALTH, "enabled", 1))) { debug(D_HEALTH, "Health is disabled."); return; } - - char pathname[FILENAME_MAX + 1]; - snprintfz(pathname, FILENAME_MAX, "%s/health", netdata_configured_varlib_dir); - if(mkdir(pathname, 0770) == -1 && errno != EEXIST) - fatal("Cannot create directory '%s'.", pathname); - - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/health-log.db", pathname); - health.log_filename = config_get("health", "health db file", filename); - - health_alarm_log_load(&localhost); - health_alarm_log_open(); - - char *path = health_config_dir(); - - snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir); - health.health_default_exec = config_get("health", "script to execute on alarm", filename); - - long n = config_get_number("health", "in memory max health log entries", (long)localhost.health_log.max); - if(n < 10) { - error("Health configuration has invalid max log entries %ld. Using default %u", n, localhost.health_log.max); - config_set_number("health", "in memory max health log entries", (long)localhost.health_log.max); - } - else localhost.health_log.max = (unsigned int)n; - - rrdhost_rwlock(&localhost); - health_readdir(path); - rrdhost_unlock(&localhost); } // ---------------------------------------------------------------------------- -// JSON generation - -static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) { - if(value && *value) - buffer_sprintf(wb, "%s\"%s\":\"%s\"%s", prefix, label, value, suffix); - else - buffer_sprintf(wb, "%s\"%s\":null%s", prefix, label, suffix); -} - -static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host) { - buffer_sprintf(wb, - "\n\t{\n" - "\t\t\"hostname\": \"%s\",\n" - "\t\t\"unique_id\": %u,\n" - "\t\t\"alarm_id\": %u,\n" - "\t\t\"alarm_event_id\": %u,\n" - "\t\t\"name\": \"%s\",\n" - "\t\t\"chart\": \"%s\",\n" - "\t\t\"family\": \"%s\",\n" - "\t\t\"processed\": %s,\n" - "\t\t\"updated\": %s,\n" - "\t\t\"exec_run\": %lu,\n" - "\t\t\"exec_failed\": %s,\n" - "\t\t\"exec\": \"%s\",\n" - "\t\t\"recipient\": \"%s\",\n" - "\t\t\"exec_code\": %d,\n" - "\t\t\"source\": \"%s\",\n" - "\t\t\"units\": \"%s\",\n" - "\t\t\"info\": \"%s\",\n" - "\t\t\"when\": %lu,\n" - "\t\t\"duration\": %lu,\n" - "\t\t\"non_clear_duration\": %lu,\n" - "\t\t\"status\": \"%s\",\n" - "\t\t\"old_status\": \"%s\",\n" - "\t\t\"delay\": %d,\n" - "\t\t\"delay_up_to_timestamp\": %lu,\n" - "\t\t\"updated_by_id\": %u,\n" - "\t\t\"updates_id\": %u,\n" - "\t\t\"value_string\": \"%s\",\n" - "\t\t\"old_value_string\": \"%s\",\n" - , host->hostname - , ae->unique_id - , ae->alarm_id - , ae->alarm_event_id - , ae->name - , ae->chart - , ae->family - , (ae->flags & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false" - , (ae->flags & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false" - , (unsigned long)ae->exec_run_timestamp - , (ae->flags & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false" - , ae->exec?ae->exec:health.health_default_exec - , ae->recipient?ae->recipient:health.health_default_recipient - , ae->exec_code - , ae->source - , ae->units?ae->units:"" - , ae->info?ae->info:"" - , (unsigned long)ae->when - , (unsigned long)ae->duration - , (unsigned long)ae->non_clear_duration - , rrdcalc_status2string(ae->new_status) - , rrdcalc_status2string(ae->old_status) - , ae->delay - , (unsigned long)ae->delay_up_to_timestamp - , ae->updated_by_id - , ae->updates_id - , ae->new_value_string - , ae->old_value_string - ); - - if(unlikely(ae->flags & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) { - buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n"); - } - - buffer_strcat(wb, "\t\t\"value\":"); - buffer_rrd_value(wb, ae->new_value); - buffer_strcat(wb, ",\n"); - - buffer_strcat(wb, "\t\t\"old_value\":"); - buffer_rrd_value(wb, ae->old_value); - buffer_strcat(wb, "\n"); - - buffer_strcat(wb, "\t}"); -} - -void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after) { - pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); - - buffer_strcat(wb, "["); - - unsigned int max = host->health_log.max; - unsigned int count = 0; - ALARM_ENTRY *ae; - for(ae = host->health_log.alarms; ae && count < max ; count++, ae = ae->next) { - if(ae->unique_id > after) { - if(likely(count)) buffer_strcat(wb, ","); - health_alarm_entry2json_nolock(wb, ae, host); - } - } - - buffer_strcat(wb, "\n]\n"); - - pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); -} - -static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) { - char value_string[100 + 1]; - format_value_and_unit(value_string, 100, rc->value, rc->units, -1); - - buffer_sprintf(wb, - "\t\t\"%s.%s\": {\n" - "\t\t\t\"id\": %lu,\n" - "\t\t\t\"name\": \"%s\",\n" - "\t\t\t\"chart\": \"%s\",\n" - "\t\t\t\"family\": \"%s\",\n" - "\t\t\t\"active\": %s,\n" - "\t\t\t\"exec\": \"%s\",\n" - "\t\t\t\"recipient\": \"%s\",\n" - "\t\t\t\"source\": \"%s\",\n" - "\t\t\t\"units\": \"%s\",\n" - "\t\t\t\"info\": \"%s\",\n" - "\t\t\t\"status\": \"%s\",\n" - "\t\t\t\"last_status_change\": %lu,\n" - "\t\t\t\"last_updated\": %lu,\n" - "\t\t\t\"next_update\": %lu,\n" - "\t\t\t\"update_every\": %d,\n" - "\t\t\t\"delay_up_duration\": %d,\n" - "\t\t\t\"delay_down_duration\": %d,\n" - "\t\t\t\"delay_max_duration\": %d,\n" - "\t\t\t\"delay_multiplier\": %f,\n" - "\t\t\t\"delay\": %d,\n" - "\t\t\t\"delay_up_to_timestamp\": %lu,\n" - "\t\t\t\"value_string\": \"%s\",\n" - , rc->chart, rc->name - , (unsigned long)rc->id - , rc->name - , rc->chart - , (rc->rrdset && rc->rrdset->family)?rc->rrdset->family:"" - , (rc->rrdset)?"true":"false" - , rc->exec?rc->exec:health.health_default_exec - , rc->recipient?rc->recipient:health.health_default_recipient - , rc->source - , rc->units?rc->units:"" - , rc->info?rc->info:"" - , rrdcalc_status2string(rc->status) - , (unsigned long)rc->last_status_change - , (unsigned long)rc->last_updated - , (unsigned long)rc->next_update - , rc->update_every - , rc->delay_up_duration - , rc->delay_down_duration - , rc->delay_max_duration - , rc->delay_multiplier - , rc->delay_last - , (unsigned long)rc->delay_up_to_timestamp - , value_string - ); - - if(unlikely(rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION)) { - buffer_strcat(wb, "\t\t\t\"no_clear_notification\": true,\n"); - } - - if(RRDCALC_HAS_DB_LOOKUP(rc)) { - if(rc->dimensions && *rc->dimensions) - health_string2json(wb, "\t\t\t", "lookup_dimensions", rc->dimensions, ",\n"); - - buffer_sprintf(wb, - "\t\t\t\"db_after\": %lu,\n" - "\t\t\t\"db_before\": %lu,\n" - "\t\t\t\"lookup_method\": \"%s\",\n" - "\t\t\t\"lookup_after\": %d,\n" - "\t\t\t\"lookup_before\": %d,\n" - "\t\t\t\"lookup_options\": \"", - (unsigned long) rc->db_after, - (unsigned long) rc->db_before, - group_method2string(rc->group), - rc->after, - rc->before - ); - buffer_data_options2string(wb, rc->options); - buffer_strcat(wb, "\",\n"); - } - - if(rc->calculation) { - health_string2json(wb, "\t\t\t", "calc", rc->calculation->source, ",\n"); - health_string2json(wb, "\t\t\t", "calc_parsed", rc->calculation->parsed_as, ",\n"); - } - - if(rc->warning) { - health_string2json(wb, "\t\t\t", "warn", rc->warning->source, ",\n"); - health_string2json(wb, "\t\t\t", "warn_parsed", rc->warning->parsed_as, ",\n"); - } - - if(rc->critical) { - health_string2json(wb, "\t\t\t", "crit", rc->critical->source, ",\n"); - health_string2json(wb, "\t\t\t", "crit_parsed", rc->critical->parsed_as, ",\n"); - } - - buffer_strcat(wb, "\t\t\t\"green\":"); - buffer_rrd_value(wb, rc->green); - buffer_strcat(wb, ",\n"); - - buffer_strcat(wb, "\t\t\t\"red\":"); - buffer_rrd_value(wb, rc->red); - buffer_strcat(wb, ",\n"); - - buffer_strcat(wb, "\t\t\t\"value\":"); - buffer_rrd_value(wb, rc->value); - buffer_strcat(wb, "\n"); - - buffer_strcat(wb, "\t\t}"); -} - -//void health_rrdcalctemplate2json_nolock(BUFFER *wb, RRDCALCTEMPLATE *rt) { -// -//} - -void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) { - int i; - - rrdhost_rdlock(&localhost); - buffer_sprintf(wb, "{\n\t\"hostname\": \"%s\"," - "\n\t\"latest_alarm_log_unique_id\": %u," - "\n\t\"status\": %s," - "\n\t\"now\": %lu," - "\n\t\"alarms\": {\n", - host->hostname, - (host->health_log.next_log_id > 0)?(host->health_log.next_log_id - 1):0, - health_enabled?"true":"false", - (unsigned long)now_realtime_sec()); - - RRDCALC *rc; - for(i = 0, rc = host->alarms; rc ; rc = rc->next) { - if(unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec)) - continue; - - if(likely(!all && !(rc->status == RRDCALC_STATUS_WARNING || rc->status == RRDCALC_STATUS_CRITICAL))) - continue; - - if(likely(i)) buffer_strcat(wb, ",\n"); - health_rrdcalc2json_nolock(wb, rc); - i++; - } - -// buffer_strcat(wb, "\n\t},\n\t\"templates\": {"); -// RRDCALCTEMPLATE *rt; -// for(rt = host->templates; rt ; rt = rt->next) -// health_rrdcalctemplate2json_nolock(wb, rt); +// re-load health configuration - buffer_strcat(wb, "\n\t}\n}\n"); - rrdhost_unlock(&localhost); -} +void health_reload_host(RRDHOST *host) { + if(unlikely(!host->health_enabled)) + return; + char *path = health_config_dir(); -// ---------------------------------------------------------------------------- -// re-load health configuration + // free all running alarms + rrdhost_wrlock(host); -static inline void health_free_all_nolock(RRDHOST *host) { while(host->templates) rrdcalctemplate_free(host, host->templates); while(host->alarms) rrdcalc_free(host, host->alarms); -} -void health_reload(void) { - if(!health_enabled) { - error("Health reload is requested, but health is not enabled."); - return; - } - - char *path = health_config_dir(); - - // free all running alarms - rrdhost_rwlock(&localhost); - health_free_all_nolock(&localhost); - rrdhost_unlock(&localhost); + rrdhost_unlock(host); // invalidate all previous entries in the alarm log ALARM_ENTRY *t; - for(t = localhost.health_log.alarms ; t ; t = t->next) { + for(t = host->health_log.alarms ; t ; t = t->next) { if(t->new_status != RRDCALC_STATUS_REMOVED) t->flags |= HEALTH_ENTRY_FLAG_UPDATED; } + rrdhost_rdlock(host); // reset all thresholds to all charts RRDSET *st; - for(st = localhost.rrdset_root; st ; st = st->next) { + rrdset_foreach_read(st, host) { st->green = NAN; st->red = NAN; } + rrdhost_unlock(host); // load the new alarms - rrdhost_rwlock(&localhost); - health_readdir(path); - rrdhost_unlock(&localhost); + rrdhost_wrlock(host); + health_readdir(host, path); // link the loaded alarms to their charts - for(st = localhost.rrdset_root; st ; st = st->next) { - rrdhost_rwlock(&localhost); - + rrdset_foreach_write(st, host) { rrdsetcalc_link_matching(st); rrdcalctemplate_link_matching(st); - - rrdhost_unlock(&localhost); } + + rrdhost_unlock(host); +} + +void health_reload(void) { + + rrd_rdlock(); + + RRDHOST *host; + rrdhost_foreach_read(host) + health_reload_host(host); + + rrd_unlock(); } // ---------------------------------------------------------------------------- @@ -2800,11 +142,8 @@ static inline void health_alarm_execute(RRDHOST *host, ALARM_ENTRY *ae) { static char command_to_run[ALARM_EXEC_COMMAND_LENGTH + 1]; pid_t command_pid; - const char *exec = ae->exec; - if(!exec) exec = health.health_default_exec; - - const char *recipient = ae->recipient; - if(!recipient) recipient = health.health_default_recipient; + const char *exec = (ae->exec) ? ae->exec : host->health_default_exec; + const char *recipient = (ae->recipient) ? ae->recipient : host->health_default_recipient; snprintfz(command_to_run, ALARM_EXEC_COMMAND_LENGTH, "exec %s '%s' '%s' '%u' '%u' '%u' '%lu' '%s' '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u' '%s' '%s' '%s' '%s'", exec, @@ -2911,17 +250,7 @@ static inline void health_alarm_log_process(RRDHOST *host) { ALARM_ENTRY *t = ae->next; - freez(ae->name); - freez(ae->chart); - freez(ae->family); - freez(ae->exec); - freez(ae->recipient); - freez(ae->source); - freez(ae->units); - freez(ae->info); - freez(ae->old_value_string); - freez(ae->new_value_string); - freez(ae); + health_alarm_log_free_one_nochecks_nounlink(ae); ae = t; host->health_log.count--; @@ -2995,319 +324,396 @@ void *health_main(void *ptr) { if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); - int min_run_every = (int)config_get_number("health", "run at least every seconds", 10); + int min_run_every = (int)config_get_number(CONFIG_SECTION_HEALTH, "run at least every seconds", 10); if(min_run_every < 1) min_run_every = 1; BUFFER *wb = buffer_create(100); + time_t now = now_realtime_sec(); + time_t now_boottime = now_boottime_sec(); + time_t last_now = now; + time_t last_now_boottime = now_boottime; + time_t hibernation_delay = config_get_number(CONFIG_SECTION_HEALTH, "postpone alarms during hibernation for seconds", 60); + unsigned int loop = 0; - while(health_enabled && !netdata_exit) { + while(!netdata_exit) { loop++; debug(D_HEALTH, "Health monitoring iteration no %u started", loop); - int oldstate, runnable = 0; - time_t now = now_realtime_sec(); + int oldstate, runnable = 0, apply_hibernation_delay = 0; time_t next_run = now + min_run_every; RRDCALC *rc; + // detect if boottime and realtime have twice the difference + // in which case we assume the system was just waken from hibernation + if(unlikely(now - last_now > 2 * (now_boottime - last_now_boottime))) + apply_hibernation_delay = 1; + + last_now = now; + last_now_boottime = now_boottime; + if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)) error("Cannot set pthread cancel state to DISABLE."); - rrdhost_rdlock(&localhost); + rrd_rdlock(); - // the first loop is to lookup values from the db - for(rc = localhost.alarms; rc; rc = rc->next) { - if(unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) { - if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE)) - rc->rrdcalc_flags &= ~RRDCALC_FLAG_RUNNABLE; + RRDHOST *host; + rrdhost_foreach_read(host) { + if(unlikely(!host->health_enabled)) continue; - } - runnable++; - rc->old_value = rc->value; - rc->rrdcalc_flags |= RRDCALC_FLAG_RUNNABLE; + if(unlikely(apply_hibernation_delay)) { - // 1. if there is database lookup, do it - // 2. if there is calculation expression, run it + info("Postponing alarm checks for %ld seconds, on host '%s', due to boottime discrepancy (realtime dt: %ld, boottime dt: %ld)." + , hibernation_delay + , host->hostname + , (long)(now - last_now) + , (long)(now_boottime - last_now_boottime) + ); - if (unlikely(RRDCALC_HAS_DB_LOOKUP(rc))) { - /* time_t old_db_timestamp = rc->db_before; */ - int value_is_null = 0; - - int ret = rrd2value(rc->rrdset, wb, &rc->value, - rc->dimensions, 1, rc->after, rc->before, rc->group, - rc->options, &rc->db_after, &rc->db_before, &value_is_null); + host->health_delay_up_to = now + hibernation_delay; + } - if (unlikely(ret != 200)) { - // database lookup failed - rc->value = NAN; + if(unlikely(!host->health_enabled || now < host->health_delay_up_to)) + continue; - debug(D_HEALTH, "Health alarm '%s.%s': database lookup returned error %d", rc->chart?rc->chart:"NOCHART", rc->name, ret); + rrdhost_rdlock(host); - if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_DB_ERROR))) { - rc->rrdcalc_flags |= RRDCALC_FLAG_DB_ERROR; - error("Health alarm '%s.%s': database lookup returned error %d", rc->chart?rc->chart:"NOCHART", rc->name, ret); - } + // the first loop is to lookup values from the db + for(rc = host->alarms; rc; rc = rc->next) { + if(unlikely(!rrdcalc_isrunnable(rc, now, &next_run))) { + if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE)) + rc->rrdcalc_flags &= ~RRDCALC_FLAG_RUNNABLE; + continue; } - else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_ERROR)) - rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_ERROR; - /* - RRDCALC_FLAG_DB_STALE not currently used - if (unlikely(old_db_timestamp == rc->db_before)) { - // database is stale + runnable++; + rc->old_value = rc->value; + rc->rrdcalc_flags |= RRDCALC_FLAG_RUNNABLE; + + // ------------------------------------------------------------ + // if there is database lookup, do it + + if(unlikely(RRDCALC_HAS_DB_LOOKUP(rc))) { + /* time_t old_db_timestamp = rc->db_before; */ + int value_is_null = 0; + + int ret = rrd2value(rc->rrdset + , wb + , &rc->value + , rc->dimensions + , 1 + , rc->after + , rc->before + , rc->group + , rc->options + , &rc->db_after + , &rc->db_before + , &value_is_null + ); - debug(D_HEALTH, "Health alarm '%s.%s': database is stale", rc->chart?rc->chart:"NOCHART", rc->name); + if(unlikely(ret != 200)) { + // database lookup failed + rc->value = NAN; + rc->rrdcalc_flags |= RRDCALC_FLAG_DB_ERROR; - if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE))) { - rc->rrdcalc_flags |= RRDCALC_FLAG_DB_STALE; - error("Health alarm '%s.%s': database is stale", rc->chart?rc->chart:"NOCHART", rc->name); + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': database lookup returned error %d" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , ret + ); } - } - else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE)) - rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_STALE; - */ + else + rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_ERROR; - if (unlikely(value_is_null)) { - // collected value is null + /* - RRDCALC_FLAG_DB_STALE not currently used + if (unlikely(old_db_timestamp == rc->db_before)) { + // database is stale - rc->value = NAN; + debug(D_HEALTH, "Health on host '%s', alarm '%s.%s': database is stale", host->hostname, rc->chart?rc->chart:"NOCHART", rc->name); - debug(D_HEALTH, "Health alarm '%s.%s': database lookup returned empty value (possibly value is not collected yet)", - rc->chart?rc->chart:"NOCHART", rc->name); + if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE))) { + rc->rrdcalc_flags |= RRDCALC_FLAG_DB_STALE; + error("Health on host '%s', alarm '%s.%s': database is stale", host->hostname, rc->chart?rc->chart:"NOCHART", rc->name); + } + } + else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_STALE)) + rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_STALE; + */ - if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_DB_NAN))) { + if(unlikely(value_is_null)) { + // collected value is null + rc->value = NAN; rc->rrdcalc_flags |= RRDCALC_FLAG_DB_NAN; - error("Health alarm '%s.%s': database lookup returned empty value (possibly value is not collected yet)", - rc->chart?rc->chart:"NOCHART", rc->name); + + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': database lookup returned empty value (possibly value is not collected yet)" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + ); } + else + rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_NAN; + + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': database lookup gave value " CALCULATED_NUMBER_FORMAT + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , rc->value + ); } - else if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_DB_NAN)) - rc->rrdcalc_flags &= ~RRDCALC_FLAG_DB_NAN; - - debug(D_HEALTH, "Health alarm '%s.%s': database lookup gave value " - CALCULATED_NUMBER_FORMAT, rc->chart?rc->chart:"NOCHART", rc->name, rc->value); - } - - if(unlikely(rc->calculation)) { - if (unlikely(!expression_evaluate(rc->calculation))) { - // calculation failed - rc->value = NAN; + // ------------------------------------------------------------ + // if there is calculation expression, run it - debug(D_HEALTH, "Health alarm '%s.%s': expression '%s' failed: %s", - rc->chart?rc->chart:"NOCHART", rc->name, rc->calculation->parsed_as, buffer_tostring(rc->calculation->error_msg)); - - if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_CALC_ERROR))) { + if(unlikely(rc->calculation)) { + if(unlikely(!expression_evaluate(rc->calculation))) { + // calculation failed + rc->value = NAN; rc->rrdcalc_flags |= RRDCALC_FLAG_CALC_ERROR; - error("Health alarm '%s.%s': expression '%s' failed: %s", - rc->chart?rc->chart:"NOCHART", rc->name, rc->calculation->parsed_as, buffer_tostring(rc->calculation->error_msg)); + + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': expression '%s' failed: %s" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , rc->calculation->parsed_as + , buffer_tostring(rc->calculation->error_msg) + ); } - } - else { - if (unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_CALC_ERROR)) + else { rc->rrdcalc_flags &= ~RRDCALC_FLAG_CALC_ERROR; - debug(D_HEALTH, "Health alarm '%s.%s': expression '%s' gave value " - CALCULATED_NUMBER_FORMAT - ": %s (source: %s)", - rc->chart?rc->chart:"NOCHART", rc->name, - rc->calculation->parsed_as, - rc->calculation->result, - buffer_tostring(rc->calculation->error_msg), - rc->source - ); + debug(D_HEALTH, "Health on host '%s', alarm '%s.%s': expression '%s' gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , rc->calculation->parsed_as + , rc->calculation->result + , buffer_tostring(rc->calculation->error_msg) + , rc->source + ); - rc->value = rc->calculation->result; + rc->value = rc->calculation->result; + } } } - } - rrdhost_unlock(&localhost); + rrdhost_unlock(host); - if(unlikely(runnable && !netdata_exit)) { - rrdhost_rdlock(&localhost); + if(unlikely(runnable && !netdata_exit)) { + rrdhost_rdlock(host); - for(rc = localhost.alarms; rc; rc = rc->next) { - if(unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE))) - continue; - - int warning_status = RRDCALC_STATUS_UNDEFINED; - int critical_status = RRDCALC_STATUS_UNDEFINED; + for(rc = host->alarms; rc; rc = rc->next) { + if(unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_RUNNABLE))) + continue; - if(likely(rc->warning)) { - if(unlikely(!expression_evaluate(rc->warning))) { - // calculation failed + int warning_status = RRDCALC_STATUS_UNDEFINED; + int critical_status = RRDCALC_STATUS_UNDEFINED; - debug(D_HEALTH, "Health alarm '%s.%s': warning expression failed with error: %s", - rc->chart?rc->chart:"NOCHART", rc->name, buffer_tostring(rc->warning->error_msg)); + // -------------------------------------------------------- + // check the warning expression - if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_WARN_ERROR))) { + if(likely(rc->warning)) { + if(unlikely(!expression_evaluate(rc->warning))) { + // calculation failed rc->rrdcalc_flags |= RRDCALC_FLAG_WARN_ERROR; - error("Health alarm '%s.%s': warning expression failed with error: %s", - rc->chart?rc->chart:"NOCHART", rc->name, buffer_tostring(rc->warning->error_msg)); + + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': warning expression failed with error: %s" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , buffer_tostring(rc->warning->error_msg) + ); } - } - else { - if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_WARN_ERROR)) + else { rc->rrdcalc_flags &= ~RRDCALC_FLAG_WARN_ERROR; - - debug(D_HEALTH, "Health alarm '%s.%s': warning expression gave value " - CALCULATED_NUMBER_FORMAT - ": %s (source: %s)", - rc->chart?rc->chart:"NOCHART", rc->name, - rc->warning->result, - buffer_tostring(rc->warning->error_msg), - rc->source - ); - - warning_status = rrdcalc_value2status(rc->warning->result); + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': warning expression gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , rc->warning->result + , buffer_tostring(rc->warning->error_msg) + , rc->source + ); + warning_status = rrdcalc_value2status(rc->warning->result); + } } - } - - if(likely(rc->critical)) { - if(unlikely(!expression_evaluate(rc->critical))) { - // calculation failed - debug(D_HEALTH, "Health alarm '%s.%s': critical expression failed with error: %s", - rc->chart?rc->chart:"NOCHART", rc->name, buffer_tostring(rc->critical->error_msg)); + // -------------------------------------------------------- + // check the critical expression - if (unlikely(!(rc->rrdcalc_flags & RRDCALC_FLAG_CRIT_ERROR))) { + if(likely(rc->critical)) { + if(unlikely(!expression_evaluate(rc->critical))) { + // calculation failed rc->rrdcalc_flags |= RRDCALC_FLAG_CRIT_ERROR; - error("Health alarm '%s.%s': critical expression failed with error: %s", - rc->chart?rc->chart:"NOCHART", rc->name, buffer_tostring(rc->critical->error_msg)); + + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': critical expression failed with error: %s" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , buffer_tostring(rc->critical->error_msg) + ); } - } - else { - if(unlikely(rc->rrdcalc_flags & RRDCALC_FLAG_CRIT_ERROR)) + else { rc->rrdcalc_flags &= ~RRDCALC_FLAG_CRIT_ERROR; + debug(D_HEALTH + , "Health on host '%s', alarm '%s.%s': critical expression gave value " CALCULATED_NUMBER_FORMAT ": %s (source: %s)" + , host->hostname + , rc->chart ? rc->chart : "NOCHART" + , rc->name + , rc->critical->result + , buffer_tostring(rc->critical->error_msg) + , rc->source + ); + critical_status = rrdcalc_value2status(rc->critical->result); + } + } - debug(D_HEALTH, "Health alarm '%s.%s': critical expression gave value " - CALCULATED_NUMBER_FORMAT - ": %s (source: %s)", - rc->chart?rc->chart:"NOCHART", rc->name, - rc->critical->result, - buffer_tostring(rc->critical->error_msg), - rc->source - ); + // -------------------------------------------------------- + // decide the final alarm status + + int status = RRDCALC_STATUS_UNDEFINED; - critical_status = rrdcalc_value2status(rc->critical->result); + switch(warning_status) { + case RRDCALC_STATUS_CLEAR: + status = RRDCALC_STATUS_CLEAR; + break; + + case RRDCALC_STATUS_RAISED: + status = RRDCALC_STATUS_WARNING; + break; + + default: + break; } - } - int status = RRDCALC_STATUS_UNDEFINED; + switch(critical_status) { + case RRDCALC_STATUS_CLEAR: + if(status == RRDCALC_STATUS_UNDEFINED) + status = RRDCALC_STATUS_CLEAR; + break; - switch(warning_status) { - case RRDCALC_STATUS_CLEAR: - status = RRDCALC_STATUS_CLEAR; - break; + case RRDCALC_STATUS_RAISED: + status = RRDCALC_STATUS_CRITICAL; + break; - case RRDCALC_STATUS_RAISED: - status = RRDCALC_STATUS_WARNING; - break; + default: + break; + } - default: - break; - } + // -------------------------------------------------------- + // check if the new status and the old differ - switch(critical_status) { - case RRDCALC_STATUS_CLEAR: - if(status == RRDCALC_STATUS_UNDEFINED) - status = RRDCALC_STATUS_CLEAR; - break; + if(status != rc->status) { + int delay = 0; - case RRDCALC_STATUS_RAISED: - status = RRDCALC_STATUS_CRITICAL; - break; + // apply trigger hysteresis - default: - break; - } + if(now > rc->delay_up_to_timestamp) { + rc->delay_up_current = rc->delay_up_duration; + rc->delay_down_current = rc->delay_down_duration; + rc->delay_last = 0; + rc->delay_up_to_timestamp = 0; + } + else { + rc->delay_up_current = (int) (rc->delay_up_current * rc->delay_multiplier); + if(rc->delay_up_current > rc->delay_max_duration) + rc->delay_up_current = rc->delay_max_duration; + + rc->delay_down_current = (int) (rc->delay_down_current * rc->delay_multiplier); + if(rc->delay_down_current > rc->delay_max_duration) + rc->delay_down_current = rc->delay_max_duration; + } - if(status != rc->status) { - int delay = 0; + if(status > rc->status) + delay = rc->delay_up_current; + else + delay = rc->delay_down_current; + + // COMMENTED: because we do need to send raising alarms + // if(now + delay < rc->delay_up_to_timestamp) + // delay = (int)(rc->delay_up_to_timestamp - now); + + rc->delay_last = delay; + rc->delay_up_to_timestamp = now + delay; + + // add the alarm into the log + + health_alarm_log( + host + , rc->id + , rc->next_event_id++ + , now + , rc->name + , rc->rrdset->id + , rc->rrdset->family + , rc->exec + , rc->recipient + , now - rc->last_status_change + , rc->old_value + , rc->value + , rc->status + , status + , rc->source + , rc->units + , rc->info + , rc->delay_last + , (rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION) ? HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION : 0 + ); - if(now > rc->delay_up_to_timestamp) { - rc->delay_up_current = rc->delay_up_duration; - rc->delay_down_current = rc->delay_down_duration; - rc->delay_last = 0; - rc->delay_up_to_timestamp = 0; + rc->last_status_change = now; + rc->status = status; } - else { - rc->delay_up_current = (int)(rc->delay_up_current * rc->delay_multiplier); - if(rc->delay_up_current > rc->delay_max_duration) rc->delay_up_current = rc->delay_max_duration; - rc->delay_down_current = (int)(rc->delay_down_current * rc->delay_multiplier); - if(rc->delay_down_current > rc->delay_max_duration) rc->delay_down_current = rc->delay_max_duration; - } + rc->last_updated = now; + rc->next_update = now + rc->update_every; - if(status > rc->status) - delay = rc->delay_up_current; - else - delay = rc->delay_down_current; - - // COMMENTED: because we do need to send raising alarms - // if(now + delay < rc->delay_up_to_timestamp) - // delay = (int)(rc->delay_up_to_timestamp - now); - - rc->delay_last = delay; - rc->delay_up_to_timestamp = now + delay; - health_alarm_log( - &localhost, - rc->id, - rc->next_event_id++, - now, - rc->name, - rc->rrdset->id, - rc->rrdset->family, - rc->exec, - rc->recipient, - now - rc->last_status_change, - rc->old_value, - rc->value, - rc->status, - status, - rc->source, - rc->units, - rc->info, - rc->delay_last, - (rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION)?HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION:0 - ); - rc->last_status_change = now; - rc->status = status; + if(next_run > rc->next_update) + next_run = rc->next_update; } - rc->last_updated = now; - rc->next_update = now + rc->update_every; - - if (next_run > rc->next_update) - next_run = rc->next_update; + rrdhost_unlock(host); } - rrdhost_unlock(&localhost); - } + if(unlikely(netdata_exit)) + break; - if (unlikely(pthread_setcancelstate(oldstate, NULL) != 0)) - error("Cannot set pthread cancel state to RESTORE (%d).", oldstate); + // execute notifications + // and cleanup + health_alarm_log_process(host); - if(unlikely(netdata_exit)) - break; + if(unlikely(netdata_exit)) + break; + + } /* rrdhost_foreach */ + + rrd_unlock(); - // execute notifications - // and cleanup - health_alarm_log_process(&localhost); + if(unlikely(pthread_setcancelstate(oldstate, NULL) != 0)) + error("Cannot set pthread cancel state to RESTORE (%d).", oldstate); if(unlikely(netdata_exit)) break; - + now = now_realtime_sec(); if(now < next_run) { - debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration in %d secs", - loop, (int) (next_run - now)); + debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration in %d secs", loop, (int) (next_run - now)); sleep_usec(USEC_PER_SEC * (usec_t) (next_run - now)); + now = now_realtime_sec(); } - else { + else debug(D_HEALTH, "Health monitoring iteration no %u done. Next iteration now", loop); - } - } + + now_boottime = now_boottime_sec(); + + } // forever buffer_free(wb); diff --git a/src/health.h b/src/health.h index 87f8a1a1..f8e29032 100644 --- a/src/health.h +++ b/src/health.h @@ -1,7 +1,7 @@ #ifndef NETDATA_HEALTH_H #define NETDATA_HEALTH_H -extern int health_enabled; +extern int default_health_enabled; extern int rrdvar_compare(void *a, void *b); @@ -369,4 +369,58 @@ extern void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value) extern const char *rrdcalc_status2string(int status); + +extern int health_alarm_log_open(RRDHOST *host); +extern void health_alarm_log_close(RRDHOST *host); +extern void health_log_rotate(RRDHOST *host); +extern void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae); +extern ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename); +extern void health_alarm_log_load(RRDHOST *host); +extern void health_alarm_log( + RRDHOST *host, + uint32_t alarm_id, + uint32_t alarm_event_id, + time_t when, + const char *name, + const char *chart, + const char *family, + const char *exec, + const char *recipient, + time_t duration, + calculated_number old_value, + calculated_number new_value, + int old_status, + int new_status, + const char *source, + const char *units, + const char *info, + int delay, + uint32_t flags +); + +extern void health_readdir(RRDHOST *host, const char *path); +extern char *health_config_dir(void); +extern void health_reload_host(RRDHOST *host); +extern void health_alarm_log_free(RRDHOST *host); + +extern void rrdcalc_free(RRDHOST *host, RRDCALC *rc); +extern void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt); + +#ifdef NETDATA_HEALTH_INTERNALS +#define RRDVAR_MAX_LENGTH 1024 + +extern int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name); +extern uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id); +extern int rrdvar_fix_name(char *variable); + +extern RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart); +extern void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc); + +extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, void *value); +extern void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv); + +extern void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae); + +#endif // NETDATA_HEALTH_INTERNALS + #endif //NETDATA_HEALTH_H diff --git a/src/health_config.c b/src/health_config.c new file mode 100644 index 00000000..ad954cbe --- /dev/null +++ b/src/health_config.c @@ -0,0 +1,877 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +#define HEALTH_CONF_MAX_LINE 4096 + +#define HEALTH_ALARM_KEY "alarm" +#define HEALTH_TEMPLATE_KEY "template" +#define HEALTH_ON_KEY "on" +#define HEALTH_FAMILIES_KEY "families" +#define HEALTH_LOOKUP_KEY "lookup" +#define HEALTH_CALC_KEY "calc" +#define HEALTH_EVERY_KEY "every" +#define HEALTH_GREEN_KEY "green" +#define HEALTH_RED_KEY "red" +#define HEALTH_WARN_KEY "warn" +#define HEALTH_CRIT_KEY "crit" +#define HEALTH_EXEC_KEY "exec" +#define HEALTH_RECIPIENT_KEY "to" +#define HEALTH_UNITS_KEY "units" +#define HEALTH_INFO_KEY "info" +#define HEALTH_DELAY_KEY "delay" +#define HEALTH_OPTIONS_KEY "options" + +static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) { + if(!rc->chart) { + error("Health configuration for alarm '%s' does not have a chart", rc->name); + return 0; + } + + if(!rc->update_every) { + error("Health configuration for alarm '%s.%s' has no frequency (parameter 'every'). Ignoring it.", rc->chart?rc->chart:"NOCHART", rc->name); + return 0; + } + + if(!RRDCALC_HAS_DB_LOOKUP(rc) && !rc->warning && !rc->critical) { + error("Health configuration for alarm '%s.%s' is useless (no calculation, no warning and no critical evaluation)", rc->chart?rc->chart:"NOCHART", rc->name); + return 0; + } + + if (rrdcalc_exists(host, rc->chart, rc->name, rc->hash_chart, rc->hash)) + return 0; + + rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id); + + debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", + rc->chart?rc->chart:"NOCHART", + rc->name, + rc->id, + (rc->exec)?rc->exec:"DEFAULT", + (rc->recipient)?rc->recipient:"DEFAULT", + rc->green, + rc->red, + rc->group, + rc->after, + rc->before, + rc->options, + (rc->dimensions)?rc->dimensions:"NONE", + rc->update_every, + (rc->calculation)?rc->calculation->parsed_as:"NONE", + (rc->warning)?rc->warning->parsed_as:"NONE", + (rc->critical)?rc->critical->parsed_as:"NONE", + rc->source, + rc->delay_up_duration, + rc->delay_down_duration, + rc->delay_max_duration, + rc->delay_multiplier + ); + + rrdcalc_create_part2(host, rc); + return 1; +} + +static inline int rrdcalctemplate_add_template_from_config(RRDHOST *host, RRDCALCTEMPLATE *rt) { + if(unlikely(!rt->context)) { + error("Health configuration for template '%s' does not have a context", rt->name); + return 0; + } + + if(unlikely(!rt->update_every)) { + error("Health configuration for template '%s' has no frequency (parameter 'every'). Ignoring it.", rt->name); + return 0; + } + + if(unlikely(!RRDCALCTEMPLATE_HAS_CALCULATION(rt) && !rt->warning && !rt->critical)) { + error("Health configuration for template '%s' is useless (no calculation, no warning and no critical evaluation)", rt->name); + return 0; + } + + RRDCALCTEMPLATE *t, *last = NULL; + for (t = host->templates; t ; last = t, t = t->next) { + if(unlikely(t->hash_name == rt->hash_name && !strcmp(t->name, rt->name))) { + error("Health configuration template '%s' already exists for host '%s'.", rt->name, host->hostname); + return 0; + } + } + + debug(D_HEALTH, "Health configuration adding template '%s': context '%s', exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", + rt->name, + (rt->context)?rt->context:"NONE", + (rt->exec)?rt->exec:"DEFAULT", + (rt->recipient)?rt->recipient:"DEFAULT", + rt->green, + rt->red, + rt->group, + rt->after, + rt->before, + rt->options, + (rt->dimensions)?rt->dimensions:"NONE", + rt->update_every, + (rt->calculation)?rt->calculation->parsed_as:"NONE", + (rt->warning)?rt->warning->parsed_as:"NONE", + (rt->critical)?rt->critical->parsed_as:"NONE", + rt->source, + rt->delay_up_duration, + rt->delay_down_duration, + rt->delay_max_duration, + rt->delay_multiplier + ); + + if(likely(last)) { + last->next = rt; + } + else { + rt->next = host->templates; + host->templates = rt; + } + + return 1; +} + +static inline int health_parse_duration(char *string, int *result) { + // make sure it is a number + if(!*string || !(isdigit(*string) || *string == '+' || *string == '-')) { + *result = 0; + return 0; + } + + char *e = NULL; + calculated_number n = strtold(string, &e); + if(e && *e) { + switch (*e) { + case 'Y': + *result = (int) (n * 86400 * 365); + break; + case 'M': + *result = (int) (n * 86400 * 30); + break; + case 'w': + *result = (int) (n * 86400 * 7); + break; + case 'd': + *result = (int) (n * 86400); + break; + case 'h': + *result = (int) (n * 3600); + break; + case 'm': + *result = (int) (n * 60); + break; + + default: + case 's': + *result = (int) (n); + break; + } + } + else + *result = (int)(n); + + return 1; +} + +static inline int health_parse_delay( + size_t line, const char *path, const char *file, char *string, + int *delay_up_duration, + int *delay_down_duration, + int *delay_max_duration, + float *delay_multiplier) { + + char given_up = 0; + char given_down = 0; + char given_max = 0; + char given_multiplier = 0; + + char *s = string; + while(*s) { + char *key = s; + + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + + if(!*key) break; + + char *value = s; + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + + if(!strcasecmp(key, "up")) { + if (!health_parse_duration(value, delay_up_duration)) { + error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", + line, path, file, value, key); + } + else given_up = 1; + } + else if(!strcasecmp(key, "down")) { + if (!health_parse_duration(value, delay_down_duration)) { + error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", + line, path, file, value, key); + } + else given_down = 1; + } + else if(!strcasecmp(key, "multiplier")) { + *delay_multiplier = strtof(value, NULL); + if(isnan(*delay_multiplier) || isinf(*delay_multiplier) || islessequal(*delay_multiplier, 0)) { + error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", + line, path, file, value, key); + } + else given_multiplier = 1; + } + else if(!strcasecmp(key, "max")) { + if (!health_parse_duration(value, delay_max_duration)) { + error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", + line, path, file, value, key); + } + else given_max = 1; + } + else { + error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", + line, path, file, key); + } + } + + if(!given_up) + *delay_up_duration = 0; + + if(!given_down) + *delay_down_duration = 0; + + if(!given_multiplier) + *delay_multiplier = 1.0; + + if(!given_max) { + if((*delay_max_duration) < (*delay_up_duration) * (*delay_multiplier)) + *delay_max_duration = (*delay_up_duration) * (*delay_multiplier); + + if((*delay_max_duration) < (*delay_down_duration) * (*delay_multiplier)) + *delay_max_duration = (*delay_down_duration) * (*delay_multiplier); + } + + return 1; +} + +static inline uint32_t health_parse_options(const char *s) { + uint32_t options = 0; + char buf[100+1] = ""; + + while(*s) { + buf[0] = '\0'; + + // skip spaces + while(*s && isspace(*s)) + s++; + + // find the next space + size_t count = 0; + while(*s && count < 100 && !isspace(*s)) + buf[count++] = *s++; + + if(buf[0]) { + buf[count] = '\0'; + + if(!strcasecmp(buf, "no-clear-notification") || !strcasecmp(buf, "no-clear")) + options |= RRDCALC_FLAG_NO_CLEAR_NOTIFICATION; + else + error("Ignoring unknown alarm option '%s'", buf); + } + } + + return options; +} + +static inline int health_parse_db_lookup( + size_t line, const char *path, const char *file, char *string, + int *group_method, int *after, int *before, int *every, + uint32_t *options, char **dimensions +) { + debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s/%s: %s", line, path, file, string); + + if(*dimensions) freez(*dimensions); + *dimensions = NULL; + *after = 0; + *before = 0; + *every = 0; + *options = 0; + + char *s = string, *key; + + // first is the group method + key = s; + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + if(!*s) { + error("Health configuration invalid chart calculation at line %zu of file '%s/%s': expected group method followed by the 'after' time, but got '%s'", + line, path, file, key); + return 0; + } + + if((*group_method = web_client_api_request_v1_data_group(key, -1)) == -1) { + error("Health configuration at line %zu of file '%s/%s': invalid group method '%s'", + line, path, file, key); + return 0; + } + + // then is the 'after' time + key = s; + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + + if(!health_parse_duration(key, after)) { + error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' after group method", + line, path, file, key); + return 0; + } + + // sane defaults + *every = abs(*after); + + // now we may have optional parameters + while(*s) { + key = s; + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + if(!*key) break; + + if(!strcasecmp(key, "at")) { + char *value = s; + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + + if (!health_parse_duration(value, before)) { + error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", + line, path, file, value, key); + } + } + else if(!strcasecmp(key, HEALTH_EVERY_KEY)) { + char *value = s; + while(*s && !isspace(*s)) s++; + while(*s && isspace(*s)) *s++ = '\0'; + + if (!health_parse_duration(value, every)) { + error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", + line, path, file, value, key); + } + } + else if(!strcasecmp(key, "absolute") || !strcasecmp(key, "abs") || !strcasecmp(key, "absolute_sum")) { + *options |= RRDR_OPTION_ABSOLUTE; + } + else if(!strcasecmp(key, "min2max")) { + *options |= RRDR_OPTION_MIN2MAX; + } + else if(!strcasecmp(key, "null2zero")) { + *options |= RRDR_OPTION_NULL2ZERO; + } + else if(!strcasecmp(key, "percentage")) { + *options |= RRDR_OPTION_PERCENTAGE; + } + else if(!strcasecmp(key, "unaligned")) { + *options |= RRDR_OPTION_NOT_ALIGNED; + } + else if(!strcasecmp(key, "of")) { + if(*s && strcasecmp(s, "all")) + *dimensions = strdupz(s); + break; + } + else { + error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", + line, path, file, key); + } + } + + return 1; +} + +static inline char *trim_all_spaces(char *buffer) { + char *d = buffer, *s = buffer; + + // skip spaces + while(isspace(*s)) s++; + + while(*s) { + // copy the non-space part + while(*s && !isspace(*s)) *d++ = *s++; + + // add a space if we have to + if(*s && isspace(*s)) { + *d++ = ' '; + s++; + } + + // skip spaces + while(isspace(*s)) s++; + } + + *d = '\0'; + + if(d > buffer) { + d--; + if(isspace(*d)) *d = '\0'; + } + + if(!buffer[0]) return NULL; + return buffer; +} + +static inline char *health_source_file(size_t line, const char *path, const char *filename) { + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename); + return strdupz(buffer); +} + +static inline void strip_quotes(char *s) { + while(*s) { + if(*s == '\'' || *s == '"') *s = ' '; + s++; + } +} + +int health_readfile(RRDHOST *host, const char *path, const char *filename) { + debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename); + + static uint32_t + hash_alarm = 0, + hash_template = 0, + hash_on = 0, + hash_families = 0, + hash_calc = 0, + hash_green = 0, + hash_red = 0, + hash_warn = 0, + hash_crit = 0, + hash_exec = 0, + hash_every = 0, + hash_lookup = 0, + hash_units = 0, + hash_info = 0, + hash_recipient = 0, + hash_delay = 0, + hash_options = 0; + + char buffer[HEALTH_CONF_MAX_LINE + 1]; + + if(unlikely(!hash_alarm)) { + hash_alarm = simple_uhash(HEALTH_ALARM_KEY); + hash_template = simple_uhash(HEALTH_TEMPLATE_KEY); + hash_on = simple_uhash(HEALTH_ON_KEY); + hash_families = simple_uhash(HEALTH_FAMILIES_KEY); + hash_calc = simple_uhash(HEALTH_CALC_KEY); + hash_lookup = simple_uhash(HEALTH_LOOKUP_KEY); + hash_green = simple_uhash(HEALTH_GREEN_KEY); + hash_red = simple_uhash(HEALTH_RED_KEY); + hash_warn = simple_uhash(HEALTH_WARN_KEY); + hash_crit = simple_uhash(HEALTH_CRIT_KEY); + hash_exec = simple_uhash(HEALTH_EXEC_KEY); + hash_every = simple_uhash(HEALTH_EVERY_KEY); + hash_units = simple_hash(HEALTH_UNITS_KEY); + hash_info = simple_hash(HEALTH_INFO_KEY); + hash_recipient = simple_hash(HEALTH_RECIPIENT_KEY); + hash_delay = simple_uhash(HEALTH_DELAY_KEY); + hash_options = simple_uhash(HEALTH_OPTIONS_KEY); + } + + snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename); + FILE *fp = fopen(buffer, "r"); + if(!fp) { + error("Health configuration cannot read file '%s'.", buffer); + return 0; + } + + RRDCALC *rc = NULL; + RRDCALCTEMPLATE *rt = NULL; + + size_t line = 0, append = 0; + char *s; + while((s = fgets(&buffer[append], (int)(HEALTH_CONF_MAX_LINE - append), fp)) || append) { + int stop_appending = !s; + line++; + s = trim(buffer); + if(!s) continue; + + append = strlen(s); + if(!stop_appending && s[append - 1] == '\\') { + s[append - 1] = ' '; + append = &s[append] - buffer; + if(append < HEALTH_CONF_MAX_LINE) + continue; + else { + error("Health configuration has too long muli-line at line %zu of file '%s/%s'.", line, path, filename); + } + } + append = 0; + + char *key = s; + while(*s && *s != ':') s++; + if(!*s) { + error("Health configuration has invalid line %zu of file '%s/%s'. It does not contain a ':'. Ignoring it.", line, path, filename); + continue; + } + *s = '\0'; + s++; + + char *value = s; + key = trim_all_spaces(key); + value = trim_all_spaces(value); + + if(!key) { + error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename); + continue; + } + + if(!value) { + error("Health configuration has invalid line %zu of file '%s/%s'. value is empty. Ignoring it.", line, path, filename); + continue; + } + + uint32_t hash = simple_uhash(key); + + if(hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { + if(rc && !rrdcalc_add_alarm_from_config(host, rc)) + rrdcalc_free(host, rc); + + if(rt) { + if (!rrdcalctemplate_add_template_from_config(host, rt)) + rrdcalctemplate_free(host, rt); + rt = NULL; + } + + rc = callocz(1, sizeof(RRDCALC)); + rc->next_event_id = 1; + rc->name = strdupz(value); + rc->hash = simple_hash(rc->name); + rc->source = health_source_file(line, path, filename); + rc->green = NAN; + rc->red = NAN; + rc->value = NAN; + rc->old_value = NAN; + rc->delay_multiplier = 1.0; + + if(rrdvar_fix_name(rc->name)) + error("Health configuration renamed alarm '%s' to '%s'", value, rc->name); + } + else if(hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) { + if(rc) { + if(!rrdcalc_add_alarm_from_config(host, rc)) + rrdcalc_free(host, rc); + rc = NULL; + } + + if(rt && !rrdcalctemplate_add_template_from_config(host, rt)) + rrdcalctemplate_free(host, rt); + + rt = callocz(1, sizeof(RRDCALCTEMPLATE)); + rt->name = strdupz(value); + rt->hash_name = simple_hash(rt->name); + rt->source = health_source_file(line, path, filename); + rt->green = NAN; + rt->red = NAN; + rt->delay_multiplier = 1.0; + + if(rrdvar_fix_name(rt->name)) + error("Health configuration renamed template '%s' to '%s'", value, rt->name); + } + else if(rc) { + if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { + if(rc->chart) { + if(strcmp(rc->chart, value)) + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rc->name, key, rc->chart, value, value); + + freez(rc->chart); + } + rc->chart = strdupz(value); + rc->hash_chart = simple_hash(rc->chart); + } + else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { + health_parse_db_lookup(line, path, filename, value, &rc->group, &rc->after, &rc->before, + &rc->update_every, + &rc->options, &rc->dimensions); + } + else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { + if(!health_parse_duration(value, &rc->update_every)) + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", + line, path, filename, rc->name, key, value); + } + else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { + char *e; + rc->green = strtold(value, &e); + if(e && *e) { + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", + line, path, filename, rc->name, key, e); + } + } + else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { + char *e; + rc->red = strtold(value, &e); + if(e && *e) { + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", + line, path, filename, rc->name, key, e); + } + } + else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { + const char *failed_at = NULL; + int error = 0; + rc->calculation = expression_parse(value, &failed_at, &error); + if(!rc->calculation) { + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + } + } + else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { + const char *failed_at = NULL; + int error = 0; + rc->warning = expression_parse(value, &failed_at, &error); + if(!rc->warning) { + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + } + } + else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { + const char *failed_at = NULL; + int error = 0; + rc->critical = expression_parse(value, &failed_at, &error); + if(!rc->critical) { + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + } + } + else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { + if(rc->exec) { + if(strcmp(rc->exec, value)) + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rc->name, key, rc->exec, value, value); + + freez(rc->exec); + } + rc->exec = strdupz(value); + } + else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { + if(rc->recipient) { + if(strcmp(rc->recipient, value)) + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rc->name, key, rc->recipient, value, value); + + freez(rc->recipient); + } + rc->recipient = strdupz(value); + } + else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { + if(rc->units) { + if(strcmp(rc->units, value)) + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rc->name, key, rc->units, value, value); + + freez(rc->units); + } + rc->units = strdupz(value); + strip_quotes(rc->units); + } + else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { + if(rc->info) { + if(strcmp(rc->info, value)) + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rc->name, key, rc->info, value, value); + + freez(rc->info); + } + rc->info = strdupz(value); + strip_quotes(rc->info); + } + else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { + health_parse_delay(line, path, filename, value, &rc->delay_up_duration, &rc->delay_down_duration, &rc->delay_max_duration, &rc->delay_multiplier); + } + else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { + rc->options |= health_parse_options(value); + } + else { + error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has unknown key '%s'.", + line, path, filename, rc->name, key); + } + } + else if(rt) { + if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { + if(rt->context) { + if(strcmp(rt->context, value)) + error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rt->name, key, rt->context, value, value); + + freez(rt->context); + } + rt->context = strdupz(value); + rt->hash_context = simple_hash(rt->context); + } + else if(hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) { + freez(rt->family_match); + simple_pattern_free(rt->family_pattern); + + rt->family_match = strdupz(value); + rt->family_pattern = simple_pattern_create(rt->family_match, SIMPLE_PATTERN_EXACT); + } + else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { + health_parse_db_lookup(line, path, filename, value, &rt->group, &rt->after, &rt->before, + &rt->update_every, &rt->options, &rt->dimensions); + } + else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { + if(!health_parse_duration(value, &rt->update_every)) + error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' cannot parse duration: '%s'.", + line, path, filename, rt->name, key, value); + } + else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { + char *e; + rt->green = strtold(value, &e); + if(e && *e) { + error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", + line, path, filename, rt->name, key, e); + } + } + else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { + char *e; + rt->red = strtold(value, &e); + if(e && *e) { + error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' leaves this string unmatched: '%s'.", + line, path, filename, rt->name, key, e); + } + } + else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { + const char *failed_at = NULL; + int error = 0; + rt->calculation = expression_parse(value, &failed_at, &error); + if(!rt->calculation) { + error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); + } + } + else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { + const char *failed_at = NULL; + int error = 0; + rt->warning = expression_parse(value, &failed_at, &error); + if(!rt->warning) { + error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); + } + } + else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { + const char *failed_at = NULL; + int error = 0; + rt->critical = expression_parse(value, &failed_at, &error); + if(!rt->critical) { + error("Health configuration at line %zu of file '%s/%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, path, filename, rt->name, key, value, expression_strerror(error), failed_at); + } + } + else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) { + if(rt->exec) { + if(strcmp(rt->exec, value)) + error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rt->name, key, rt->exec, value, value); + + freez(rt->exec); + } + rt->exec = strdupz(value); + } + else if(hash == hash_recipient && !strcasecmp(key, HEALTH_RECIPIENT_KEY)) { + if(rt->recipient) { + if(strcmp(rt->recipient, value)) + error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rt->name, key, rt->recipient, value, value); + + freez(rt->recipient); + } + rt->recipient = strdupz(value); + } + else if(hash == hash_units && !strcasecmp(key, HEALTH_UNITS_KEY)) { + if(rt->units) { + if(strcmp(rt->units, value)) + error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rt->name, key, rt->units, value, value); + + freez(rt->units); + } + rt->units = strdupz(value); + strip_quotes(rt->units); + } + else if(hash == hash_info && !strcasecmp(key, HEALTH_INFO_KEY)) { + if(rt->info) { + if(strcmp(rt->info, value)) + error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, path, filename, rt->name, key, rt->info, value, value); + + freez(rt->info); + } + rt->info = strdupz(value); + strip_quotes(rt->info); + } + else if(hash == hash_delay && !strcasecmp(key, HEALTH_DELAY_KEY)) { + health_parse_delay(line, path, filename, value, &rt->delay_up_duration, &rt->delay_down_duration, &rt->delay_max_duration, &rt->delay_multiplier); + } + else if(hash == hash_options && !strcasecmp(key, HEALTH_OPTIONS_KEY)) { + rt->options |= health_parse_options(value); + } + else { + error("Health configuration at line %zu of file '%s/%s' for template '%s' has unknown key '%s'.", + line, path, filename, rt->name, key); + } + } + else { + error("Health configuration at line %zu of file '%s/%s' has unknown key '%s'. Expected either '" HEALTH_ALARM_KEY "' or '" HEALTH_TEMPLATE_KEY "'.", + line, path, filename, key); + } + } + + if(rc && !rrdcalc_add_alarm_from_config(host, rc)) + rrdcalc_free(host, rc); + + if(rt && !rrdcalctemplate_add_template_from_config(host, rt)) + rrdcalctemplate_free(host, rt); + + fclose(fp); + return 1; +} + +void health_readdir(RRDHOST *host, const char *path) { + if(!host->health_enabled) return; + + size_t pathlen = strlen(path); + + debug(D_HEALTH, "Health configuration reading directory '%s'", path); + + DIR *dir = opendir(path); + if (!dir) { + error("Health configuration cannot open directory '%s'.", path); + return; + } + + struct dirent *de = NULL; + while ((de = readdir(dir))) { + size_t len = strlen(de->d_name); + + if(de->d_type == DT_DIR + && ( + (de->d_name[0] == '.' && de->d_name[1] == '\0') + || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') + )) { + debug(D_HEALTH, "Ignoring directory '%s'", de->d_name); + continue; + } + + else if(de->d_type == DT_DIR) { + char *s = mallocz(pathlen + strlen(de->d_name) + 2); + strcpy(s, path); + strcat(s, "/"); + strcat(s, de->d_name); + health_readdir(host, s); + freez(s); + continue; + } + + else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) && + len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { + health_readfile(host, path, de->d_name); + } + + else debug(D_HEALTH, "Ignoring file '%s'", de->d_name); + } + + closedir(dir); +} + + diff --git a/src/health_json.c b/src/health_json.c new file mode 100644 index 00000000..4d24d5d1 --- /dev/null +++ b/src/health_json.c @@ -0,0 +1,256 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) { + if(value && *value) + buffer_sprintf(wb, "%s\"%s\":\"%s\"%s", prefix, label, value, suffix); + else + buffer_sprintf(wb, "%s\"%s\":null%s", prefix, label, suffix); +} + +static inline void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host) { + buffer_sprintf(wb, + "\n\t{\n" + "\t\t\"hostname\": \"%s\",\n" + "\t\t\"unique_id\": %u,\n" + "\t\t\"alarm_id\": %u,\n" + "\t\t\"alarm_event_id\": %u,\n" + "\t\t\"name\": \"%s\",\n" + "\t\t\"chart\": \"%s\",\n" + "\t\t\"family\": \"%s\",\n" + "\t\t\"processed\": %s,\n" + "\t\t\"updated\": %s,\n" + "\t\t\"exec_run\": %lu,\n" + "\t\t\"exec_failed\": %s,\n" + "\t\t\"exec\": \"%s\",\n" + "\t\t\"recipient\": \"%s\",\n" + "\t\t\"exec_code\": %d,\n" + "\t\t\"source\": \"%s\",\n" + "\t\t\"units\": \"%s\",\n" + "\t\t\"info\": \"%s\",\n" + "\t\t\"when\": %lu,\n" + "\t\t\"duration\": %lu,\n" + "\t\t\"non_clear_duration\": %lu,\n" + "\t\t\"status\": \"%s\",\n" + "\t\t\"old_status\": \"%s\",\n" + "\t\t\"delay\": %d,\n" + "\t\t\"delay_up_to_timestamp\": %lu,\n" + "\t\t\"updated_by_id\": %u,\n" + "\t\t\"updates_id\": %u,\n" + "\t\t\"value_string\": \"%s\",\n" + "\t\t\"old_value_string\": \"%s\",\n" + , host->hostname + , ae->unique_id + , ae->alarm_id + , ae->alarm_event_id + , ae->name + , ae->chart + , ae->family + , (ae->flags & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false" + , (ae->flags & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false" + , (unsigned long)ae->exec_run_timestamp + , (ae->flags & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false" + , ae->exec?ae->exec:host->health_default_exec + , ae->recipient?ae->recipient:host->health_default_recipient + , ae->exec_code + , ae->source + , ae->units?ae->units:"" + , ae->info?ae->info:"" + , (unsigned long)ae->when + , (unsigned long)ae->duration + , (unsigned long)ae->non_clear_duration + , rrdcalc_status2string(ae->new_status) + , rrdcalc_status2string(ae->old_status) + , ae->delay + , (unsigned long)ae->delay_up_to_timestamp + , ae->updated_by_id + , ae->updates_id + , ae->new_value_string + , ae->old_value_string + ); + + if(unlikely(ae->flags & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) { + buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n"); + } + + buffer_strcat(wb, "\t\t\"value\":"); + buffer_rrd_value(wb, ae->new_value); + buffer_strcat(wb, ",\n"); + + buffer_strcat(wb, "\t\t\"old_value\":"); + buffer_rrd_value(wb, ae->old_value); + buffer_strcat(wb, "\n"); + + buffer_strcat(wb, "\t}"); +} + +void health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after) { + pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); + + buffer_strcat(wb, "["); + + unsigned int max = host->health_log.max; + unsigned int count = 0; + ALARM_ENTRY *ae; + for(ae = host->health_log.alarms; ae && count < max ; count++, ae = ae->next) { + if(ae->unique_id > after) { + if(likely(count)) buffer_strcat(wb, ","); + health_alarm_entry2json_nolock(wb, ae, host); + } + } + + buffer_strcat(wb, "\n]\n"); + + pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); +} + +static inline void health_rrdcalc2json_nolock(RRDHOST *host, BUFFER *wb, RRDCALC *rc) { + char value_string[100 + 1]; + format_value_and_unit(value_string, 100, rc->value, rc->units, -1); + + buffer_sprintf(wb, + "\t\t\"%s.%s\": {\n" + "\t\t\t\"id\": %lu,\n" + "\t\t\t\"name\": \"%s\",\n" + "\t\t\t\"chart\": \"%s\",\n" + "\t\t\t\"family\": \"%s\",\n" + "\t\t\t\"active\": %s,\n" + "\t\t\t\"exec\": \"%s\",\n" + "\t\t\t\"recipient\": \"%s\",\n" + "\t\t\t\"source\": \"%s\",\n" + "\t\t\t\"units\": \"%s\",\n" + "\t\t\t\"info\": \"%s\",\n" + "\t\t\t\"status\": \"%s\",\n" + "\t\t\t\"last_status_change\": %lu,\n" + "\t\t\t\"last_updated\": %lu,\n" + "\t\t\t\"next_update\": %lu,\n" + "\t\t\t\"update_every\": %d,\n" + "\t\t\t\"delay_up_duration\": %d,\n" + "\t\t\t\"delay_down_duration\": %d,\n" + "\t\t\t\"delay_max_duration\": %d,\n" + "\t\t\t\"delay_multiplier\": %f,\n" + "\t\t\t\"delay\": %d,\n" + "\t\t\t\"delay_up_to_timestamp\": %lu,\n" + "\t\t\t\"value_string\": \"%s\",\n" + , rc->chart, rc->name + , (unsigned long)rc->id + , rc->name + , rc->chart + , (rc->rrdset && rc->rrdset->family)?rc->rrdset->family:"" + , (rc->rrdset)?"true":"false" + , rc->exec?rc->exec:host->health_default_exec + , rc->recipient?rc->recipient:host->health_default_recipient + , rc->source + , rc->units?rc->units:"" + , rc->info?rc->info:"" + , rrdcalc_status2string(rc->status) + , (unsigned long)rc->last_status_change + , (unsigned long)rc->last_updated + , (unsigned long)rc->next_update + , rc->update_every + , rc->delay_up_duration + , rc->delay_down_duration + , rc->delay_max_duration + , rc->delay_multiplier + , rc->delay_last + , (unsigned long)rc->delay_up_to_timestamp + , value_string + ); + + if(unlikely(rc->options & RRDCALC_FLAG_NO_CLEAR_NOTIFICATION)) { + buffer_strcat(wb, "\t\t\t\"no_clear_notification\": true,\n"); + } + + if(RRDCALC_HAS_DB_LOOKUP(rc)) { + if(rc->dimensions && *rc->dimensions) + health_string2json(wb, "\t\t\t", "lookup_dimensions", rc->dimensions, ",\n"); + + buffer_sprintf(wb, + "\t\t\t\"db_after\": %lu,\n" + "\t\t\t\"db_before\": %lu,\n" + "\t\t\t\"lookup_method\": \"%s\",\n" + "\t\t\t\"lookup_after\": %d,\n" + "\t\t\t\"lookup_before\": %d,\n" + "\t\t\t\"lookup_options\": \"", + (unsigned long) rc->db_after, + (unsigned long) rc->db_before, + group_method2string(rc->group), + rc->after, + rc->before + ); + buffer_data_options2string(wb, rc->options); + buffer_strcat(wb, "\",\n"); + } + + if(rc->calculation) { + health_string2json(wb, "\t\t\t", "calc", rc->calculation->source, ",\n"); + health_string2json(wb, "\t\t\t", "calc_parsed", rc->calculation->parsed_as, ",\n"); + } + + if(rc->warning) { + health_string2json(wb, "\t\t\t", "warn", rc->warning->source, ",\n"); + health_string2json(wb, "\t\t\t", "warn_parsed", rc->warning->parsed_as, ",\n"); + } + + if(rc->critical) { + health_string2json(wb, "\t\t\t", "crit", rc->critical->source, ",\n"); + health_string2json(wb, "\t\t\t", "crit_parsed", rc->critical->parsed_as, ",\n"); + } + + buffer_strcat(wb, "\t\t\t\"green\":"); + buffer_rrd_value(wb, rc->green); + buffer_strcat(wb, ",\n"); + + buffer_strcat(wb, "\t\t\t\"red\":"); + buffer_rrd_value(wb, rc->red); + buffer_strcat(wb, ",\n"); + + buffer_strcat(wb, "\t\t\t\"value\":"); + buffer_rrd_value(wb, rc->value); + buffer_strcat(wb, "\n"); + + buffer_strcat(wb, "\t\t}"); +} + +//void health_rrdcalctemplate2json_nolock(BUFFER *wb, RRDCALCTEMPLATE *rt) { +// +//} + +void health_alarms2json(RRDHOST *host, BUFFER *wb, int all) { + int i; + + rrdhost_rdlock(host); + buffer_sprintf(wb, "{\n\t\"hostname\": \"%s\"," + "\n\t\"latest_alarm_log_unique_id\": %u," + "\n\t\"status\": %s," + "\n\t\"now\": %lu," + "\n\t\"alarms\": {\n", + host->hostname, + (host->health_log.next_log_id > 0)?(host->health_log.next_log_id - 1):0, + host->health_enabled?"true":"false", + (unsigned long)now_realtime_sec()); + + RRDCALC *rc; + for(i = 0, rc = host->alarms; rc ; rc = rc->next) { + if(unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec)) + continue; + + if(likely(!all && !(rc->status == RRDCALC_STATUS_WARNING || rc->status == RRDCALC_STATUS_CRITICAL))) + continue; + + if(likely(i)) buffer_strcat(wb, ",\n"); + health_rrdcalc2json_nolock(host, wb, rc); + i++; + } + +// buffer_strcat(wb, "\n\t},\n\t\"templates\": {"); +// RRDCALCTEMPLATE *rt; +// for(rt = host->templates; rt ; rt = rt->next) +// health_rrdcalctemplate2json_nolock(wb, rt); + + buffer_strcat(wb, "\n\t}\n}\n"); + rrdhost_unlock(host); +} + + + diff --git a/src/health_log.c b/src/health_log.c new file mode 100644 index 00000000..990894ef --- /dev/null +++ b/src/health_log.c @@ -0,0 +1,465 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +// ---------------------------------------------------------------------------- +// health alarm log load/save +// no need for locking - only one thread is reading / writing the alarms log + +inline int health_alarm_log_open(RRDHOST *host) { + if(host->health_log_fp) + fclose(host->health_log_fp); + + host->health_log_fp = fopen(host->health_log_filename, "a"); + + if(host->health_log_fp) { + if (setvbuf(host->health_log_fp, NULL, _IOLBF, 0) != 0) + error("HEALTH [%s]: cannot set line buffering on health log file '%s'.", host->hostname, host->health_log_filename); + return 0; + } + + error("HEALTH [%s]: cannot open health log file '%s'. Health data will be lost in case of netdata or server crash.", host->hostname, host->health_log_filename); + return -1; +} + +inline void health_alarm_log_close(RRDHOST *host) { + if(host->health_log_fp) { + fclose(host->health_log_fp); + host->health_log_fp = NULL; + } +} + +inline void health_log_rotate(RRDHOST *host) { + static size_t rotate_every = 0; + + if(unlikely(rotate_every == 0)) { + rotate_every = (size_t)config_get_number(CONFIG_SECTION_HEALTH, "rotate log every lines", 2000); + if(rotate_every < 100) rotate_every = 100; + } + + if(unlikely(host->health_log_entries_written > rotate_every)) { + health_alarm_log_close(host); + + char old_filename[FILENAME_MAX + 1]; + snprintfz(old_filename, FILENAME_MAX, "%s.old", host->health_log_filename); + + if(unlink(old_filename) == -1 && errno != ENOENT) + error("HEALTH [%s]: cannot remove old alarms log file '%s'", host->hostname, old_filename); + + if(link(host->health_log_filename, old_filename) == -1 && errno != ENOENT) + error("HEALTH [%s]: cannot move file '%s' to '%s'.", host->hostname, host->health_log_filename, old_filename); + + if(unlink(host->health_log_filename) == -1 && errno != ENOENT) + error("HEALTH [%s]: cannot remove old alarms log file '%s'", host->hostname, host->health_log_filename); + + // open it with truncate + host->health_log_fp = fopen(host->health_log_filename, "w"); + + if(host->health_log_fp) + fclose(host->health_log_fp); + else + error("HEALTH [%s]: cannot truncate health log '%s'", host->hostname, host->health_log_filename); + + host->health_log_fp = NULL; + + host->health_log_entries_written = 0; + health_alarm_log_open(host); + } +} + +inline void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae) { + health_log_rotate(host); + + if(likely(host->health_log_fp)) { + if(unlikely(fprintf(host->health_log_fp + , "%c\t%s" + "\t%08x\t%08x\t%08x\t%08x\t%08x" + "\t%08x\t%08x\t%08x" + "\t%08x\t%08x\t%08x" + "\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s" + "\t%d\t%d\t%d\t%d" + "\t%Lf\t%Lf" + "\n" + , (ae->flags & HEALTH_ENTRY_FLAG_SAVED)?'U':'A' + , host->hostname + + , ae->unique_id + , ae->alarm_id + , ae->alarm_event_id + , ae->updated_by_id + , ae->updates_id + + , (uint32_t)ae->when + , (uint32_t)ae->duration + , (uint32_t)ae->non_clear_duration + , (uint32_t)ae->flags + , (uint32_t)ae->exec_run_timestamp + , (uint32_t)ae->delay_up_to_timestamp + + , (ae->name)?ae->name:"" + , (ae->chart)?ae->chart:"" + , (ae->family)?ae->family:"" + , (ae->exec)?ae->exec:"" + , (ae->recipient)?ae->recipient:"" + , (ae->source)?ae->source:"" + , (ae->units)?ae->units:"" + , (ae->info)?ae->info:"" + + , ae->exec_code + , ae->new_status + , ae->old_status + , ae->delay + + , (long double)ae->new_value + , (long double)ae->old_value + ) < 0)) + error("HEALTH [%s]: failed to save alarm log entry to '%s'. Health data may be lost in case of abnormal restart.", host->hostname, host->health_log_filename); + else { + ae->flags |= HEALTH_ENTRY_FLAG_SAVED; + host->health_log_entries_written++; + } + } +} + +inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename) { + static uint32_t max_unique_id = 0, max_alarm_id = 0; + + errno = 0; + + char *s, *buf = mallocz(65536 + 1); + size_t line = 0, len = 0; + ssize_t loaded = 0, updated = 0, errored = 0, duplicate = 0; + + pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); + + while((s = fgets_trim_len(buf, 65536, fp, &len))) { + host->health_log_entries_written++; + line++; + + int max_entries = 30, entries = 0; + char *pointers[max_entries]; + + pointers[entries++] = s++; + while(*s) { + if(unlikely(*s == '\t')) { + *s = '\0'; + pointers[entries++] = ++s; + if(entries >= max_entries) { + error("HEALTH [%s]: line %zu of file '%s' has more than %d entries. Ignoring excessive entries.", host->hostname, line, filename, max_entries); + break; + } + } + else s++; + } + + if(likely(*pointers[0] == 'U' || *pointers[0] == 'A')) { + ALARM_ENTRY *ae = NULL; + + if(entries < 26) { + error("HEALTH [%s]: line %zu of file '%s' should have at least 26 entries, but it has %d. Ignoring it.", host->hostname, line, filename, entries); + errored++; + continue; + } + + // check that we have valid ids + uint32_t unique_id = (uint32_t)strtoul(pointers[2], NULL, 16); + if(!unique_id) { + error("HEALTH [%s]: line %zu of file '%s' states alarm entry with invalid unique id %u (%s). Ignoring it.", host->hostname, line, filename, unique_id, pointers[2]); + errored++; + continue; + } + + uint32_t alarm_id = (uint32_t)strtoul(pointers[3], NULL, 16); + if(!alarm_id) { + error("HEALTH [%s]: line %zu of file '%s' states alarm entry for invalid alarm id %u (%s). Ignoring it.", host->hostname, line, filename, alarm_id, pointers[3]); + errored++; + continue; + } + + if(unlikely(*pointers[0] == 'A')) { + // make sure it is properly numbered + if(unlikely(host->health_log.alarms && unique_id < host->health_log.alarms->unique_id)) { + error("HEALTH [%s]: line %zu of file '%s' has alarm log entry %u in wrong order. Ignoring it.", host->hostname, line, filename, unique_id); + errored++; + continue; + } + + ae = callocz(1, sizeof(ALARM_ENTRY)); + } + else if(unlikely(*pointers[0] == 'U')) { + // find the original + for(ae = host->health_log.alarms; ae; ae = ae->next) { + if(unlikely(unique_id == ae->unique_id)) { + if(unlikely(*pointers[0] == 'A')) { + error("HEALTH [%s]: line %zu of file '%s' adds duplicate alarm log entry %u. Using the later." + , host->hostname, line, filename, unique_id); + *pointers[0] = 'U'; + duplicate++; + } + break; + } + else if(unlikely(unique_id > ae->unique_id)) { + // no need to continue + // the linked list is sorted + ae = NULL; + break; + } + } + } + + // if not found, skip this line + if(unlikely(!ae)) { + // error("HEALTH [%s]: line %zu of file '%s' updates alarm log entry with unique id %u, but it is not found.", host->hostname, line, filename, unique_id); + continue; + } + + // check for a possible host missmatch + //if(strcmp(pointers[1], host->hostname)) + // error("HEALTH [%s]: line %zu of file '%s' provides an alarm for host '%s' but this is named '%s'.", host->hostname, line, filename, pointers[1], host->hostname); + + ae->unique_id = unique_id; + ae->alarm_id = alarm_id; + ae->alarm_event_id = (uint32_t)strtoul(pointers[4], NULL, 16); + ae->updated_by_id = (uint32_t)strtoul(pointers[5], NULL, 16); + ae->updates_id = (uint32_t)strtoul(pointers[6], NULL, 16); + + ae->when = (uint32_t)strtoul(pointers[7], NULL, 16); + ae->duration = (uint32_t)strtoul(pointers[8], NULL, 16); + ae->non_clear_duration = (uint32_t)strtoul(pointers[9], NULL, 16); + + ae->flags = (uint32_t)strtoul(pointers[10], NULL, 16); + ae->flags |= HEALTH_ENTRY_FLAG_SAVED; + + ae->exec_run_timestamp = (uint32_t)strtoul(pointers[11], NULL, 16); + ae->delay_up_to_timestamp = (uint32_t)strtoul(pointers[12], NULL, 16); + + freez(ae->name); + ae->name = strdupz(pointers[13]); + ae->hash_name = simple_hash(ae->name); + + freez(ae->chart); + ae->chart = strdupz(pointers[14]); + ae->hash_chart = simple_hash(ae->chart); + + freez(ae->family); + ae->family = strdupz(pointers[15]); + + freez(ae->exec); + ae->exec = strdupz(pointers[16]); + if(!*ae->exec) { freez(ae->exec); ae->exec = NULL; } + + freez(ae->recipient); + ae->recipient = strdupz(pointers[17]); + if(!*ae->recipient) { freez(ae->recipient); ae->recipient = NULL; } + + freez(ae->source); + ae->source = strdupz(pointers[18]); + if(!*ae->source) { freez(ae->source); ae->source = NULL; } + + freez(ae->units); + ae->units = strdupz(pointers[19]); + if(!*ae->units) { freez(ae->units); ae->units = NULL; } + + freez(ae->info); + ae->info = strdupz(pointers[20]); + if(!*ae->info) { freez(ae->info); ae->info = NULL; } + + ae->exec_code = str2i(pointers[21]); + ae->new_status = str2i(pointers[22]); + ae->old_status = str2i(pointers[23]); + ae->delay = str2i(pointers[24]); + + ae->new_value = str2l(pointers[25]); + ae->old_value = str2l(pointers[26]); + + static char value_string[100 + 1]; + freez(ae->old_value_string); + freez(ae->new_value_string); + ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1)); + ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1)); + + // add it to host if not already there + if(unlikely(*pointers[0] == 'A')) { + ae->next = host->health_log.alarms; + host->health_log.alarms = ae; + loaded++; + } + else updated++; + + if(unlikely(ae->unique_id > max_unique_id)) + max_unique_id = ae->unique_id; + + if(unlikely(ae->alarm_id >= max_alarm_id)) + max_alarm_id = ae->alarm_id; + } + else { + error("HEALTH [%s]: line %zu of file '%s' is invalid (unrecognized entry type '%s').", host->hostname, line, filename, pointers[0]); + errored++; + } + } + + pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); + + freez(buf); + + if(!max_unique_id) max_unique_id = (uint32_t)now_realtime_sec(); + if(!max_alarm_id) max_alarm_id = (uint32_t)now_realtime_sec(); + + host->health_log.next_log_id = max_unique_id + 1; + host->health_log.next_alarm_id = max_alarm_id + 1; + + debug(D_HEALTH, "HEALTH [%s]: loaded file '%s' with %zd new alarm entries, updated %zd alarms, errors %zd entries, duplicate %zd", host->hostname, filename, loaded, updated, errored, duplicate); + return loaded; +} + +inline void health_alarm_log_load(RRDHOST *host) { + health_alarm_log_close(host); + + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s.old", host->health_log_filename); + FILE *fp = fopen(filename, "r"); + if(!fp) + error("HEALTH [%s]: cannot open health file: %s", host->hostname, filename); + else { + health_alarm_log_read(host, fp, filename); + fclose(fp); + } + + host->health_log_entries_written = 0; + fp = fopen(host->health_log_filename, "r"); + if(!fp) + error("HEALTH [%s]: cannot open health file: %s", host->hostname, host->health_log_filename); + else { + health_alarm_log_read(host, fp, host->health_log_filename); + fclose(fp); + } + + health_alarm_log_open(host); +} + + +// ---------------------------------------------------------------------------- +// health alarm log management + +inline void health_alarm_log( + RRDHOST *host, + uint32_t alarm_id, + uint32_t alarm_event_id, + time_t when, + const char *name, + const char *chart, + const char *family, + const char *exec, + const char *recipient, + time_t duration, + calculated_number old_value, + calculated_number new_value, + int old_status, + int new_status, + const char *source, + const char *units, + const char *info, + int delay, + uint32_t flags +) { + debug(D_HEALTH, "Health adding alarm log entry with id: %u", host->health_log.next_log_id); + + ALARM_ENTRY *ae = callocz(1, sizeof(ALARM_ENTRY)); + ae->name = strdupz(name); + ae->hash_name = simple_hash(ae->name); + + if(chart) { + ae->chart = strdupz(chart); + ae->hash_chart = simple_hash(ae->chart); + } + + if(family) + ae->family = strdupz(family); + + if(exec) ae->exec = strdupz(exec); + if(recipient) ae->recipient = strdupz(recipient); + if(source) ae->source = strdupz(source); + if(units) ae->units = strdupz(units); + if(info) ae->info = strdupz(info); + + ae->unique_id = host->health_log.next_log_id++; + ae->alarm_id = alarm_id; + ae->alarm_event_id = alarm_event_id; + ae->when = when; + ae->old_value = old_value; + ae->new_value = new_value; + + static char value_string[100 + 1]; + ae->old_value_string = strdupz(format_value_and_unit(value_string, 100, ae->old_value, ae->units, -1)); + ae->new_value_string = strdupz(format_value_and_unit(value_string, 100, ae->new_value, ae->units, -1)); + + ae->old_status = old_status; + ae->new_status = new_status; + ae->duration = duration; + ae->delay = delay; + ae->delay_up_to_timestamp = when + delay; + + ae->flags |= flags; + + if(ae->old_status == RRDCALC_STATUS_WARNING || ae->old_status == RRDCALC_STATUS_CRITICAL) + ae->non_clear_duration += ae->duration; + + // link it + pthread_rwlock_wrlock(&host->health_log.alarm_log_rwlock); + ae->next = host->health_log.alarms; + host->health_log.alarms = ae; + host->health_log.count++; + pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); + + // match previous alarms + pthread_rwlock_rdlock(&host->health_log.alarm_log_rwlock); + ALARM_ENTRY *t; + for(t = host->health_log.alarms ; t ; t = t->next) { + if(t != ae && t->alarm_id == ae->alarm_id) { + if(!(t->flags & HEALTH_ENTRY_FLAG_UPDATED) && !t->updated_by_id) { + t->flags |= HEALTH_ENTRY_FLAG_UPDATED; + t->updated_by_id = ae->unique_id; + ae->updates_id = t->unique_id; + + if((t->new_status == RRDCALC_STATUS_WARNING || t->new_status == RRDCALC_STATUS_CRITICAL) && + (t->old_status == RRDCALC_STATUS_WARNING || t->old_status == RRDCALC_STATUS_CRITICAL)) + ae->non_clear_duration += t->non_clear_duration; + + health_alarm_log_save(host, t); + } + + // no need to continue + break; + } + } + pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); + + health_alarm_log_save(host, ae); +} + +inline void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae) { + freez(ae->name); + freez(ae->chart); + freez(ae->family); + freez(ae->exec); + freez(ae->recipient); + freez(ae->source); + freez(ae->units); + freez(ae->info); + freez(ae->old_value_string); + freez(ae->new_value_string); + freez(ae); +} + +inline void health_alarm_log_free(RRDHOST *host) { + rrdhost_check_wrlock(host); + + pthread_rwlock_wrlock(&host->health_log.alarm_log_rwlock); + + ALARM_ENTRY *ae; + while((ae = host->health_log.alarms)) { + host->health_log.alarms = ae->next; + health_alarm_log_free_one_nochecks_nounlink(ae); + } + + pthread_rwlock_unlock(&host->health_log.alarm_log_rwlock); +} diff --git a/src/ipc.c b/src/ipc.c index 39797893..1dabf5e1 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -184,23 +184,27 @@ int do_ipc(int update_every, usec_t dt) { return 1; } - arrays_max = rrdvar_custom_host_variable_create(&localhost, "ipc.semaphores.arrays.max"); - semaphores_max = rrdvar_custom_host_variable_create(&localhost, "ipc.semaphores.max"); + arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.arrays.max"); + semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.max"); if(arrays_max) rrdvar_custom_host_variable_set(arrays_max, limits.semmni); if(semaphores_max) rrdvar_custom_host_variable_set(semaphores_max, limits.semmns); // create the charts - semaphores = rrdset_find("system.ipc_semaphores"); + semaphores = rrdset_find_localhost("system.ipc_semaphores"); if(!semaphores) { - semaphores = rrdset_create("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(semaphores, "semaphores", NULL, 1, 1, RRDDIM_ABSOLUTE); + semaphores = rrdset_create_localhost("system", "ipc_semaphores", NULL, "ipc semaphores", NULL + , "IPC Semaphores", "semaphores", 1000, localhost->rrd_update_every + , RRDSET_TYPE_AREA); + rrddim_add(semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } - arrays = rrdset_find("system.ipc_semaphore_arrays"); + arrays = rrdset_find_localhost("system.ipc_semaphore_arrays"); if(!arrays) { - arrays = rrdset_create("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(arrays, "arrays", NULL, 1, 1, RRDDIM_ABSOLUTE); + arrays = rrdset_create_localhost("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL + , "IPC Semaphore Arrays", "arrays", 1000, localhost->rrd_update_every + , RRDSET_TYPE_AREA); + rrddim_add(arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } } diff --git a/src/log.c b/src/log.c index d4c7fa14..855ecaee 100644 --- a/src/log.c +++ b/src/log.c @@ -1,7 +1,7 @@ #include "common.h" const char *program_name = ""; -unsigned long long debug_flags = DEBUG; +uint64_t debug_flags = DEBUG; int access_log_syslog = 1; int error_log_syslog = 1; @@ -257,8 +257,8 @@ void info_int( const char *file, const char *function, const unsigned long line, log_date(stderr); va_start( args, fmt ); - if(debug_flags) fprintf(stderr, "%s: INFO: (%04lu@%-10.10s:%-15.15s):", program_name, line, file, function); - else fprintf(stderr, "%s: INFO: ", program_name); + if(debug_flags) fprintf(stderr, "%s: INFO : (%04lu@%-10.10s:%-15.15s): ", program_name, line, file, function); + else fprintf(stderr, "%s: INFO : ", program_name); vfprintf( stderr, fmt, args ); va_end( args ); diff --git a/src/log.h b/src/log.h index e61ffdd0..24b971e2 100644 --- a/src/log.h +++ b/src/log.h @@ -1,38 +1,39 @@ #ifndef NETDATA_LOG_H #define NETDATA_LOG_H 1 -#define D_WEB_BUFFER 0x00000001 -#define D_WEB_CLIENT 0x00000002 -#define D_LISTENER 0x00000004 -#define D_WEB_DATA 0x00000008 -#define D_OPTIONS 0x00000010 -#define D_PROCNETDEV_LOOP 0x00000020 -#define D_RRD_STATS 0x00000040 -#define D_WEB_CLIENT_ACCESS 0x00000080 -#define D_TC_LOOP 0x00000100 -#define D_DEFLATE 0x00000200 -#define D_CONFIG 0x00000400 -#define D_PLUGINSD 0x00000800 -#define D_CHILDS 0x00001000 -#define D_EXIT 0x00002000 -#define D_CHECKS 0x00004000 -#define D_NFACCT_LOOP 0x00008000 -#define D_PROCFILE 0x00010000 -#define D_RRD_CALLS 0x00020000 -#define D_DICTIONARY 0x00040000 -#define D_MEMORY 0x00080000 -#define D_CGROUP 0x00100000 -#define D_REGISTRY 0x00200000 -#define D_VARIABLES 0x00400000 -#define D_HEALTH 0x00800000 -#define D_CONNECT_TO 0x01000000 -#define D_SYSTEM 0x80000000 +#define D_WEB_BUFFER 0x0000000000000001 +#define D_WEB_CLIENT 0x0000000000000002 +#define D_LISTENER 0x0000000000000004 +#define D_WEB_DATA 0x0000000000000008 +#define D_OPTIONS 0x0000000000000010 +#define D_PROCNETDEV_LOOP 0x0000000000000020 +#define D_RRD_STATS 0x0000000000000040 +#define D_WEB_CLIENT_ACCESS 0x0000000000000080 +#define D_TC_LOOP 0x0000000000000100 +#define D_DEFLATE 0x0000000000000200 +#define D_CONFIG 0x0000000000000400 +#define D_PLUGINSD 0x0000000000000800 +#define D_CHILDS 0x0000000000001000 +#define D_EXIT 0x0000000000002000 +#define D_CHECKS 0x0000000000004000 +#define D_NFACCT_LOOP 0x0000000000008000 +#define D_PROCFILE 0x0000000000010000 +#define D_RRD_CALLS 0x0000000000020000 +#define D_DICTIONARY 0x0000000000040000 +#define D_MEMORY 0x0000000000080000 +#define D_CGROUP 0x0000000000100000 +#define D_REGISTRY 0x0000000000200000 +#define D_VARIABLES 0x0000000000400000 +#define D_HEALTH 0x0000000000800000 +#define D_CONNECT_TO 0x0000000001000000 +#define D_RRDHOST 0x0000000002000000 +#define D_SYSTEM 0x8000000000000000 //#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS) //#define DEBUG 0xffffffff #define DEBUG (0) -extern unsigned long long debug_flags; +extern uint64_t debug_flags; extern const char *program_name; diff --git a/src/macos_fw.c b/src/macos_fw.c index a62aa7a7..c47da52f 100644 --- a/src/macos_fw.c +++ b/src/macos_fw.c @@ -136,12 +136,14 @@ int do_macos_iokit(int update_every, usec_t dt) { total_disk_writes += diskstat.bytes_write; } - st = rrdset_find_bytype("disk", diskstat.name); + st = rrdset_find_bytype_localhost("disk", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk", diskstat.name, NULL, diskstat.name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("disk", diskstat.name, NULL, diskstat.name, "disk.io" + , "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every + , RRDSET_TYPE_AREA); - rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -161,13 +163,15 @@ int do_macos_iokit(int update_every, usec_t dt) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.writes); } - st = rrdset_find_bytype("disk_ops", diskstat.name); + st = rrdset_find_bytype_localhost("disk_ops", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk_ops", diskstat.name, NULL, diskstat.name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_ops", diskstat.name, NULL, diskstat.name, "disk.ops" + , "Disk Completed I/O Operations", "operations/s", 2001 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -187,12 +191,14 @@ int do_macos_iokit(int update_every, usec_t dt) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.time_write); } - st = rrdset_find_bytype("disk_util", diskstat.name); + st = rrdset_find_bytype_localhost("disk_util", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk_util", diskstat.name, NULL, diskstat.name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("disk_util", diskstat.name, NULL, diskstat.name, "disk.util" + , "Disk Utilization Time", "% of time working", 2004, update_every + , RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "utilization", NULL, 1, 10000000, RRDDIM_INCREMENTAL); + rrddim_add(st, "utilization", NULL, 1, 10000000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -212,13 +218,15 @@ int do_macos_iokit(int update_every, usec_t dt) { CFNumberGetValue(number, kCFNumberSInt64Type, &diskstat.latency_write); } - st = rrdset_find_bytype("disk_iotime", diskstat.name); + st = rrdset_find_bytype_localhost("disk_iotime", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk_iotime", diskstat.name, NULL, diskstat.name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_iotime", diskstat.name, NULL, diskstat.name, "disk.iotime" + , "Disk Total I/O Time", "milliseconds/s", 2022, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -236,13 +244,15 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_await", diskstat.name); + st = rrdset_find_bytype_localhost("disk_await", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk_await", diskstat.name, NULL, diskstat.name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_await", diskstat.name, NULL, diskstat.name, "disk.await" + , "Average Completed I/O Operation Time", "ms per operation" + , 2005, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1000000, RRDDIM_ABSOLUTE); - rrddim_add(st, "writes", NULL, -1, 1000000, RRDDIM_ABSOLUTE); + rrddim_add(st, "reads", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "writes", NULL, -1, 1000000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -254,13 +264,16 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_avgsz", diskstat.name); + st = rrdset_find_bytype_localhost("disk_avgsz", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk_avgsz", diskstat.name, NULL, diskstat.name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; - - rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("disk_avgsz", diskstat.name, NULL, diskstat.name, "disk.avgsz" + , "Average Completed I/O Operation Bandwidth" + , "kilobytes per operation", 2006, update_every + , RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -272,12 +285,14 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("disk_svctm", diskstat.name); + st = rrdset_find_bytype_localhost("disk_svctm", diskstat.name); if (unlikely(!st)) { - st = rrdset_create("disk_svctm", diskstat.name, NULL, diskstat.name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_svctm", diskstat.name, NULL, diskstat.name, "disk.svctm" + , "Average Service Time", "ms per operation", 2007 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "svctm", NULL, 1, 1000000, RRDDIM_ABSOLUTE); + rrddim_add(st, "svctm", NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -301,11 +316,12 @@ int do_macos_iokit(int update_every, usec_t dt) { } if (likely(do_io)) { - st = rrdset_find_bytype("system", "io"); + st = rrdset_find_bytype_localhost("system", "io"); if (unlikely(!st)) { - st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "in", NULL, 1, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150 + , update_every, RRDSET_TYPE_AREA); + rrddim_add(st, "in", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "out", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -340,17 +356,17 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------------- if (likely(do_space)) { - st = rrdset_find_bytype("disk_space", mntbuf[i].f_mntonname); + st = rrdset_find_bytype_localhost("disk_space", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Space Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); - st = rrdset_create("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.space", title, "GB", 2023, - update_every, - RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("disk_space", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname + , "disk.space", title, "GB", 2023, update_every + , RRDSET_TYPE_STACKED); - rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRDDIM_ABSOLUTE); + rrddim_add(st, "avail", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE); rrddim_add(st, "reserved_for_root", "reserved for root", mntbuf[i].f_bsize, GIGA_FACTOR, - RRDDIM_ABSOLUTE); + RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -363,15 +379,16 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------------- if (likely(do_inodes)) { - st = rrdset_find_bytype("disk_inodes", mntbuf[i].f_mntonname); + st = rrdset_find_bytype_localhost("disk_inodes", mntbuf[i].f_mntonname); if (unlikely(!st)) { snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname); - st = rrdset_create("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname, "disk.inodes", title, "Inodes", 2024, - update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("disk_inodes", mntbuf[i].f_mntonname, NULL, mntbuf[i].f_mntonname + , "disk.inodes", title, "Inodes", 2024, update_every + , RRDSET_TYPE_STACKED); - rrddim_add(st, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -398,12 +415,13 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth" + , "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -413,15 +431,16 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_packets", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_packets", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "multicast_received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "multicast_sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets" + , "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -433,13 +452,14 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_errors", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_errors", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors" + , "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -449,12 +469,13 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_drops", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_drops", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops" + , "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -463,14 +484,16 @@ int do_macos_iokit(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("net_events", ifa->ifa_name); + st = rrdset_find_bytype_localhost("net_events", ifa->ifa_name); if (unlikely(!st)) { - st = rrdset_create("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events" + , "Network Interface Events", "events/s", 7006, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/macos_mach_smi.c b/src/macos_mach_smi.c index d86a0322..da282551 100644 --- a/src/macos_mach_smi.c +++ b/src/macos_mach_smi.c @@ -48,14 +48,15 @@ int do_macos_mach_smi(int update_every, usec_t dt) { error("DISABLED: system.cpu"); } else { - st = rrdset_find_bytype("system", "cpu"); + st = rrdset_find_bytype_localhost("system", "cpu"); if (unlikely(!st)) { - st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization" + , "percentage", 100, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "nice", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "system", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "idle", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "system", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } else rrdset_next(st); @@ -84,18 +85,19 @@ int do_macos_mach_smi(int update_every, usec_t dt) { error("DISABLED: mem.pgfaults"); } else { if (likely(do_ram)) { - st = rrdset_find("system.ram"); + st = rrdset_find_localhost("system.ram"); if (unlikely(!st)) { - st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED); - - rrddim_add(st, "active", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "wired", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "throttled", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "compressor", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "inactive", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "purgeable", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "speculative", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "free", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200 + , update_every, RRDSET_TYPE_STACKED); + + rrddim_add(st, "active", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "wired", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "throttled", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "compressor", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "inactive", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "purgeable", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "speculative", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "free", NULL, system_pagesize, 1048576, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -113,12 +115,13 @@ int do_macos_mach_smi(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_swapio)) { - st = rrdset_find("system.swapio"); + st = rrdset_find_localhost("system.swapio"); if (unlikely(!st)) { - st = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250 + , update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "in", NULL, system_pagesize, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "in", NULL, system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -130,20 +133,21 @@ int do_macos_mach_smi(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_pgfaults)) { - st = rrdset_find("mem.pgfaults"); + st = rrdset_find_localhost("mem.pgfaults"); if (unlikely(!st)) { - st = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "memory", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "cow", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "pagein", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "pageout", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "compress", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "decompress", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "zero_fill", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "reactivate", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "purge", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults" + , "page faults/s", 500, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "memory", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "cow", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "pagein", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "pageout", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "compress", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "decompress", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "zero_fill", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "reactivate", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "purge", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/macos_sysctl.c b/src/macos_sysctl.c index 1b8765cd..f43789de 100644 --- a/src/macos_sysctl.c +++ b/src/macos_sysctl.c @@ -41,10 +41,10 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_tcp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1); do_tcp_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1); do_tcp_handshake = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1); - do_ecn = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_syscookies = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_ofo = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_connaborts = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND); + do_ecn = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_BOOLEAN_AUTO); + do_tcpext_syscookies = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO); + do_tcpext_ofo = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO); + do_tcpext_connaborts = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_BOOLEAN_AUTO); do_udp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP packets", 1); do_udp_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP errors", 1); do_icmp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP packets", 1); @@ -53,17 +53,17 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_ip_fragsout = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments sent", 1); do_ip_fragsin = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments assembly", 1); do_ip_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 errors", 1); - do_ip6_packets = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND); - do_ip6_fragsout = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND); - do_ip6_fragsin = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND); - do_ip6_errors = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6 = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_redir = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_errors = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp errors", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_echos = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp echos", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_router = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp router", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_neighbor = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND); - do_icmp6_types = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp types", CONFIG_ONDEMAND_ONDEMAND); + do_ip6_packets = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 packets", CONFIG_BOOLEAN_AUTO); + do_ip6_fragsout = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO); + do_ip6_fragsin = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO); + do_ip6_errors = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 errors", CONFIG_BOOLEAN_AUTO); + do_icmp6 = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp", CONFIG_BOOLEAN_AUTO); + do_icmp6_redir = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp redirects", CONFIG_BOOLEAN_AUTO); + do_icmp6_errors = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp errors", CONFIG_BOOLEAN_AUTO); + do_icmp6_echos = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp echos", CONFIG_BOOLEAN_AUTO); + do_icmp6_router = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp router", CONFIG_BOOLEAN_AUTO); + do_icmp6_neighbor = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp neighbor", CONFIG_BOOLEAN_AUTO); + do_icmp6_types = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp types", CONFIG_BOOLEAN_AUTO); do_uptime = config_get_boolean("plugin:macos:sysctl", "system uptime", 1); } @@ -215,12 +215,14 @@ int do_macos_sysctl(int update_every, usec_t dt) { error("DISABLED: system.load"); } else { - st = rrdset_find_bytype("system", "load"); + st = rrdset_find_bytype_localhost("system", "load"); if (unlikely(!st)) { - st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "load", NULL, "load", NULL, "System Load Average", "load" + , 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) + ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -242,13 +244,14 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_swap = 0; error("DISABLED: system.swap"); } else { - st = rrdset_find("system.swap"); + st = rrdset_find_localhost("system.swap"); if (unlikely(!st)) { - st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; + st = rrdset_create_localhost("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201 + , update_every, RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "free", NULL, 1, 1048576, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, 1, 1048576, RRDDIM_ABSOLUTE); + rrddim_add(st, "free", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, 1, 1048576, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -291,12 +294,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { iftot.ift_obytes += if2m->ifm_data.ifi_obytes; } } - st = rrdset_find("system.ipv4"); + st = rrdset_find_localhost("system.ipv4"); if (unlikely(!st)) { - st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s" + , 500, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "InOctets", "received", 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutOctets", "sent", -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -328,14 +332,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.ecnpkts"); } else { if (likely(do_tcp_packets)) { - st = rrdset_find("ipv4.tcppackets"); + st = rrdset_find_localhost("ipv4.tcppackets"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", - "packets/s", - 2600, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets" + , "packets/s", 2600, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -347,16 +350,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_tcp_errors)) { - st = rrdset_find("ipv4.tcperrors"); + st = rrdset_find_localhost("ipv4.tcperrors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", - "packets/s", - 2700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s" + , 2700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -369,17 +371,16 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_tcp_handshake)) { - st = rrdset_find("ipv4.tcphandshake"); + st = rrdset_find_localhost("ipv4.tcphandshake"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL, - "IPv4 TCP Handshake Issues", - "events/s", 2900, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues" + , "events/s", 2900, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -392,16 +393,17 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop))) { - do_tcpext_connaborts = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpconnaborts"); + if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop))) { + do_tcpext_connaborts = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpconnaborts"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts" + , "connections/s", 3010, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -414,13 +416,14 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) { - do_tcpext_ofo = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpofo"); + if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_rcvoopack)) { + do_tcpext_ofo = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpofo"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue" + , "packets/s", 3050, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -430,16 +433,17 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) { - do_tcpext_syscookies = CONFIG_ONDEMAND_YES; + if (do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) { + do_tcpext_syscookies = CONFIG_BOOLEAN_YES; - st = rrdset_find("ipv4.tcpsyncookies"); + st = rrdset_find_localhost("ipv4.tcpsyncookies"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies" + , "packets/s", 3100, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -451,15 +455,16 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) { - do_ecn = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.ecnpkts"); + if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) { + do_ecn = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.ecnpkts"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics" + , "packets/s", 8700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -482,13 +487,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.udperrors"); } else { if (likely(do_udp_packets)) { - st = rrdset_find("ipv4.udppackets"); + st = rrdset_find_localhost("ipv4.udppackets"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", - "packets/s", 2601, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets" + , "packets/s", 2601, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -500,17 +505,17 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_udp_errors)) { - st = rrdset_find("ipv4.udperrors"); + st = rrdset_find_localhost("ipv4.udperrors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", - 2701, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s" + , 2701, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -543,14 +548,13 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_icmp_packets)) { - st = rrdset_find("ipv4.icmp"); + st = rrdset_find_localhost("ipv4.icmp"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s", - 2602, - update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s" + , 2602, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -561,15 +565,14 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("ipv4.icmp_errors"); + st = rrdset_find_localhost("ipv4.icmp_errors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors", - "packets/s", - 2603, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors" + , "packets/s", 2603, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -583,15 +586,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_icmpmsg)) { - st = rrdset_find("ipv4.icmpmsg"); + st = rrdset_find_localhost("ipv4.icmpmsg"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages", - "packets/s", 2604, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages" + , "packets/s", 2604, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InEchoReps", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InEchoReps", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -620,15 +623,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { error("DISABLED: ipv4.errors"); } else { if (likely(do_ip_packets)) { - st = rrdset_find("ipv4.packets"); + st = rrdset_find_localhost("ipv4.packets"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", - 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s" + , 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InReceives", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutRequests", "sent", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InDelivers", "delivered", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -642,15 +645,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ip_fragsout)) { - st = rrdset_find("ipv4.fragsout"); + st = rrdset_find_localhost("ipv4.fragsout"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", - "packets/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent" + , "packets/s", 3010, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "FragOKs", "ok", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "FragFails", "failed", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "FragCreates", "created", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -663,16 +666,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ip_fragsin)) { - st = rrdset_find("ipv4.fragsin"); + st = rrdset_find_localhost("ipv4.fragsin"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "fragsin", NULL, "fragments", NULL, - "IPv4 Fragments Reassembly", - "packets/s", 3011, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ReasmFails", "failed", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ReasmReqds", "all", 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly" + , "packets/s", 3011, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -685,21 +687,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- if (likely(do_ip_errors)) { - st = rrdset_find("ipv4.errors"); + st = rrdset_find_localhost("ipv4.errors"); if (unlikely(!st)) { - st = rrdset_create("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", - 3002, - update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s" + , 3002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -727,19 +728,19 @@ int do_macos_sysctl(int update_every, usec_t dt) { do_ip6_errors = 0; error("DISABLED: ipv6.errors"); } else { - if (do_ip6_packets == CONFIG_ONDEMAND_YES || (do_ip6_packets == CONFIG_ONDEMAND_ONDEMAND && + if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_localout || ip6stat.ip6s_total || ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) { - do_ip6_packets = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.packets"); + do_ip6_packets = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.packets"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, - update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s" + , 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -752,19 +753,19 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ip6_fragsout == CONFIG_ONDEMAND_YES || (do_ip6_fragsout == CONFIG_ONDEMAND_ONDEMAND && + if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag || ip6stat.ip6s_ofragments))) { - do_ip6_fragsout = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.fragsout"); + do_ip6_fragsout = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.fragsout"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", - "packets/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent" + , "packets/s", 3010, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -776,20 +777,20 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ip6_fragsin == CONFIG_ONDEMAND_YES || (do_ip6_fragsin == CONFIG_ONDEMAND_ONDEMAND && + if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO && (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped || ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) { - do_ip6_fragsin = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.fragsin"); + do_ip6_fragsin = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.fragsin"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", - "packets/s", 3011, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly" + , "packets/s", 3011, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -802,7 +803,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_ip6_errors == CONFIG_ONDEMAND_YES || (do_ip6_errors == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && ( ip6stat.ip6s_toosmall || ip6stat.ip6s_odropped || ip6stat.ip6s_badoptions || @@ -812,22 +813,22 @@ int do_macos_sysctl(int update_every, usec_t dt) { ip6stat.ip6s_tooshort || ip6stat.ip6s_cantforward || ip6stat.ip6s_noroute))) { - do_ip6_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.errors"); + do_ip6_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.errors"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, - update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s" + , 3002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -858,15 +859,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i]; } icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort; - if (do_icmp6 == CONFIG_ONDEMAND_YES || (do_icmp6 == CONFIG_ONDEMAND_ONDEMAND && (icmp6_total.msgs_in || icmp6_total.msgs_out))) { - do_icmp6 = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmp"); + if (do_icmp6 == CONFIG_BOOLEAN_YES || (do_icmp6 == CONFIG_BOOLEAN_AUTO && (icmp6_total.msgs_in || icmp6_total.msgs_out))) { + do_icmp6 = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmp"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", - "messages/s", 10000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s" + , 10000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -877,15 +878,15 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_redir == CONFIG_ONDEMAND_YES || (do_icmp6_redir == CONFIG_ONDEMAND_ONDEMAND && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) { - do_icmp6_redir = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmpredir"); + if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) { + do_icmp6_redir = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmpredir"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", - "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects" + , "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -896,7 +897,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_errors == CONFIG_ONDEMAND_YES || (do_icmp6_errors == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_badcode || icmp6stat.icp6s_badlen || icmp6stat.icp6s_checksum || @@ -908,22 +909,23 @@ int do_macos_sysctl(int update_every, usec_t dt) { icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] || icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] || icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) { - do_icmp6_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmperrors"); + do_icmp6_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmperrors"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors" + , "errors/s", 10100, update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -942,20 +944,21 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_echos == CONFIG_ONDEMAND_YES || (do_icmp6_echos == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] || icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] || icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] || icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) { - do_icmp6_echos = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmpechos"); + do_icmp6_echos = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmpechos"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s" + , 10200, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -968,20 +971,21 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_router == CONFIG_ONDEMAND_YES || (do_icmp6_router == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] || icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] || icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] || icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) { - do_icmp6_router = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmprouter"); + do_icmp6_router = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmprouter"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages" + , "messages/s", 10400, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -994,20 +998,21 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_neighbor == CONFIG_ONDEMAND_YES || (do_icmp6_neighbor == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] || icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] || icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] || icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) { - do_icmp6_neighbor = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmpneighbor"); + do_icmp6_neighbor = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmpneighbor"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages" + , "messages/s", 10500, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1020,7 +1025,7 @@ int do_macos_sysctl(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if (do_icmp6_types == CONFIG_ONDEMAND_YES || (do_icmp6_types == CONFIG_ONDEMAND_ONDEMAND && ( + if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && ( icmp6stat.icp6s_inhist[1] || icmp6stat.icp6s_inhist[128] || icmp6stat.icp6s_inhist[129] || @@ -1031,22 +1036,22 @@ int do_macos_sysctl(int update_every, usec_t dt) { icmp6stat.icp6s_outhist[133] || icmp6stat.icp6s_outhist[135] || icmp6stat.icp6s_outhist[136]))) { - do_icmp6_types = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv6.icmptypes"); + do_icmp6_types = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv6.icmptypes"); if (unlikely(!st)) { - st = rrdset_create("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", - "messages/s", 10700, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types" + , "messages/s", 10700, update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -1073,11 +1078,12 @@ int do_macos_sysctl(int update_every, usec_t dt) { error("DISABLED: system.uptime"); } else { clock_gettime(CLOCK_REALTIME, &cur_time); - st = rrdset_find("system.uptime"); + st = rrdset_find_localhost("system.uptime"); if(unlikely(!st)) { - st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "uptime", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000 + , update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/main.c b/src/main.c index 278e0aaf..86bd8604 100644 --- a/src/main.c +++ b/src/main.c @@ -10,7 +10,7 @@ void netdata_cleanup_and_exit(int ret) { debug(D_EXIT, "Called: netdata_cleanup_and_exit()"); // save the database - rrdset_save_all(); + rrdhost_save_all(); // unlink the pid if(pidfile[0]) { @@ -23,7 +23,8 @@ void netdata_cleanup_and_exit(int ret) { //kill_childs(); // free database - rrdset_free_all(); + sleep(2); + rrdhost_free_all(); #endif info("netdata exiting. Bye bye..."); @@ -34,51 +35,55 @@ struct netdata_static_thread static_threads[] = { #ifdef INTERNAL_PLUGIN_NFACCT // nfacct requires root access // so, we build it as an external plugin with setuid to root - {"nfacct", "plugins", "nfacct", 1, NULL, NULL, nfacct_main}, + {"nfacct", CONFIG_SECTION_PLUGINS, "nfacct", 1, NULL, NULL, nfacct_main}, #endif - {"tc", "plugins", "tc", 1, NULL, NULL, tc_main}, - {"idlejitter", "plugins", "idlejitter", 1, NULL, NULL, cpuidlejitter_main}, + {"tc", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main}, + {"idlejitter", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main}, #if defined(__FreeBSD__) - {"freebsd", "plugins", "freebsd", 1, NULL, NULL, freebsd_main}, + {"freebsd", CONFIG_SECTION_PLUGINS, "freebsd", 1, NULL, NULL, freebsd_main}, #elif defined(__APPLE__) - {"macos", "plugins", "macos", 1, NULL, NULL, macos_main}, + {"macos", CONFIG_SECTION_PLUGINS, "macos", 1, NULL, NULL, macos_main}, #else - {"proc", "plugins", "proc", 1, NULL, NULL, proc_main}, - {"diskspace", "plugins", "diskspace", 1, NULL, NULL, proc_diskspace_main}, - {"cgroups", "plugins", "cgroups", 1, NULL, NULL, cgroups_main}, + {"proc", CONFIG_SECTION_PLUGINS, "proc", 1, NULL, NULL, proc_main}, + {"diskspace", CONFIG_SECTION_PLUGINS, "diskspace", 1, NULL, NULL, proc_diskspace_main}, + {"cgroups", CONFIG_SECTION_PLUGINS, "cgroups", 1, NULL, NULL, cgroups_main}, #endif /* __FreeBSD__, __APPLE__*/ - {"check", "plugins", "checks", 0, NULL, NULL, checks_main}, - {"backends", NULL, NULL, 1, NULL, NULL, backends_main}, - {"health", NULL, NULL, 1, NULL, NULL, health_main}, - {"plugins.d", NULL, NULL, 1, NULL, NULL, pluginsd_main}, - {"web", NULL, NULL, 1, NULL, NULL, socket_listen_main_multi_threaded}, - {"web-single-threaded", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded}, - {NULL, NULL, NULL, 0, NULL, NULL, NULL} + {"check", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main}, + {"backends", NULL, NULL, 1, NULL, NULL, backends_main}, + {"health", NULL, NULL, 1, NULL, NULL, health_main}, + {"plugins.d", NULL, NULL, 1, NULL, NULL, pluginsd_main}, + {"web", NULL, NULL, 1, NULL, NULL, socket_listen_main_multi_threaded}, + {"web-single-threaded", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded}, + {"push-metrics", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread}, + {NULL, NULL, NULL, 0, NULL, NULL, NULL} }; void web_server_threading_selection(void) { - int threaded = config_get_boolean("global", "multi threaded web server", 1); + web_server_mode = web_server_mode_id(config_get(CONFIG_SECTION_WEB, "mode", web_server_mode_name(web_server_mode))); + + int multi_threaded = (web_server_mode == WEB_SERVER_MODE_MULTI_THREADED); + int single_threaded = (web_server_mode == WEB_SERVER_MODE_SINGLE_THREADED); int i; for(i = 0; static_threads[i].name ; i++) { if(static_threads[i].start_routine == socket_listen_main_multi_threaded) - static_threads[i].enabled = threaded?1:0; + static_threads[i].enabled = multi_threaded; if(static_threads[i].start_routine == socket_listen_main_single_threaded) - static_threads[i].enabled = threaded?0:1; + static_threads[i].enabled = single_threaded; } - web_client_timeout = (int) config_get_number("global", "disconnect idle web clients after seconds", DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS); + web_client_timeout = (int) config_get_number(CONFIG_SECTION_WEB, "disconnect idle clients after seconds", DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS); - respect_web_browser_do_not_track_policy = config_get_boolean("global", "respect web browser do not track policy", respect_web_browser_do_not_track_policy); - web_x_frame_options = config_get("global", "web x-frame-options header", ""); + respect_web_browser_do_not_track_policy = config_get_boolean(CONFIG_SECTION_WEB, "respect do not track policy", respect_web_browser_do_not_track_policy); + web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", ""); if(!*web_x_frame_options) web_x_frame_options = NULL; #ifdef NETDATA_WITH_ZLIB - web_enable_gzip = config_get_boolean("global", "enable web responses gzip compression", web_enable_gzip); + web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip); - char *s = config_get("global", "web compression strategy", "default"); + char *s = config_get(CONFIG_SECTION_WEB, "gzip compression strategy", "default"); if(!strcmp(s, "default")) web_gzip_strategy = Z_DEFAULT_STRATEGY; else if(!strcmp(s, "filtered")) @@ -94,7 +99,7 @@ void web_server_threading_selection(void) { web_gzip_strategy = Z_DEFAULT_STRATEGY; } - web_gzip_level = (int)config_get_number("global", "web compression level", 3); + web_gzip_level = (int)config_get_number(CONFIG_SECTION_WEB, "gzip compression level", 3); if(web_gzip_level < 1) { error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 1 (fastest compression).", web_gzip_level); web_gzip_level = 1; @@ -220,7 +225,6 @@ struct option_def options[] = { { 'h', "Display this help message.", NULL, NULL}, { 'P', "File to save a pid while running.", "filename", "do not save pid to a file"}, { 'i', "The IP address to listen to.", "IP", "all IP addresses IPv4 and IPv6"}, - { 'k', "Check health configuration and exit.", NULL, NULL}, { 'p', "API/Web port to use.", "port", "19999"}, { 's', "Prefix for /proc and /sys (for containers).", "path", "no prefix"}, { 't', "The internal clock of netdata.", "seconds", "1"}, @@ -334,9 +338,188 @@ static const char *verify_required_directory(const char *dir) { return dir; } +void log_init(void) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/debug.log", netdata_configured_log_dir); + stdout_filename = config_get(CONFIG_SECTION_GLOBAL, "debug log", filename); + + snprintfz(filename, FILENAME_MAX, "%s/error.log", netdata_configured_log_dir); + stderr_filename = config_get(CONFIG_SECTION_GLOBAL, "error log", filename); + + snprintfz(filename, FILENAME_MAX, "%s/access.log", netdata_configured_log_dir); + stdaccess_filename = config_get(CONFIG_SECTION_GLOBAL, "access log", filename); + + error_log_throttle_period_backup = + error_log_throttle_period = config_get_number(CONFIG_SECTION_GLOBAL, "errors flood protection period", error_log_throttle_period); + error_log_errors_per_period = (unsigned long)config_get_number(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection", (long long int)error_log_errors_per_period); + + setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get(CONFIG_SECTION_GLOBAL, "errors flood protection period" , ""), 1); + setenv("NETDATA_ERRORS_PER_PERIOD", config_get(CONFIG_SECTION_GLOBAL, "errors to trigger flood protection", ""), 1); +} + +static void backwards_compatible_config() { + // allow existing configurations to work with the current version of netdata + + if(config_exists(CONFIG_SECTION_GLOBAL, "multi threaded web server")) { + int mode = config_get_boolean(CONFIG_SECTION_GLOBAL, "multi threaded web server", 1); + web_server_mode = (mode)?WEB_SERVER_MODE_MULTI_THREADED:WEB_SERVER_MODE_SINGLE_THREADED; + } + + // move [global] options to the [api] section + config_move(CONFIG_SECTION_GLOBAL, "bind socket to IP", + CONFIG_SECTION_WEB, "bind to"); + + config_move(CONFIG_SECTION_GLOBAL, "bind to", + CONFIG_SECTION_WEB, "bind to"); + + config_move(CONFIG_SECTION_GLOBAL, "port", + CONFIG_SECTION_WEB, "default port"); + + config_move(CONFIG_SECTION_GLOBAL, "default port", + CONFIG_SECTION_WEB, "default port"); + + config_move(CONFIG_SECTION_GLOBAL, "disconnect idle web clients after seconds", + CONFIG_SECTION_WEB, "disconnect idle clients after seconds"); + + config_move(CONFIG_SECTION_GLOBAL, "respect web browser do not track policy", + CONFIG_SECTION_WEB, "respect do not track policy"); + + config_move(CONFIG_SECTION_GLOBAL, "web x-frame-options header", + CONFIG_SECTION_WEB, "x-frame-options response header"); + + config_move(CONFIG_SECTION_GLOBAL, "enable web responses gzip compression", + CONFIG_SECTION_WEB, "enable gzip compression"); + + config_move(CONFIG_SECTION_GLOBAL, "web compression strategy", + CONFIG_SECTION_WEB, "gzip compression strategy"); + + config_move(CONFIG_SECTION_GLOBAL, "web compression level", + CONFIG_SECTION_WEB, "gzip compression level"); + + config_move(CONFIG_SECTION_GLOBAL, "web files owner", + CONFIG_SECTION_WEB, "web files owner"); + + config_move(CONFIG_SECTION_GLOBAL, "web files group", + CONFIG_SECTION_WEB, "web files group"); +} + +static void get_netdata_configured_variables() { + backwards_compatible_config(); + + // ------------------------------------------------------------------------ + // get the hostname + + char buf[HOSTNAME_MAX + 1]; + if(gethostname(buf, HOSTNAME_MAX) == -1) + error("WARNING: Cannot get machine hostname."); + + netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf); + debug(D_OPTIONS, "hostname set to '%s'", netdata_configured_hostname); + + netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", CONFIG_DIR); + + // ------------------------------------------------------------------------ + // get default database size + + default_rrd_history_entries = (int) config_get_number(CONFIG_SECTION_GLOBAL, "history", align_entries_to_pagesize(default_rrd_memory_mode, RRD_DEFAULT_HISTORY_ENTRIES)); + + long h = align_entries_to_pagesize(default_rrd_memory_mode, default_rrd_history_entries); + if(h != default_rrd_history_entries) { + config_set_number(CONFIG_SECTION_GLOBAL, "history", h); + default_rrd_history_entries = (int)h; + } + + if(default_rrd_history_entries < 5 || default_rrd_history_entries > RRD_HISTORY_ENTRIES_MAX) { + error("Invalid history entries %d given. Defaulting to %d.", default_rrd_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); + default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; + } + + // ------------------------------------------------------------------------ + // get default database update frequency + + default_rrd_update_every = (int) config_get_number(CONFIG_SECTION_GLOBAL, "update every", UPDATE_EVERY); + if(default_rrd_update_every < 1 || default_rrd_update_every > 600) { + error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", default_rrd_update_every, UPDATE_EVERY_MAX); + default_rrd_update_every = UPDATE_EVERY; + } + + // ------------------------------------------------------------------------ + // let the plugins know the min update_every + + // get system paths + netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR); + netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR); + netdata_configured_plugins_dir = config_get(CONFIG_SECTION_GLOBAL, "plugins directory", PLUGINS_DIR); + netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR); + netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR); + netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR); + netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR); + + // ------------------------------------------------------------------------ + // get default memory mode for the database + + default_rrd_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_GLOBAL, "memory mode", rrd_memory_mode_name(default_rrd_memory_mode))); + + // ------------------------------------------------------------------------ + + netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", ""); + + // -------------------------------------------------------------------- + // get KSM settings + +#ifdef MADV_MERGEABLE + enable_ksm = config_get_boolean(CONFIG_SECTION_GLOBAL, "memory deduplication (ksm)", enable_ksm); +#endif + + // -------------------------------------------------------------------- + // get various system parameters + + get_system_HZ(); + get_system_cpus(); + get_system_pid_max(); +} + +void set_global_environment() { + { + char b[16]; + snprintfz(b, 15, "%d", default_rrd_update_every); + setenv("NETDATA_UPDATE_EVERY", b, 1); + } + + setenv("NETDATA_HOSTNAME" , netdata_configured_hostname, 1); + setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_config_dir), 1); + setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_plugins_dir), 1); + setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1); + setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1); + setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1); + setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1); + setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1); + setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1); + + // avoid flood calls to stat(/etc/localtime) + // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux + setenv("TZ", ":/etc/localtime", 0); + + // set the path we need + char path[1024 + 1], *p = getenv("PATH"); + if(!p) p = "/bin:/usr/bin"; + snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); + setenv("PATH", config_get(CONFIG_SECTION_PLUGINS, "PATH environment variable", path), 1); + + // python options + p = getenv("PYTHONPATH"); + if(!p) p = ""; + setenv("PYTHONPATH", config_get(CONFIG_SECTION_PLUGINS, "PYTHONPATH environment variable", p), 1); + + // disable buffering for python plugins + setenv("PYTHONUNBUFFERED", "1", 1); + + // switch to standard locale for plugins + setenv("LC_ALL", "C", 1); +} + int main(int argc, char **argv) { - char *hostname = "localhost"; - int i, check_config = 0; + int i; int config_loaded = 0; int dont_fork = 0; size_t wanted_stacksize = 0, stacksize = 0; @@ -361,12 +544,12 @@ int main(int argc, char **argv) { remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { - config_set("global", "host access prefix", argv[i+1]); + config_set(CONFIG_SECTION_GLOBAL, "host access prefix", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { - config_set("global", "history", argv[i+1]); + config_set(CONFIG_SECTION_GLOBAL, "history", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } @@ -396,7 +579,7 @@ int main(int argc, char **argv) { while( (opt = getopt(argc, argv, optstring)) != -1 ) { switch(opt) { case 'c': - if(load_config(optarg, 1) != 1) { + if(config_load(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); exit(1); } @@ -412,27 +595,23 @@ int main(int argc, char **argv) { help(0); break; case 'i': - config_set("global", "bind to", optarg); - break; - case 'k': - dont_fork = 1; - check_config = 1; + config_set(CONFIG_SECTION_WEB, "bind to", optarg); break; case 'P': strncpy(pidfile, optarg, FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; break; case 'p': - config_set("global", "default port", optarg); + config_set(CONFIG_SECTION_GLOBAL, "default port", optarg); break; case 's': - config_set("global", "host access prefix", optarg); + config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg); break; case 't': - config_set("global", "update every", optarg); + config_set(CONFIG_SECTION_GLOBAL, "update every", optarg); break; case 'u': - config_set("global", "run as user", optarg); + config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg); break; case 'v': printf("%s %s\n", program_name, program_version); @@ -442,7 +621,15 @@ int main(int argc, char **argv) { char* stacksize_string = "stacksize="; char* debug_flags_string = "debug_flags="; if(strcmp(optarg, "unittest") == 0) { - rrd_update_every = 1; + default_rrd_update_every = 1; + default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; + if(!config_loaded) config_load(NULL, 0); + get_netdata_configured_variables(); + default_rrd_update_every = 1; + default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; + default_health_enabled = 0; + rrd_init("unittest"); + default_rrdpush_enabled = 0; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); @@ -492,11 +679,11 @@ int main(int argc, char **argv) { } else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) { optarg += strlen(stacksize_string); - config_set("global", "pthread stack size", optarg); + config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg); } else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) { optarg += strlen(debug_flags_string); - config_set("global", "debug flags", optarg); + config_set(CONFIG_SECTION_GLOBAL, "debug flags", optarg); debug_flags = strtoull(optarg, NULL, 0); } } @@ -519,70 +706,44 @@ int main(int argc, char **argv) { #endif if(!config_loaded) - load_config(NULL, 0); + config_load(NULL, 0); + // ------------------------------------------------------------------------ + // initialize netdata { - char *pmax = config_get("global", "glibc malloc arena max for plugins", "1"); + char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1"); if(pmax && *pmax) setenv("MALLOC_ARENA_MAX", pmax, 1); #if defined(HAVE_C_MALLOPT) - int i = config_get_number("global", "glibc malloc arena max for netdata", 1); + i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1); if(i > 0) mallopt(M_ARENA_MAX, 1); #endif // prepare configuration environment variables for the plugins - netdata_configured_config_dir = config_get("global", "config directory", CONFIG_DIR); - netdata_configured_log_dir = config_get("global", "log directory", LOG_DIR); - netdata_configured_plugins_dir = config_get("global", "plugins directory", PLUGINS_DIR); - netdata_configured_web_dir = config_get("global", "web files directory", WEB_DIR); - netdata_configured_cache_dir = config_get("global", "cache directory", CACHE_DIR); - netdata_configured_varlib_dir = config_get("global", "lib directory", VARLIB_DIR); - netdata_configured_home_dir = config_get("global", "home directory", CACHE_DIR); - - setenv("NETDATA_CONFIG_DIR" , verify_required_directory(netdata_configured_config_dir), 1); - setenv("NETDATA_PLUGINS_DIR", verify_required_directory(netdata_configured_plugins_dir), 1); - setenv("NETDATA_WEB_DIR" , verify_required_directory(netdata_configured_web_dir), 1); - setenv("NETDATA_CACHE_DIR" , verify_required_directory(netdata_configured_cache_dir), 1); - setenv("NETDATA_LIB_DIR" , verify_required_directory(netdata_configured_varlib_dir), 1); - setenv("NETDATA_LOG_DIR" , verify_required_directory(netdata_configured_log_dir), 1); - setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1); - - netdata_configured_host_prefix = config_get("global", "host access prefix", ""); - setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1); - - // disable buffering for python plugins - setenv("PYTHONUNBUFFERED", "1", 1); - - // avoid flood calls to stat(/etc/localtime) - // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux - setenv("TZ", ":/etc/localtime", 0); + get_netdata_configured_variables(); + set_global_environment(); // work while we are cd into config_dir // to allow the plugins refer to their config // files using relative filenames if(chdir(netdata_configured_config_dir) == -1) fatal("Cannot cd to '%s'", netdata_configured_config_dir); - - char path[1024 + 1], *p = getenv("PATH"); - if(!p) p = "/bin:/usr/bin"; - snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); - setenv("PATH", config_get("plugins", "PATH environment variable", path), 1); - - p = getenv("PYTHONPATH"); - if(!p) p = ""; - setenv("PYTHONPATH", config_get("plugins", "PYTHONPATH environment variable", p), 1); } char *user = NULL; + { - char *flags = config_get("global", "debug flags", "0x00000000"); + // -------------------------------------------------------------------- + // get the debugging flags from the configuration file + + char *flags = config_get(CONFIG_SECTION_GLOBAL, "debug flags", "0x0000000000000000"); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); - debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); + debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; @@ -594,91 +755,25 @@ int main(int argc, char **argv) { #endif } - // -------------------------------------------------------------------- - -#ifdef MADV_MERGEABLE - enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); -#else -#warning "Kernel memory deduplication (KSM) is not available" -#endif // -------------------------------------------------------------------- + // get log filenames and settings - get_system_HZ(); - get_system_cpus(); - get_system_pid_max(); - - // -------------------------------------------------------------------- - - { - char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/debug.log", netdata_configured_log_dir); - stdout_filename = config_get("global", "debug log", filename); - - snprintfz(filename, FILENAME_MAX, "%s/error.log", netdata_configured_log_dir); - stderr_filename = config_get("global", "error log", filename); - - snprintfz(filename, FILENAME_MAX, "%s/access.log", netdata_configured_log_dir); - stdaccess_filename = config_get("global", "access log", filename); - } - - error_log_throttle_period_backup = - error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period); - setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1); - - error_log_errors_per_period = (unsigned long)config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period); - setenv("NETDATA_ERRORS_PER_PERIOD" , config_get("global", "errors to trigger flood protection", ""), 1); - - if(check_config) { - stdout_filename = stderr_filename = stdaccess_filename = "system"; - error_log_throttle_period = 0; - error_log_errors_per_period = 0; - } + log_init(); error_log_limit_unlimited(); - // -------------------------------------------------------------------- - - rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- - + // load stream.conf { - char hostnamebuf[HOSTNAME_MAX + 1]; - if(gethostname(hostnamebuf, HOSTNAME_MAX) == -1) - error("WARNING: Cannot get machine hostname."); - hostname = config_get("global", "hostname", hostnamebuf); - debug(D_OPTIONS, "hostname set to '%s'", hostname); - setenv("NETDATA_HOSTNAME", hostname, 1); - } - - // -------------------------------------------------------------------- - - rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); - if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { - error("Invalid history entries %d given. Defaulting to %d.", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); - rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; - } - else { - debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); - } - - // -------------------------------------------------------------------- - - rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); - if(rrd_update_every < 1 || rrd_update_every > 600) { - error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", rrd_update_every, UPDATE_EVERY_MAX); - rrd_update_every = UPDATE_EVERY; + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir); + appconfig_load(&stream_config, filename, 0); } - else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); - // let the plugins know the min update_every - { - char buf[16]; - snprintfz(buf, 15, "%d", rrd_update_every); - setenv("NETDATA_UPDATE_EVERY", buf, 1); - } // -------------------------------------------------------------------- + // setup process signals // block signals while initializing threads. // this causes the threads to block signals. @@ -724,7 +819,9 @@ int main(int argc, char **argv) { if(sigaction(SIGUSR2, &sa, NULL) == -1) error("Failed to change signal handler for SIGUSR2"); + // -------------------------------------------------------------------- + // get the required stack size of the threads of netdata i = pthread_attr_init(&attr); if(i != 0) @@ -736,30 +833,44 @@ int main(int argc, char **argv) { else debug(D_OPTIONS, "initial pthread stack size is %zu bytes", stacksize); - wanted_stacksize = (size_t)config_get_number("global", "pthread stack size", (long)stacksize); + wanted_stacksize = (size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)stacksize); + // -------------------------------------------------------------------- + // check which threads are enabled and initialize them for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; - if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); - if(st->enabled && st->init_routine) st->init_routine(); + if(st->config_name) + st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); + + if(st->enabled && st->init_routine) + st->init_routine(); } - // -------------------------------------------------------------------- + // -------------------------------------------------------------------- // get the user we should run + // IMPORTANT: this is required before web_files_uid() - user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); + if(getuid() == 0) { + user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER); + } + else { + struct passwd *passwd = getpwuid(getuid()); + user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:""); + } // IMPORTANT: these have to run once, while single threaded web_files_uid(); // IMPORTANT: web_files_uid() before web_files_gid() web_files_gid(); + // -------------------------------------------------------------------- + // create the listening sockets - if(!check_config) + if(web_server_mode != WEB_SERVER_MODE_NONE) create_listen_sockets(); } @@ -777,14 +888,16 @@ int main(int argc, char **argv) { } #endif /* NETDATA_INTERNAL_CHECKS */ + // fork, switch user, create pid file, set process priority if(become_daemon(dont_fork, user) == -1) fatal("Cannot daemonize myself."); info("netdata started on pid %d.", getpid()); + // ------------------------------------------------------------------------ - // get default pthread stack size + // set default pthread stack size - after we have forked if(stacksize < wanted_stacksize) { i = pthread_attr_setstacksize(&attr, wanted_stacksize); @@ -794,29 +907,19 @@ int main(int argc, char **argv) { debug(D_SYSTEM, "Successfully set pthread stacksize to %zu bytes", wanted_stacksize); } - // ------------------------------------------------------------------------ - // initialize rrd host - - rrdhost_init(hostname); // ------------------------------------------------------------------------ - // initialize the registry + // initialize rrd, registry, health, rrdpush, etc. - registry_init(); - - // ------------------------------------------------------------------------ - // initialize health monitoring + rrd_init(netdata_configured_hostname); - health_init(); - - if(check_config) - exit(1); // ------------------------------------------------------------------------ // enable log flood protection error_log_limit_reset(); + // ------------------------------------------------------------------------ // spawn the threads @@ -841,6 +944,7 @@ int main(int argc, char **argv) { info("netdata initialization completed. Enjoy real-time performance monitoring!"); + // ------------------------------------------------------------------------ // block signals while initializing threads. sigset_t sigset; diff --git a/src/plugin_checks.c b/src/plugin_checks.c index fcc542e6..3a0a83bd 100644 --- a/src/plugin_checks.c +++ b/src/plugin_checks.c @@ -11,23 +11,26 @@ void *checks_main(void *ptr) { if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); - usec_t usec = 0, susec = rrd_update_every * USEC_PER_SEC, loop_usec = 0, total_susec = 0; + usec_t usec = 0, susec = localhost->rrd_update_every * USEC_PER_SEC, loop_usec = 0, total_susec = 0; struct timeval now, last, loop; RRDSET *check1, *check2, *check3, *apps_cpu = NULL; - check1 = rrdset_create("netdata", "check1", NULL, "netdata", NULL, "Caller gives microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(check1, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE); - rrddim_add(check1, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL); + check1 = rrdset_create_localhost("netdata", "check1", NULL, "netdata", NULL, "Caller gives microseconds" + , "a million !", 99999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + rrddim_add(check1, "absolute", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(check1, "incremental", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - check2 = rrdset_create("netdata", "check2", NULL, "netdata", NULL, "Netdata calcs microseconds", "a million !", 99999, rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(check2, "absolute", NULL, -1, 1, RRDDIM_ABSOLUTE); - rrddim_add(check2, "incremental", NULL, 1, 1, RRDDIM_INCREMENTAL); + check2 = rrdset_create_localhost("netdata", "check2", NULL, "netdata", NULL, "Netdata calcs microseconds" + , "a million !", 99999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + rrddim_add(check2, "absolute", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(check2, "incremental", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - check3 = rrdset_create("netdata", "checkdt", NULL, "netdata", NULL, "Clock difference", "microseconds diff", 99999, rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(check3, "caller", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(check3, "netdata", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRDDIM_ABSOLUTE); + check3 = rrdset_create_localhost("netdata", "checkdt", NULL, "netdata", NULL, "Clock difference" + , "microseconds diff", 99999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + rrddim_add(check3, "caller", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(check3, "netdata", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(check3, "apps.plugin", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); now_realtime_timeval(&last); while(1) { @@ -39,8 +42,8 @@ void *checks_main(void *ptr) { usec = loop_usec - susec; debug(D_PROCNETDEV_LOOP, "CHECK: last loop took %llu usec (worked for %llu, sleeped for %llu).", loop_usec, usec, susec); - if(usec < (rrd_update_every * USEC_PER_SEC / 2ULL)) susec = (rrd_update_every * USEC_PER_SEC) - usec; - else susec = rrd_update_every * USEC_PER_SEC / 2ULL; + if(usec < (localhost->rrd_update_every * USEC_PER_SEC / 2ULL)) susec = (localhost->rrd_update_every * USEC_PER_SEC) - usec; + else susec = localhost->rrd_update_every * USEC_PER_SEC / 2ULL; // -------------------------------------------------------------------- // Calculate loop time @@ -68,7 +71,7 @@ void *checks_main(void *ptr) { // -------------------------------------------------------------------- // check chart 3 - if(!apps_cpu) apps_cpu = rrdset_find("apps.cpu"); + if(!apps_cpu) apps_cpu = rrdset_find_localhost("apps.cpu"); if(check3->counter_done) rrdset_next_usec(check3, loop_usec); now_realtime_timeval(&loop); rrddim_set(check3, "caller", (long long) dt_usec(&loop, &check1->last_collected_time)); diff --git a/src/plugin_freebsd.c b/src/plugin_freebsd.c index 4fef148a..3490e70e 100644 --- a/src/plugin_freebsd.c +++ b/src/plugin_freebsd.c @@ -18,7 +18,7 @@ void *freebsd_main(void *ptr) { // keep track of the time each module was called unsigned long long sutime_freebsd_sysctl = 0ULL; - usec_t step = rrd_update_every * USEC_PER_SEC; + usec_t step = localhost->rrd_update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); for(;;) { @@ -30,7 +30,7 @@ void *freebsd_main(void *ptr) { if(!vdo_freebsd_sysctl) { debug(D_PROCNETDEV_LOOP, "FREEBSD: calling do_freebsd_sysctl()."); - vdo_freebsd_sysctl = do_freebsd_sysctl(rrd_update_every, hb_dt); + vdo_freebsd_sysctl = do_freebsd_sysctl(localhost->rrd_update_every, hb_dt); } if(unlikely(netdata_exit)) break; diff --git a/src/plugin_idlejitter.c b/src/plugin_idlejitter.c index 2d08e02d..2ed78160 100644 --- a/src/plugin_idlejitter.c +++ b/src/plugin_idlejitter.c @@ -19,10 +19,11 @@ void *cpuidlejitter_main(void *ptr) { sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS; } - RRDSET *st = rrdset_find("system.idlejitter"); + RRDSET *st = rrdset_find_localhost("system.idlejitter"); if(!st) { - st = rrdset_create("system", "idlejitter", NULL, "processes", NULL, "CPU Idle Jitter", "microseconds lost/s", 9999, rrd_update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "jitter", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "idlejitter", NULL, "processes", NULL, "CPU Idle Jitter" + , "microseconds lost/s", 9999, localhost->rrd_update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "jitter", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } struct timeval before, after; @@ -30,7 +31,9 @@ void *cpuidlejitter_main(void *ptr) { for(counter = 0; 1 ;counter++) { usec_t usec = 0, susec = 0; - while(susec < (rrd_update_every * USEC_PER_SEC)) { + if(netdata_exit) break; + + while(susec < (localhost->rrd_update_every * USEC_PER_SEC)) { now_monotonic_timeval(&before); sleep_usec(sleep_ms * 1000); diff --git a/src/plugin_macos.c b/src/plugin_macos.c index 54965c5d..4e84a084 100644 --- a/src/plugin_macos.c +++ b/src/plugin_macos.c @@ -22,7 +22,7 @@ void *macos_main(void *ptr) { unsigned long long sutime_macos_mach_smi = 0ULL; unsigned long long sutime_macos_iokit = 0ULL; - usec_t step = rrd_update_every * USEC_PER_SEC; + usec_t step = localhost->rrd_update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); for(;;) { @@ -34,19 +34,19 @@ void *macos_main(void *ptr) { if(!vdo_macos_sysctl) { debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_sysctl()."); - vdo_macos_sysctl = do_macos_sysctl(rrd_update_every, hb_dt); + vdo_macos_sysctl = do_macos_sysctl(localhost->rrd_update_every, hb_dt); } if(unlikely(netdata_exit)) break; if(!vdo_macos_mach_smi) { debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_mach_smi()."); - vdo_macos_mach_smi = do_macos_mach_smi(rrd_update_every, hb_dt); + vdo_macos_mach_smi = do_macos_mach_smi(localhost->rrd_update_every, hb_dt); } if(unlikely(netdata_exit)) break; if(!vdo_macos_iokit) { debug(D_PROCNETDEV_LOOP, "MACOS: calling do_macos_iokit()."); - vdo_macos_iokit = do_macos_iokit(rrd_update_every, hb_dt); + vdo_macos_iokit = do_macos_iokit(localhost->rrd_update_every, hb_dt); } if(unlikely(netdata_exit)) break; diff --git a/src/plugin_nfacct.c b/src/plugin_nfacct.c index 7aae33c0..a9e6ebc9 100644 --- a/src/plugin_nfacct.c +++ b/src/plugin_nfacct.c @@ -128,8 +128,8 @@ void *nfacct_main(void *ptr) { usec = dt_usec(&now, &last) - susec; debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec); - if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec; - else susec = rrd_update_every * 1000000ULL / 2ULL; + if(usec < (default_rrd_update_every * 1000000ULL / 2ULL)) susec = (default_rrd_update_every * 1000000ULL) - usec; + else susec = default_rrd_update_every * 1000000ULL / 2ULL; // -------------------------------------------------------------------- @@ -139,17 +139,17 @@ void *nfacct_main(void *ptr) { st = rrdset_find_bytype("netfilter", "nfacct_packets"); if(!st) { - st = rrdset_create("netfilter", "nfacct_packets", NULL, "nfacct", NULL, "Netfilter Accounting Packets", "packets/s", 3206, rrd_update_every, RRDSET_TYPE_STACKED); + st = rrdset_create("netfilter", "nfacct_packets", NULL, "nfacct", NULL, "Netfilter Accounting Packets", "packets/s", 3206, default_rrd_update_every, RRDSET_TYPE_STACKED); for(i = 0; i < nfacct_list->len ; i++) - rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL); + rrddim_add(st, nfacct_list->data[i].name, NULL, 1, default_rrd_update_every, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); for(i = 0; i < nfacct_list->len ; i++) { RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name); - if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, rrd_update_every, RRDDIM_INCREMENTAL); + if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, default_rrd_update_every, RRD_ALGORITHM_INCREMENTAL); if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].pkts); } @@ -159,17 +159,17 @@ void *nfacct_main(void *ptr) { st = rrdset_find_bytype("netfilter", "nfacct_bytes"); if(!st) { - st = rrdset_create("netfilter", "nfacct_bytes", NULL, "nfacct", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 3207, rrd_update_every, RRDSET_TYPE_STACKED); + st = rrdset_create("netfilter", "nfacct_bytes", NULL, "nfacct", NULL, "Netfilter Accounting Bandwidth", "kilobytes/s", 3207, default_rrd_update_every, RRDSET_TYPE_STACKED); for(i = 0; i < nfacct_list->len ; i++) - rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL); + rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * default_rrd_update_every, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); for(i = 0; i < nfacct_list->len ; i++) { RRDDIM *rd = rrddim_find(st, nfacct_list->data[i].name); - if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL); + if(!rd) rd = rrddim_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * default_rrd_update_every, RRD_ALGORITHM_INCREMENTAL); if(rd) rrddim_set_by_pointer(st, rd, nfacct_list->data[i].bytes); } diff --git a/src/plugin_proc.c b/src/plugin_proc.c index 215925a5..2ca77491 100644 --- a/src/plugin_proc.c +++ b/src/plugin_proc.c @@ -79,7 +79,7 @@ void *proc_main(void *ptr) { pm->rd = NULL; } - usec_t step = rrd_update_every * USEC_PER_SEC; + usec_t step = localhost->rrd_update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); @@ -97,7 +97,7 @@ void *proc_main(void *ptr) { debug(D_PROCNETDEV_LOOP, "PROC calling %s.", pm->name); - pm->enabled = !pm->func(rrd_update_every, hb_dt); + pm->enabled = !pm->func(localhost->rrd_update_every, hb_dt); pm->duration = heartbeat_dt_usec(&hb) - duration; duration += pm->duration; @@ -112,16 +112,18 @@ void *proc_main(void *ptr) { static RRDSET *st = NULL; if(unlikely(!st)) { - st = rrdset_find_bytype("netdata", "plugin_proc_modules"); + st = rrdset_find_bytype_localhost("netdata", "plugin_proc_modules"); if(!st) { - st = rrdset_create("netdata", "plugin_proc_modules", NULL, "proc", NULL, "NetData Proc Plugin Modules Durations", "milliseconds/run", 132001, rrd_update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("netdata", "plugin_proc_modules", NULL, "proc", NULL + , "NetData Proc Plugin Modules Durations", "milliseconds/run", 132001 + , localhost->rrd_update_every, RRDSET_TYPE_STACKED); for(i = 0 ; proc_modules[i].name ;i++) { struct proc_module *pm = &proc_modules[i]; if(unlikely(!pm->enabled)) continue; - pm->rd = rrddim_add(st, pm->dim, NULL, 1, 1000, RRDDIM_ABSOLUTE); + pm->rd = rrddim_add(st, pm->dim, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } } } diff --git a/src/plugin_proc_diskspace.c b/src/plugin_proc_diskspace.c index 689efe7c..6657ffe7 100644 --- a/src/plugin_proc_diskspace.c +++ b/src/plugin_proc_diskspace.c @@ -1,6 +1,8 @@ #include "common.h" #define DELAULT_EXLUDED_PATHS "/proc/* /sys/* /var/run/user/* /run/user/*" +#define DEFAULT_EXCLUDED_FILESYSTEMS "" +#define CONFIG_SECTION_DISKSPACE "plugin:proc:diskspace" static struct mountinfo *disk_mountinfo_root = NULL; static int check_for_new_mountpoints_every = 15; @@ -14,7 +16,7 @@ static inline void mountinfo_reload(int force) { mountinfo_free(disk_mountinfo_root); // re-read mountinfo in case something changed - disk_mountinfo_root = mountinfo_read(1); + disk_mountinfo_root = mountinfo_read(0); last_loaded = now; } @@ -25,6 +27,7 @@ static inline void mountinfo_reload(int force) { struct mount_point_metadata { int do_space; int do_inodes; + int shown_error; size_t collected; // the number of times this has been collected @@ -45,22 +48,28 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { static DICTIONARY *mount_points = NULL; static SIMPLE_PATTERN *excluded_mountpoints = NULL; + static SIMPLE_PATTERN *excluded_filesystems = NULL; int do_space, do_inodes; if(unlikely(!mount_points)) { - const char *s; SIMPLE_PREFIX_MODE mode = SIMPLE_PATTERN_EXACT; - if(config_exists("plugin:proc:/proc/diskstats", "exclude space metrics on paths") && !config_exists("plugin:proc:diskspace", "exclude space metrics on paths")) { - // the config exists in the old section - s = config_get("plugin:proc:/proc/diskstats", "exclude space metrics on paths", DELAULT_EXLUDED_PATHS); + if(config_move("plugin:proc:/proc/diskstats", "exclude space metrics on paths", CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths") != -1) { + // old configuration, enable backwards compatibility mode = SIMPLE_PATTERN_PREFIX; } - else - s = config_get("plugin:proc:diskspace", "exclude space metrics on paths", DELAULT_EXLUDED_PATHS); + + excluded_mountpoints = simple_pattern_create( + config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths", DELAULT_EXLUDED_PATHS), + mode + ); + + excluded_filesystems = simple_pattern_create( + config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on filesystems", DEFAULT_EXCLUDED_FILESYSTEMS), + SIMPLE_PATTERN_EXACT + ); mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); - excluded_mountpoints = simple_pattern_create(s, mode); } struct mount_point_metadata *m = dictionary_get(mount_points, mi->mount_point); @@ -68,12 +77,17 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { char var_name[4096 + 1]; snprintfz(var_name, 4096, "plugin:proc:diskspace:%s", mi->mount_point); - int def_space = config_get_boolean_ondemand("plugin:proc:diskspace", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND); - int def_inodes = config_get_boolean_ondemand("plugin:proc:diskspace", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND); + int def_space = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "space usage for all disks", CONFIG_BOOLEAN_AUTO); + int def_inodes = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO); if(unlikely(simple_pattern_matches(excluded_mountpoints, mi->mount_point))) { - def_space = CONFIG_ONDEMAND_NO; - def_inodes = CONFIG_ONDEMAND_NO; + def_space = CONFIG_BOOLEAN_NO; + def_inodes = CONFIG_BOOLEAN_NO; + } + + if(unlikely(simple_pattern_matches(excluded_filesystems, mi->filesystem))) { + def_space = CONFIG_BOOLEAN_NO; + def_inodes = CONFIG_BOOLEAN_NO; } do_space = config_get_boolean_ondemand(var_name, "space usage", def_space); @@ -82,6 +96,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { struct mount_point_metadata mp = { .do_space = do_space, .do_inodes = do_inodes, + .shown_error = 0, .collected = 0, @@ -98,12 +113,8 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { m = dictionary_set(mount_points, mi->mount_point, &mp, sizeof(struct mount_point_metadata)); } - else { - do_space = m->do_space; - do_inodes = m->do_inodes; - } - if(unlikely(do_space == CONFIG_ONDEMAND_NO && do_inodes == CONFIG_ONDEMAND_NO)) + if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO)) return; if(unlikely(mi->flags & MOUNTINFO_READONLY && !m->collected)) @@ -111,9 +122,18 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { struct statvfs buff_statvfs; if (statvfs(mi->mount_point, &buff_statvfs) < 0) { - error("Failed statvfs() for '%s' (disk '%s')", mi->mount_point, disk); + if(!m->shown_error) { + error("Failed statvfs() for '%s' (disk '%s', filesystem '%s', root '%s')" + , mi->mount_point + , disk + , mi->filesystem?mi->filesystem:"" + , mi->root?mi->root:"" + ); + m->shown_error = 1; + } return; } + m->shown_error = 0; // logic found at get_fs_usage() in coreutils unsigned long bsize = (buff_statvfs.f_frsize) ? buff_statvfs.f_frsize : buff_statvfs.f_bsize; @@ -150,19 +170,30 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { int rendered = 0; - if(do_space == CONFIG_ONDEMAND_YES || (do_space == CONFIG_ONDEMAND_ONDEMAND && (bavail || breserved_root || bused))) { + if(m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (bavail || breserved_root || bused))) { if(unlikely(!m->st_space)) { - m->do_space = CONFIG_ONDEMAND_YES; - m->st_space = rrdset_find_bytype("disk_space", disk); + m->do_space = CONFIG_BOOLEAN_YES; + m->st_space = rrdset_find_bytype_localhost("disk_space", disk); if(unlikely(!m->st_space)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mi->mount_source); - m->st_space = rrdset_create("disk_space", disk, NULL, family, "disk.space", title, "GB", 2023, update_every, RRDSET_TYPE_STACKED); + m->st_space = rrdset_create_localhost( + "disk_space" + , disk + , NULL + , family + , "disk.space" + , title + , "GB" + , 2023 + , update_every + , RRDSET_TYPE_STACKED + ); } - m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL, bsize, 1024 * 1024 * 1024, RRDDIM_ABSOLUTE); - m->rd_space_used = rrddim_add(m->st_space, "used", NULL, bsize, 1024 * 1024 * 1024, RRDDIM_ABSOLUTE); - m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", bsize, 1024 * 1024 * 1024, RRDDIM_ABSOLUTE); + m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + m->rd_space_used = rrddim_add(m->st_space, "used", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(m->st_space); @@ -177,19 +208,30 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { // -------------------------------------------------------------------------- - if(do_inodes == CONFIG_ONDEMAND_YES || (do_inodes == CONFIG_ONDEMAND_ONDEMAND && (favail || freserved_root || fused))) { + if(m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (favail || freserved_root || fused))) { if(unlikely(!m->st_inodes)) { - m->do_inodes = CONFIG_ONDEMAND_YES; - m->st_inodes = rrdset_find_bytype("disk_inodes", disk); + m->do_inodes = CONFIG_BOOLEAN_YES; + m->st_inodes = rrdset_find_bytype_localhost("disk_inodes", disk); if(unlikely(!m->st_inodes)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mi->mount_source); - m->st_inodes = rrdset_create("disk_inodes", disk, NULL, family, "disk.inodes", title, "Inodes", 2024, update_every, RRDSET_TYPE_STACKED); + m->st_inodes = rrdset_create_localhost( + "disk_inodes" + , disk + , NULL + , family + , "disk.inodes" + , title + , "Inodes" + , 2024 + , update_every + , RRDSET_TYPE_STACKED + ); } - m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRDDIM_ABSOLUTE); - m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRDDIM_ABSOLUTE); - m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRDDIM_ABSOLUTE); + m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(m->st_inodes); @@ -221,11 +263,11 @@ void *proc_diskspace_main(void *ptr) { int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1); - int update_every = (int)config_get_number("plugin:proc:diskspace", "update every", rrd_update_every); - if(update_every < rrd_update_every) - update_every = rrd_update_every; + int update_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "update every", localhost->rrd_update_every); + if(update_every < localhost->rrd_update_every) + update_every = localhost->rrd_update_every; - check_for_new_mountpoints_every = (int)config_get_number("plugin:proc:diskspace", "check for new mount points every", check_for_new_mountpoints_every); + check_for_new_mountpoints_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "check for new mount points every", check_for_new_mountpoints_every); if(check_for_new_mountpoints_every < update_every) check_for_new_mountpoints_every = update_every; @@ -272,13 +314,23 @@ void *proc_diskspace_main(void *ptr) { getrusage(RUSAGE_THREAD, &thread); if(!stcpu_thread) { - stcpu_thread = rrdset_find("netdata.plugin_diskspace"); - if(!stcpu_thread) stcpu_thread = rrdset_create("netdata", "plugin_diskspace", NULL, "diskspace", NULL - , "NetData Disk Space Plugin CPU usage", "milliseconds/s", 132020 - , update_every, RRDSET_TYPE_STACKED); - - rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); + stcpu_thread = rrdset_find_localhost("netdata.plugin_diskspace"); + if(!stcpu_thread) + stcpu_thread = rrdset_create_localhost( + "netdata" + , "plugin_diskspace" + , NULL + , "diskspace" + , NULL + , "NetData Disk Space Plugin CPU usage" + , "milliseconds/s" + , 132020 + , update_every + , RRDSET_TYPE_STACKED + ); + + rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); @@ -290,12 +342,22 @@ void *proc_diskspace_main(void *ptr) { // ---------------------------------------------------------------- if(!st_duration) { - st_duration = rrdset_find("netdata.plugin_diskspace_dt"); - if(!st_duration) st_duration = rrdset_create("netdata", "plugin_diskspace_dt", NULL, "diskspace", NULL - , "NetData Disk Space Plugin Duration", "milliseconds/run", 132021 - , update_every, RRDSET_TYPE_AREA); - - rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRDDIM_ABSOLUTE); + st_duration = rrdset_find_localhost("netdata.plugin_diskspace_dt"); + if(!st_duration) + st_duration = rrdset_create_localhost( + "netdata" + , "plugin_diskspace_dt" + , NULL + , "diskspace" + , NULL + , "NetData Disk Space Plugin Duration" + , "milliseconds/run" + , 132021 + , update_every + , RRDSET_TYPE_AREA + ); + + rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st_duration); diff --git a/src/plugin_tc.c b/src/plugin_tc.c index 3cb64505..35763d31 100644 --- a/src/plugin_tc.c +++ b/src/plugin_tc.c @@ -190,13 +190,13 @@ static inline void tc_device_commit(struct tc_device *d) { static int enable_new_interfaces = -1, enable_bytes = -1, enable_packets = -1, enable_dropped = -1, enable_tokens = -1, enable_ctokens = -1, enabled_all_classes_qdiscs = -1; if(unlikely(enable_new_interfaces == -1)) { - enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_YES); - enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - enable_tokens = config_get_boolean_ondemand("plugin:tc", "enable tokens charts for all interfaces", CONFIG_ONDEMAND_NO); - enable_ctokens = config_get_boolean_ondemand("plugin:tc", "enable ctokens charts for all interfaces", CONFIG_ONDEMAND_NO); - enabled_all_classes_qdiscs = config_get_boolean_ondemand("plugin:tc", "enable show all classes and qdiscs for all interfaces", CONFIG_ONDEMAND_NO); + enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_YES); + enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_BOOLEAN_AUTO); + enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_BOOLEAN_AUTO); + enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_BOOLEAN_AUTO); + enable_tokens = config_get_boolean_ondemand("plugin:tc", "enable tokens charts for all interfaces", CONFIG_BOOLEAN_NO); + enable_ctokens = config_get_boolean_ondemand("plugin:tc", "enable ctokens charts for all interfaces", CONFIG_BOOLEAN_NO); + enabled_all_classes_qdiscs = config_get_boolean_ondemand("plugin:tc", "enable show all classes and qdiscs for all interfaces", CONFIG_BOOLEAN_NO); } if(unlikely(d->enabled == (char)-1)) { @@ -370,11 +370,15 @@ static inline void tc_device_commit(struct tc_device *d) { // -------------------------------------------------------------------- // bytes - if(d->enabled_bytes == CONFIG_ONDEMAND_YES || (d->enabled_bytes == CONFIG_ONDEMAND_ONDEMAND && bytes_sum)) { - d->enabled_bytes = CONFIG_ONDEMAND_YES; + if(d->enabled_bytes == CONFIG_BOOLEAN_YES || (d->enabled_bytes == CONFIG_BOOLEAN_AUTO && bytes_sum)) { + d->enabled_bytes = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_bytes)) - d->st_bytes = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, RRD_TYPE_TC ".qos", "Class Usage", "kilobits/s", 7000, rrd_update_every, d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED); + d->st_bytes = rrdset_create_localhost(RRD_TYPE_TC, d->id, d->name ? d->name : d->id + , d->family ? d->family : d->id, RRD_TYPE_TC ".qos", "Class Usage" + , "kilobits/s", 7000, localhost->rrd_update_every + , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE + : RRDSET_TYPE_STACKED); else { rrdset_next(d->st_bytes); @@ -388,7 +392,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_bytes)) - c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL); + c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, 1024, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_bytes, c->rd_bytes, c->name); @@ -400,8 +404,8 @@ static inline void tc_device_commit(struct tc_device *d) { // -------------------------------------------------------------------- // packets - if(d->enabled_packets == CONFIG_ONDEMAND_YES || (d->enabled_packets == CONFIG_ONDEMAND_ONDEMAND && packets_sum)) { - d->enabled_packets = CONFIG_ONDEMAND_YES; + if(d->enabled_packets == CONFIG_BOOLEAN_YES || (d->enabled_packets == CONFIG_BOOLEAN_AUTO && packets_sum)) { + d->enabled_packets = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_packets)) { char id[RRD_ID_LENGTH_MAX + 1]; @@ -409,7 +413,10 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id); - d->st_packets = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010, rrd_update_every, d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED); + d->st_packets = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010 + , localhost->rrd_update_every, d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE + : RRDSET_TYPE_STACKED); } else { rrdset_next(d->st_packets); @@ -428,7 +435,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_packets)) - c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL); + c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_packets, c->rd_packets, c->name); @@ -440,8 +447,8 @@ static inline void tc_device_commit(struct tc_device *d) { // -------------------------------------------------------------------- // dropped - if(d->enabled_dropped == CONFIG_ONDEMAND_YES || (d->enabled_dropped == CONFIG_ONDEMAND_ONDEMAND && dropped_sum)) { - d->enabled_dropped = CONFIG_ONDEMAND_YES; + if(d->enabled_dropped == CONFIG_BOOLEAN_YES || (d->enabled_dropped == CONFIG_BOOLEAN_AUTO && dropped_sum)) { + d->enabled_dropped = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_dropped)) { char id[RRD_ID_LENGTH_MAX + 1]; @@ -449,7 +456,11 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id); - d->st_dropped = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s", 7020, rrd_update_every, d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED); + d->st_dropped = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s" + , 7020, localhost->rrd_update_every + , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE + : RRDSET_TYPE_STACKED); } else { rrdset_next(d->st_dropped); @@ -468,7 +479,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_dropped)) - c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL); + c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_dropped, c->rd_dropped, c->name); @@ -480,8 +491,8 @@ static inline void tc_device_commit(struct tc_device *d) { // -------------------------------------------------------------------- // tokens - if(d->enabled_tokens == CONFIG_ONDEMAND_YES || (d->enabled_tokens == CONFIG_ONDEMAND_ONDEMAND && tokens_sum)) { - d->enabled_tokens = CONFIG_ONDEMAND_YES; + if(d->enabled_tokens == CONFIG_BOOLEAN_YES || (d->enabled_tokens == CONFIG_BOOLEAN_AUTO && tokens_sum)) { + d->enabled_tokens = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_tokens)) { char id[RRD_ID_LENGTH_MAX + 1]; @@ -489,7 +500,9 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_tokens", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id); - d->st_tokens = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_tokens", "Class Tokens", "tokens", 7030, rrd_update_every, RRDSET_TYPE_LINE); + d->st_tokens = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_tokens", "Class Tokens", "tokens", 7030 + , localhost->rrd_update_every, RRDSET_TYPE_LINE); } else { rrdset_next(d->st_tokens); @@ -508,7 +521,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_tokens)) { - c->rd_tokens = rrddim_add(d->st_tokens, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_ABSOLUTE); + c->rd_tokens = rrddim_add(d->st_tokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else if(unlikely(c->name_updated)) rrddim_set_name(d->st_tokens, c->rd_tokens, c->name); @@ -521,8 +534,8 @@ static inline void tc_device_commit(struct tc_device *d) { // -------------------------------------------------------------------- // ctokens - if(d->enabled_ctokens == CONFIG_ONDEMAND_YES || (d->enabled_ctokens == CONFIG_ONDEMAND_ONDEMAND && ctokens_sum)) { - d->enabled_ctokens = CONFIG_ONDEMAND_YES; + if(d->enabled_ctokens == CONFIG_BOOLEAN_YES || (d->enabled_ctokens == CONFIG_BOOLEAN_AUTO && ctokens_sum)) { + d->enabled_ctokens = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_ctokens)) { char id[RRD_ID_LENGTH_MAX + 1]; @@ -530,7 +543,9 @@ static inline void tc_device_commit(struct tc_device *d) { snprintfz(id, RRD_ID_LENGTH_MAX, "%s_ctokens", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id); - d->st_ctokens = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_ctokens", "Class cTokens", "ctokens", 7040, rrd_update_every, RRDSET_TYPE_LINE); + d->st_ctokens = rrdset_create_localhost(RRD_TYPE_TC, id, name, d->family ? d->family : d->id + , RRD_TYPE_TC ".qos_ctokens", "Class cTokens", "ctokens", 7040 + , localhost->rrd_update_every, RRDSET_TYPE_LINE); } else { debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", d->name?d->name:d->id); @@ -550,7 +565,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_ctokens)) - c->rd_ctokens = rrddim_add(d->st_ctokens, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_ABSOLUTE); + c->rd_ctokens = rrddim_add(d->st_ctokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_ctokens, c->rd_ctokens, c->name); @@ -792,7 +807,7 @@ void *tc_main(void *ptr) { struct tc_device *device = NULL; struct tc_class *class = NULL; - snprintfz(buffer, TC_LINE_MAX, "exec %s %d", tc_script, rrd_update_every); + snprintfz(buffer, TC_LINE_MAX, "exec %s %d", tc_script, localhost->rrd_update_every); debug(D_TC_LOOP, "executing '%s'", buffer); fp = mypopen(buffer, (pid_t *)&tc_child_pid); @@ -974,11 +989,13 @@ void *tc_main(void *ptr) { // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]); getrusage(RUSAGE_THREAD, &thread); - if(unlikely(!stcpu)) stcpu = rrdset_find("netdata.plugin_tc_cpu"); + if(unlikely(!stcpu)) stcpu = rrdset_find_localhost("netdata.plugin_tc_cpu"); if(unlikely(!stcpu)) { - stcpu = rrdset_create("netdata", "plugin_tc_cpu", NULL, "tc.helper", NULL, "NetData TC CPU usage", "milliseconds/s", 135000, rrd_update_every, RRDSET_TYPE_STACKED); - rrddim_add(stcpu, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rrddim_add(stcpu, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); + stcpu = rrdset_create_localhost("netdata", "plugin_tc_cpu", NULL, "tc.helper", NULL + , "NetData TC CPU usage", "milliseconds/s", 135000, localhost->rrd_update_every + , RRDSET_TYPE_STACKED); + rrddim_add(stcpu, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(stcpu, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu); @@ -986,10 +1003,12 @@ void *tc_main(void *ptr) { rrddim_set(stcpu, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(stcpu); - if(unlikely(!sttime)) stcpu = rrdset_find("netdata.plugin_tc_time"); + if(unlikely(!sttime)) stcpu = rrdset_find_localhost("netdata.plugin_tc_time"); if(unlikely(!sttime)) { - sttime = rrdset_create("netdata", "plugin_tc_time", NULL, "tc.helper", NULL, "NetData TC script execution", "milliseconds/run", 135001, rrd_update_every, RRDSET_TYPE_AREA); - rrddim_add(sttime, "run_time", "run time", 1, 1, RRDDIM_ABSOLUTE); + sttime = rrdset_create_localhost("netdata", "plugin_tc_time", NULL, "tc.helper", NULL + , "NetData TC script execution", "milliseconds/run", 135001 + , localhost->rrd_update_every, RRDSET_TYPE_AREA); + rrddim_add(sttime, "run_time", "run time", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(sttime); @@ -1037,7 +1056,7 @@ void *tc_main(void *ptr) { goto cleanup; } - sleep((unsigned int) rrd_update_every); + sleep((unsigned int) localhost->rrd_update_every); } cleanup: diff --git a/src/plugins_d.c b/src/plugins_d.c index 9a027cb2..7fa19eaf 100644 --- a/src/plugins_d.c +++ b/src/plugins_d.c @@ -83,302 +83,315 @@ static int pluginsd_split_words(char *str, char **words, int max_words) { return i; } +inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations) { + int enabled = cd->enabled; -void *pluginsd_worker_thread(void *arg) -{ - struct plugind *cd = (struct plugind *)arg; - cd->obsolete = 0; + if(!fp || !enabled) { + cd->enabled = 0; + return 0; + } - char line[PLUGINSD_LINE_MAX + 1]; + size_t count = 0; -#ifdef DETACH_PLUGINS_FROM_NETDATA - usec_t usec = 0, susec = 0; - struct timeval last = {0, 0} , now = {0, 0}; -#endif + char line[PLUGINSD_LINE_MAX + 1]; char *words[MAX_WORDS] = { NULL }; + /* uint32_t HOST_HASH = simple_hash("HOST"); */ uint32_t BEGIN_HASH = simple_hash("BEGIN"); uint32_t END_HASH = simple_hash("END"); uint32_t FLUSH_HASH = simple_hash("FLUSH"); uint32_t CHART_HASH = simple_hash("CHART"); uint32_t DIMENSION_HASH = simple_hash("DIMENSION"); uint32_t DISABLE_HASH = simple_hash("DISABLE"); -#ifdef DETACH_PLUGINS_FROM_NETDATA - uint32_t MYPID_HASH = simple_hash("MYPID"); - uint32_t STOPPING_WAKE_ME_UP_PLEASE_HASH = simple_hash("STOPPING_WAKE_ME_UP_PLEASE"); -#endif - size_t count = 0; + RRDSET *st = NULL; + uint32_t hash; - for(;;) { + errno = 0; + clearerr(fp); + + if(unlikely(fileno(fp) == -1)) { + error("PLUGINSD: %s: file is not a valid stream.", cd->fullfilename); + goto cleanup; + } + + while(!ferror(fp)) { if(unlikely(netdata_exit)) break; - FILE *fp = mypopen(cd->cmd, &cd->pid); - if(unlikely(!fp)) { - error("Cannot popen(\"%s\", \"r\").", cd->cmd); + char *r = fgets(line, PLUGINSD_LINE_MAX, fp); + if(unlikely(!r)) { + error("PLUGINSD: %s : read failed.", cd->fullfilename); break; } - info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid); + if(unlikely(netdata_exit)) break; - RRDSET *st = NULL; - uint32_t hash; + line[PLUGINSD_LINE_MAX] = '\0'; - while(likely(fgets(line, PLUGINSD_LINE_MAX, fp) != NULL)) { - if(unlikely(netdata_exit)) break; + // debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line); - line[PLUGINSD_LINE_MAX] = '\0'; + int w = pluginsd_split_words(line, words, MAX_WORDS); + char *s = words[0]; + if(unlikely(!s || !*s || !w)) { + // debug(D_PLUGINSD, "PLUGINSD: empty line"); + continue; + } - // debug(D_PLUGINSD, "PLUGINSD: %s: %s", cd->filename, line); + // debug(D_PLUGINSD, "PLUGINSD: words 0='%s' 1='%s' 2='%s' 3='%s' 4='%s' 5='%s' 6='%s' 7='%s' 8='%s' 9='%s'", words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]); - int w = pluginsd_split_words(line, words, MAX_WORDS); - char *s = words[0]; - if(unlikely(!s || !*s || !w)) { - // debug(D_PLUGINSD, "PLUGINSD: empty line"); - continue; - } + if(likely(!simple_hash_strcmp(s, "SET", &hash))) { + char *dimension = words[1]; + char *value = words[2]; - // debug(D_PLUGINSD, "PLUGINSD: words 0='%s' 1='%s' 2='%s' 3='%s' 4='%s' 5='%s' 6='%s' 7='%s' 8='%s' 9='%s'", words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]); + if(unlikely(!dimension || !*dimension)) { + error("PLUGINSD: '%s' is requesting a SET on chart '%s' of host '%s', without a dimension. Disabling it.", cd->fullfilename, st->id, host->hostname); + enabled = 0; + break; + } - if(likely(!simple_hash_strcmp(s, "SET", &hash))) { - char *dimension = words[1]; - char *value = words[2]; + if(unlikely(!value || !*value)) value = NULL; - if(unlikely(!dimension || !*dimension)) { - error("PLUGINSD: '%s' is requesting a SET on chart '%s', without a dimension. Disabling it.", cd->fullfilename, st->id); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } + if(unlikely(!st)) { + error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s on host '%s', without a BEGIN. Disabling it.", cd->fullfilename, dimension, value?value:"", host->hostname); + enabled = 0; + break; + } - if(unlikely(!value || !*value)) value = NULL; + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value?value:""); - if(unlikely(!st)) { - error("PLUGINSD: '%s' is requesting a SET on dimension %s with value %s, without a BEGIN. Disabling it.", cd->fullfilename, dimension, value?value:""); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } - - if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is setting dimension %s/%s to %s", cd->fullfilename, st->id, dimension, value?value:""); + if(value) rrddim_set(st, dimension, strtoll(value, NULL, 0)); + } + else if(likely(hash == BEGIN_HASH && !strcmp(s, "BEGIN"))) { + char *id = words[1]; + char *microseconds_txt = words[2]; - if(value) rrddim_set(st, dimension, strtoll(value, NULL, 0)); + if(unlikely(!id)) { + error("PLUGINSD: '%s' is requesting a BEGIN without a chart id for host '%s'. Disabling it.", cd->fullfilename, host->hostname); + enabled = 0; + break; } - else if(likely(hash == BEGIN_HASH && !strcmp(s, "BEGIN"))) { - char *id = words[1]; - char *microseconds_txt = words[2]; - if(unlikely(!id)) { - error("PLUGINSD: '%s' is requesting a BEGIN without a chart id. Disabling it.", cd->fullfilename); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } + st = rrdset_find(host, id); + if(unlikely(!st)) { + error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist on host '%s'. Disabling it.", cd->fullfilename, id, host->hostname); + enabled = 0; + break; + } - st = rrdset_find(id); - if(unlikely(!st)) { - error("PLUGINSD: '%s' is requesting a BEGIN on chart '%s', which does not exist. Disabling it.", cd->fullfilename, id); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } + if(likely(st->counter_done)) { + usec_t microseconds = 0; + if(microseconds_txt && *microseconds_txt) microseconds = str2ull(microseconds_txt); - if(likely(st->counter_done)) { - usec_t microseconds = 0; - if(microseconds_txt && *microseconds_txt) microseconds = str2ull(microseconds_txt); - if(microseconds) rrdset_next_usec(st, microseconds); - else rrdset_next(st); + if(likely(microseconds)) { + if(trust_durations) + rrdset_next_usec_unfiltered(st, microseconds); + else + rrdset_next_usec(st, microseconds); } + else rrdset_next(st); } - else if(likely(hash == END_HASH && !strcmp(s, "END"))) { - if(unlikely(!st)) { - error("PLUGINSD: '%s' is requesting an END, without a BEGIN. Disabling it.", cd->fullfilename); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } + } + else if(likely(hash == END_HASH && !strcmp(s, "END"))) { + if(unlikely(!st)) { + error("PLUGINSD: '%s' is requesting an END, without a BEGIN on host '%s'. Disabling it.", cd->fullfilename, host->hostname); + enabled = 0; + break; + } + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting an END on chart %s", cd->fullfilename, st->id); - if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting an END on chart %s", cd->fullfilename, st->id); + rrdset_done(st); + st = NULL; - rrdset_done(st); - st = NULL; + count++; + } +/* else if(likely(hash == HOST_HASH && !strcmp(s, "HOST"))) { + char *guid = words[1]; + char *hostname = words[2]; - count++; + if(unlikely(!guid || !*guid)) { + error("PLUGINSD: '%s' is requesting HOST with guid '%s' and hostname '%s', without a guid. Disabling it.", cd->fullfilename, guid?guid:"", hostname?hostname:""); + enabled = 0; + break; } - else if(likely(hash == FLUSH_HASH && !strcmp(s, "FLUSH"))) { - debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename); - st = NULL; + if(unlikely(!hostname || !*hostname)) { + error("PLUGINSD: '%s' is requesting HOST with guid '%s' and hostname '%s', without a hostname. Disabling it.", cd->fullfilename, guid?guid:"", hostname?hostname:""); + enabled = 0; + break; } - else if(likely(hash == CHART_HASH && !strcmp(s, "CHART"))) { - int noname = 0; - st = NULL; - - if((words[1]) != NULL && (words[2]) != NULL && strcmp(words[1], words[2]) == 0) - noname = 1; - - char *type = words[1]; - char *id = NULL; - if(likely(type)) { - id = strchr(type, '.'); - if(likely(id)) { *id = '\0'; id++; } - } - char *name = words[2]; - char *title = words[3]; - char *units = words[4]; - char *family = words[5]; - char *context = words[6]; - char *chart = words[7]; - char *priority_s = words[8]; - char *update_every_s = words[9]; - - if(unlikely(!type || !*type || !id || !*id)) { - error("PLUGINSD: '%s' is requesting a CHART, without a type.id. Disabling it.", cd->fullfilename); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } - int priority = 1000; - if(likely(priority_s)) priority = str2i(priority_s); - - int update_every = cd->update_every; - if(likely(update_every_s)) update_every = str2i(update_every_s); - if(unlikely(!update_every)) update_every = cd->update_every; - - int chart_type = RRDSET_TYPE_LINE; - if(unlikely(chart)) chart_type = rrdset_type_id(chart); - - if(unlikely(noname || !name || !*name || strcasecmp(name, "NULL") == 0 || strcasecmp(name, "(NULL)") == 0)) name = NULL; - if(unlikely(!family || !*family)) family = NULL; - if(unlikely(!context || !*context)) context = NULL; - - st = rrdset_find_bytype(type, id); - if(unlikely(!st)) { - debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d" - , type, id - , name?name:"" - , family?family:"" - , context?context:"" - , rrdset_type_name(chart_type) - , priority - , update_every - ); - - st = rrdset_create(type, id, name, family, context, title, units, priority, update_every, chart_type); - cd->update_every = update_every; - } - else debug(D_PLUGINSD, "PLUGINSD: Chart '%s' already exists. Not adding it again.", st->id); + host = rrdhost_find_or_create(hostname, guid); + } */ + else if(likely(hash == FLUSH_HASH && !strcmp(s, "FLUSH"))) { + debug(D_PLUGINSD, "PLUGINSD: '%s' is requesting a FLUSH", cd->fullfilename); + st = NULL; + } + else if(likely(hash == CHART_HASH && !strcmp(s, "CHART"))) { + int noname = 0; + st = NULL; + + if((words[1]) != NULL && (words[2]) != NULL && strcmp(words[1], words[2]) == 0) + noname = 1; + + char *type = words[1]; + char *id = NULL; + if(likely(type)) { + id = strchr(type, '.'); + if(likely(id)) { *id = '\0'; id++; } + } + char *name = words[2]; + char *title = words[3]; + char *units = words[4]; + char *family = words[5]; + char *context = words[6]; + char *chart = words[7]; + char *priority_s = words[8]; + char *update_every_s = words[9]; + + if(unlikely(!type || !*type || !id || !*id)) { + error("PLUGINSD: '%s' is requesting a CHART, without a type.id, on host '%s'. Disabling it.", cd->fullfilename, host->hostname); + enabled = 0; + break; } - else if(likely(hash == DIMENSION_HASH && !strcmp(s, "DIMENSION"))) { - char *id = words[1]; - char *name = words[2]; - char *algorithm = words[3]; - char *multiplier_s = words[4]; - char *divisor_s = words[5]; - char *options = words[6]; - - if(unlikely(!id || !*id)) { - error("PLUGINSD: '%s' is requesting a DIMENSION, without an id. Disabling it.", cd->fullfilename); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } - - if(unlikely(!st)) { - error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART. Disabling it.", cd->fullfilename); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; - } - long multiplier = 1; - if(multiplier_s && *multiplier_s) multiplier = strtol(multiplier_s, NULL, 0); - if(unlikely(!multiplier)) multiplier = 1; - - long divisor = 1; - if(likely(divisor_s && *divisor_s)) divisor = strtol(divisor_s, NULL, 0); - if(unlikely(!divisor)) divisor = 1; - - if(unlikely(!algorithm || !*algorithm)) algorithm = "absolute"; - - if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: Creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'" - , st->id - , id - , name?name:"" - , rrddim_algorithm_name(rrddim_algorithm_id(algorithm)) - , multiplier - , divisor - , options?options:"" - ); - - RRDDIM *rd = rrddim_find(st, id); - if(unlikely(!rd)) { - rd = rrddim_add(st, id, name, multiplier, divisor, rrddim_algorithm_id(algorithm)); - rd->flags = 0x00000000; - if(options && *options) { - if(strstr(options, "hidden") != NULL) rd->flags |= RRDDIM_FLAG_HIDDEN; - if(strstr(options, "noreset") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS; - if(strstr(options, "nooverflow") != NULL) rd->flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS; - } - } - else if(unlikely(st->debug)) debug(D_PLUGINSD, "PLUGINSD: dimension %s/%s already exists. Not adding it again.", st->id, id); + int priority = 1000; + if(likely(priority_s)) priority = str2i(priority_s); + + int update_every = cd->update_every; + if(likely(update_every_s)) update_every = str2i(update_every_s); + if(unlikely(!update_every)) update_every = cd->update_every; + + RRDSET_TYPE chart_type = RRDSET_TYPE_LINE; + if(unlikely(chart)) chart_type = rrdset_type_id(chart); + + if(unlikely(noname || !name || !*name || strcasecmp(name, "NULL") == 0 || strcasecmp(name, "(NULL)") == 0)) name = NULL; + if(unlikely(!family || !*family)) family = NULL; + if(unlikely(!context || !*context)) context = NULL; + + st = rrdset_find_bytype(host, type, id); + if(unlikely(!st)) { + debug(D_PLUGINSD, "PLUGINSD: Creating chart type='%s', id='%s', name='%s', family='%s', context='%s', chart='%s', priority=%d, update_every=%d" + , type, id + , name?name:"" + , family?family:"" + , context?context:"" + , rrdset_type_name(chart_type) + , priority + , update_every + ); + + st = rrdset_create(host, type, id, name, family, context, title, units, priority, update_every, chart_type); + cd->update_every = update_every; } - else if(unlikely(hash == DISABLE_HASH && !strcmp(s, "DISABLE"))) { - info("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); + else debug(D_PLUGINSD, "PLUGINSD: Chart '%s' already exists. Not adding it again.", st->id); + } + else if(likely(hash == DIMENSION_HASH && !strcmp(s, "DIMENSION"))) { + char *id = words[1]; + char *name = words[2]; + char *algorithm = words[3]; + char *multiplier_s = words[4]; + char *divisor_s = words[5]; + char *options = words[6]; + + if(unlikely(!id || !*id)) { + error("PLUGINSD: '%s' is requesting a DIMENSION, without an id, host '%s' and chart '%s'. Disabling it.", cd->fullfilename, host->hostname, st?st->id:"UNSET"); + enabled = 0; break; } -#ifdef DETACH_PLUGINS_FROM_NETDATA - else if(likely(hash == MYPID_HASH && !strcmp(s, "MYPID"))) { - char *pid_s = words[1]; - pid_t pid = strtod(pid_s, NULL, 0); - if(likely(pid)) cd->pid = pid; - debug(D_PLUGINSD, "PLUGINSD: %s is on pid %d", cd->id, cd->pid); + if(unlikely(!st)) { + error("PLUGINSD: '%s' is requesting a DIMENSION, without a CHART, on host '%s'. Disabling it.", cd->fullfilename, host->hostname); + enabled = 0; + break; } - else if(likely(hash == STOPPING_WAKE_ME_UP_PLEASE_HASH && !strcmp(s, "STOPPING_WAKE_ME_UP_PLEASE"))) { - error("PLUGINSD: '%s' (pid %d) called STOPPING_WAKE_ME_UP_PLEASE.", cd->fullfilename, cd->pid); - now_realtime_timeval(&now); - if(unlikely(!usec && !susec)) { - // our first run - susec = cd->rrd_update_every * USEC_PER_SEC; + long multiplier = 1; + if(multiplier_s && *multiplier_s) multiplier = strtol(multiplier_s, NULL, 0); + if(unlikely(!multiplier)) multiplier = 1; + + long divisor = 1; + if(likely(divisor_s && *divisor_s)) divisor = strtol(divisor_s, NULL, 0); + if(unlikely(!divisor)) divisor = 1; + + if(unlikely(!algorithm || !*algorithm)) algorithm = "absolute"; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_PLUGINSD, "PLUGINSD: Creating dimension in chart %s, id='%s', name='%s', algorithm='%s', multiplier=%ld, divisor=%ld, hidden='%s'" + , st->id + , id + , name?name:"" + , rrd_algorithm_name(rrd_algorithm_id(algorithm)) + , multiplier + , divisor + , options?options:"" + ); + + RRDDIM *rd = rrddim_find(st, id); + if(unlikely(!rd)) { + rd = rrddim_add(st, id, name, multiplier, divisor, rrd_algorithm_id(algorithm)); + rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN); + rrddim_flag_clear(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); + if(options && *options) { + if(strstr(options, "hidden") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN); + if(strstr(options, "noreset") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); + if(strstr(options, "nooverflow") != NULL) rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); } - else { - // second+ run - usec = dt_usec(&now, &last) - susec; - error("PLUGINSD: %s last loop took %llu usec (worked for %llu, sleeped for %llu).\n", cd->fullfilename, usec + susec, usec, susec); - if(unlikely(usec < (rrd_update_every * USEC_PER_SEC / 2ULL))) susec = (rrd_update_every * USEC_PER_SEC) - usec; - else susec = rrd_update_every * USEC_PER_SEC / 2ULL; - } - - error("PLUGINSD: %s sleeping for %llu. Will kill with SIGCONT pid %d to wake it up.\n", cd->fullfilename, susec, cd->pid); - usleep(susec); - killpid(cd->pid, SIGCONT); - memmove(&last, &now, sizeof(struct timeval)); - break; - } -#endif - else { - error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata. Disabling it.", cd->fullfilename, s); - cd->enabled = 0; - killpid(cd->pid, SIGTERM); - break; } + else if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_PLUGINSD, "PLUGINSD: dimension %s/%s already exists. Not adding it again.", st->id, id); + } + else if(unlikely(hash == DISABLE_HASH && !strcmp(s, "DISABLE"))) { + info("PLUGINSD: '%s' called DISABLE. Disabling it.", cd->fullfilename); + enabled = 0; + break; } - if(likely(count)) { - cd->successful_collections += count; - cd->serial_failures = 0; + else { + error("PLUGINSD: '%s' is sending command '%s' which is not known by netdata, for host '%s'. Disabling it.", cd->fullfilename, s, host->hostname); + enabled = 0; + break; } - else - cd->serial_failures++; + } + +cleanup: + cd->enabled = enabled; + + if(likely(count)) { + cd->successful_collections += count; + cd->serial_failures = 0; + } + else + cd->serial_failures++; + + return count; +} + +void *pluginsd_worker_thread(void *arg) { + struct plugind *cd = (struct plugind *)arg; + cd->obsolete = 0; + + size_t count = 0; + + for(;;) { + if(unlikely(netdata_exit)) break; + + FILE *fp = mypopen(cd->cmd, &cd->pid); + if(unlikely(!fp)) { + error("Cannot popen(\"%s\", \"r\").", cd->cmd); + break; + } + + info("PLUGINSD: '%s' running on pid %d", cd->fullfilename, cd->pid); + + count = pluginsd_process(localhost, cd, fp, 0); + error("PLUGINSD: plugin '%s' disconnected.", cd->fullfilename); + + killpid(cd->pid, SIGTERM); info("PLUGINSD: '%s' on pid %d stopped after %zu successful data collections (ENDs).", cd->fullfilename, cd->pid, count); // get the return code int code = mypclose(fp, cd->pid); - + if(unlikely(netdata_exit)) break; else if(code != 0) { // the plugin reports failure @@ -442,14 +455,14 @@ void *pluginsd_main(void *ptr) { if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); - int automatic_run = config_get_boolean("plugins", "enable running new plugins", 1); - int scan_frequency = (int) config_get_number("plugins", "check for new plugins every", 60); + int automatic_run = config_get_boolean(CONFIG_SECTION_PLUGINS, "enable running new plugins", 1); + int scan_frequency = (int) config_get_number(CONFIG_SECTION_PLUGINS, "check for new plugins every", 60); DIR *dir = NULL; struct dirent *file = NULL; struct plugind *cd; // enable the apps plugin by default - // config_get_boolean("plugins", "apps", 1); + // config_get_boolean(CONFIG_SECTION_PLUGINS, "apps", 1); if(scan_frequency < 1) scan_frequency = 1; @@ -478,7 +491,7 @@ void *pluginsd_main(void *ptr) { char pluginname[CONFIG_MAX_NAME + 1]; snprintfz(pluginname, CONFIG_MAX_NAME, "%.*s", (int)(len - PLUGINSD_FILE_SUFFIX_LEN), file->d_name); - int enabled = config_get_boolean("plugins", pluginname, automatic_run); + int enabled = config_get_boolean(CONFIG_SECTION_PLUGINS, pluginname, automatic_run); if(unlikely(!enabled)) { debug(D_PLUGINSD, "PLUGINSD: plugin '%s' is not enabled", file->d_name); @@ -505,7 +518,7 @@ void *pluginsd_main(void *ptr) { snprintfz(cd->fullfilename, FILENAME_MAX, "%s/%s", netdata_configured_plugins_dir, cd->filename); cd->enabled = enabled; - cd->update_every = (int) config_get_number(cd->id, "update every", rrd_update_every); + cd->update_every = (int) config_get_number(cd->id, "update every", localhost->rrd_update_every); cd->started_t = now_realtime_sec(); char *def = ""; diff --git a/src/plugins_d.h b/src/plugins_d.h index 3c74355a..d34c4030 100644 --- a/src/plugins_d.h +++ b/src/plugins_d.h @@ -11,7 +11,7 @@ struct plugind { char filename[FILENAME_MAX+1]; // just the filename char fullfilename[FILENAME_MAX+1]; // with path - char cmd[PLUGINSD_CMD_MAX+1]; // the command that is executes + char cmd[PLUGINSD_CMD_MAX+1]; // the command that it executes pid_t pid; pthread_t thread; @@ -34,5 +34,6 @@ struct plugind { extern struct plugind *pluginsd_root; extern void *pluginsd_main(void *ptr); +extern size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations); #endif /* NETDATA_PLUGINS_D_H */ diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c index b21838b6..134e7a1a 100644 --- a/src/proc_diskstats.c +++ b/src/proc_diskstats.c @@ -198,17 +198,17 @@ static inline int is_major_enabled(int major) { int do_proc_diskstats(int update_every, usec_t dt) { static procfile *ff = NULL; - static int global_enable_new_disks_detected_at_runtime = CONFIG_ONDEMAND_YES, - global_enable_performance_for_physical_disks = CONFIG_ONDEMAND_ONDEMAND, - global_enable_performance_for_virtual_disks = CONFIG_ONDEMAND_ONDEMAND, - global_enable_performance_for_partitions = CONFIG_ONDEMAND_NO, - global_do_io = CONFIG_ONDEMAND_ONDEMAND, - global_do_ops = CONFIG_ONDEMAND_ONDEMAND, - global_do_mops = CONFIG_ONDEMAND_ONDEMAND, - global_do_iotime = CONFIG_ONDEMAND_ONDEMAND, - global_do_qops = CONFIG_ONDEMAND_ONDEMAND, - global_do_util = CONFIG_ONDEMAND_ONDEMAND, - global_do_backlog = CONFIG_ONDEMAND_ONDEMAND, + static int global_enable_new_disks_detected_at_runtime = CONFIG_BOOLEAN_YES, + global_enable_performance_for_physical_disks = CONFIG_BOOLEAN_AUTO, + global_enable_performance_for_virtual_disks = CONFIG_BOOLEAN_AUTO, + global_enable_performance_for_partitions = CONFIG_BOOLEAN_NO, + global_do_io = CONFIG_BOOLEAN_AUTO, + global_do_ops = CONFIG_BOOLEAN_AUTO, + global_do_mops = CONFIG_BOOLEAN_AUTO, + global_do_iotime = CONFIG_BOOLEAN_AUTO, + global_do_qops = CONFIG_BOOLEAN_AUTO, + global_do_util = CONFIG_BOOLEAN_AUTO, + global_do_backlog = CONFIG_BOOLEAN_AUTO, globals_initialized = 0; if(unlikely(!globals_initialized)) { @@ -333,21 +333,21 @@ int do_proc_diskstats(int update_every, usec_t dt) { snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk); int def_enable = config_get_boolean_ondemand(var_name, "enable", global_enable_new_disks_detected_at_runtime); - if(unlikely(def_enable == CONFIG_ONDEMAND_NO)) { + if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) { // the user does not want any metrics for this disk - d->do_io = CONFIG_ONDEMAND_NO; - d->do_ops = CONFIG_ONDEMAND_NO; - d->do_mops = CONFIG_ONDEMAND_NO; - d->do_iotime = CONFIG_ONDEMAND_NO; - d->do_qops = CONFIG_ONDEMAND_NO; - d->do_util = CONFIG_ONDEMAND_NO; - d->do_backlog = CONFIG_ONDEMAND_NO; + d->do_io = CONFIG_BOOLEAN_NO; + d->do_ops = CONFIG_BOOLEAN_NO; + d->do_mops = CONFIG_BOOLEAN_NO; + d->do_iotime = CONFIG_BOOLEAN_NO; + d->do_qops = CONFIG_BOOLEAN_NO; + d->do_util = CONFIG_BOOLEAN_NO; + d->do_backlog = CONFIG_BOOLEAN_NO; } else { // this disk is enabled // check its direct settings - int def_performance = CONFIG_ONDEMAND_ONDEMAND; + int def_performance = CONFIG_BOOLEAN_AUTO; // since this is 'on demand' we can figure the performance settings // based on the type of disk @@ -378,16 +378,16 @@ int do_proc_diskstats(int update_every, usec_t dt) { // check the user configuration (this will also show our 'on demand' decision) def_performance = config_get_boolean_ondemand(var_name, "enable performance metrics", def_performance); - int ddo_io = CONFIG_ONDEMAND_NO, - ddo_ops = CONFIG_ONDEMAND_NO, - ddo_mops = CONFIG_ONDEMAND_NO, - ddo_iotime = CONFIG_ONDEMAND_NO, - ddo_qops = CONFIG_ONDEMAND_NO, - ddo_util = CONFIG_ONDEMAND_NO, - ddo_backlog = CONFIG_ONDEMAND_NO; + int ddo_io = CONFIG_BOOLEAN_NO, + ddo_ops = CONFIG_BOOLEAN_NO, + ddo_mops = CONFIG_BOOLEAN_NO, + ddo_iotime = CONFIG_BOOLEAN_NO, + ddo_qops = CONFIG_BOOLEAN_NO, + ddo_util = CONFIG_BOOLEAN_NO, + ddo_backlog = CONFIG_BOOLEAN_NO; // we enable individual performance charts only when def_performance is not disabled - if(unlikely(def_performance != CONFIG_ONDEMAND_NO)) { + if(unlikely(def_performance != CONFIG_BOOLEAN_NO)) { ddo_io = global_do_io, ddo_ops = global_do_ops, ddo_mops = global_do_mops, @@ -414,15 +414,16 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------------- // Do performance metrics - if(d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) { - d->do_io = CONFIG_ONDEMAND_YES; + if(d->do_io == CONFIG_BOOLEAN_YES || (d->do_io == CONFIG_BOOLEAN_AUTO && (readsectors || writesectors))) { + d->do_io = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype(RRD_TYPE_DISK, disk); + st = rrdset_find_bytype_localhost(RRD_TYPE_DISK, disk); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_DISK, disk, NULL, family, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost(RRD_TYPE_DISK, disk, NULL, family, "disk.io", "Disk I/O Bandwidth" + , "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -433,16 +434,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes))) { - d->do_ops = CONFIG_ONDEMAND_YES; + if(d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes))) { + d->do_ops = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype("disk_ops", disk); + st = rrdset_find_bytype_localhost("disk_ops", disk); if(unlikely(!st)) { - st = rrdset_create("disk_ops", disk, NULL, family, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_ops", disk, NULL, family, "disk.ops", "Disk Completed I/O Operations" + , "operations/s", 2001, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -453,15 +455,16 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(d->do_qops == CONFIG_ONDEMAND_YES || (d->do_qops == CONFIG_ONDEMAND_ONDEMAND && queued_ios)) { - d->do_qops = CONFIG_ONDEMAND_YES; + if(d->do_qops == CONFIG_BOOLEAN_YES || (d->do_qops == CONFIG_BOOLEAN_AUTO && queued_ios)) { + d->do_qops = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype("disk_qops", disk); + st = rrdset_find_bytype_localhost("disk_qops", disk); if(unlikely(!st)) { - st = rrdset_create("disk_qops", disk, NULL, family, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_qops", disk, NULL, family, "disk.qops", "Disk Current I/O Operations" + , "operations", 2002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -471,15 +474,16 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(d->do_backlog == CONFIG_ONDEMAND_YES || (d->do_backlog == CONFIG_ONDEMAND_ONDEMAND && backlog_ms)) { - d->do_backlog = CONFIG_ONDEMAND_YES; + if(d->do_backlog == CONFIG_BOOLEAN_YES || (d->do_backlog == CONFIG_BOOLEAN_AUTO && backlog_ms)) { + d->do_backlog = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype("disk_backlog", disk); + st = rrdset_find_bytype_localhost("disk_backlog", disk); if(unlikely(!st)) { - st = rrdset_create("disk_backlog", disk, NULL, family, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("disk_backlog", disk, NULL, family, "disk.backlog", "Disk Backlog" + , "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "backlog", NULL, 1, 10, RRDDIM_INCREMENTAL); + rrddim_add(st, "backlog", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -489,15 +493,16 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) { - d->do_util = CONFIG_ONDEMAND_YES; + if(d->do_util == CONFIG_BOOLEAN_YES || (d->do_util == CONFIG_BOOLEAN_AUTO && busy_ms)) { + d->do_util = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype("disk_util", disk); + st = rrdset_find_bytype_localhost("disk_util", disk); if(unlikely(!st)) { - st = rrdset_create("disk_util", disk, NULL, family, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("disk_util", disk, NULL, family, "disk.util", "Disk Utilization Time" + , "% of time working", 2004, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL); + rrddim_add(st, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -507,16 +512,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(d->do_mops == CONFIG_ONDEMAND_YES || (d->do_mops == CONFIG_ONDEMAND_ONDEMAND && (mreads || mwrites))) { - d->do_mops = CONFIG_ONDEMAND_YES; + if(d->do_mops == CONFIG_BOOLEAN_YES || (d->do_mops == CONFIG_BOOLEAN_AUTO && (mreads || mwrites))) { + d->do_mops = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype("disk_mops", disk); + st = rrdset_find_bytype_localhost("disk_mops", disk); if(unlikely(!st)) { - st = rrdset_create("disk_mops", disk, NULL, family, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_mops", disk, NULL, family, "disk.mops", "Disk Merged Operations" + , "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -527,16 +533,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) { - d->do_iotime = CONFIG_ONDEMAND_YES; + if(d->do_iotime == CONFIG_BOOLEAN_YES || (d->do_iotime == CONFIG_BOOLEAN_AUTO && (readms || writems))) { + d->do_iotime = CONFIG_BOOLEAN_YES; - st = rrdset_find_bytype("disk_iotime", disk); + st = rrdset_find_bytype_localhost("disk_iotime", disk); if(unlikely(!st)) { - st = rrdset_create("disk_iotime", disk, NULL, family, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_iotime", disk, NULL, family, "disk.iotime", "Disk Total I/O Time" + , "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -550,15 +557,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { // only if this is not the first time we run if(likely(dt)) { - if( (d->do_iotime == CONFIG_ONDEMAND_YES || (d->do_iotime == CONFIG_ONDEMAND_ONDEMAND && (readms || writems))) && - (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) { - st = rrdset_find_bytype("disk_await", disk); + if( (d->do_iotime == CONFIG_BOOLEAN_YES || (d->do_iotime == CONFIG_BOOLEAN_AUTO && (readms || writems))) && + (d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes)))) { + st = rrdset_find_bytype_localhost("disk_await", disk); if(unlikely(!st)) { - st = rrdset_create("disk_await", disk, NULL, family, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_await", disk, NULL, family, "disk.await" + , "Average Completed I/O Operation Time", "ms per operation", 2005 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -567,15 +576,17 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_done(st); } - if( (d->do_io == CONFIG_ONDEMAND_YES || (d->do_io == CONFIG_ONDEMAND_ONDEMAND && (readsectors || writesectors))) && - (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) { - st = rrdset_find_bytype("disk_avgsz", disk); + if( (d->do_io == CONFIG_BOOLEAN_YES || (d->do_io == CONFIG_BOOLEAN_AUTO && (readsectors || writesectors))) && + (d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes)))) { + st = rrdset_find_bytype_localhost("disk_avgsz", disk); if(unlikely(!st)) { - st = rrdset_create("disk_avgsz", disk, NULL, family, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("disk_avgsz", disk, NULL, family, "disk.avgsz" + , "Average Completed I/O Operation Bandwidth" + , "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "reads", NULL, d->sector_size, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "writes", NULL, d->sector_size * -1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -584,14 +595,15 @@ int do_proc_diskstats(int update_every, usec_t dt) { rrdset_done(st); } - if( (d->do_util == CONFIG_ONDEMAND_YES || (d->do_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms)) && - (d->do_ops == CONFIG_ONDEMAND_YES || (d->do_ops == CONFIG_ONDEMAND_ONDEMAND && (reads || writes)))) { - st = rrdset_find_bytype("disk_svctm", disk); + if( (d->do_util == CONFIG_BOOLEAN_YES || (d->do_util == CONFIG_BOOLEAN_AUTO && busy_ms)) && + (d->do_ops == CONFIG_BOOLEAN_YES || (d->do_ops == CONFIG_BOOLEAN_AUTO && (reads || writes)))) { + st = rrdset_find_bytype_localhost("disk_svctm", disk); if(unlikely(!st)) { - st = rrdset_create("disk_svctm", disk, NULL, family, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("disk_svctm", disk, NULL, family, "disk.svctm", "Average Service Time" + , "ms per operation", 2007, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/proc_interrupts.c b/src/proc_interrupts.c index 5e29f4f0..082e1f57 100644 --- a/src/proc_interrupts.c +++ b/src/proc_interrupts.c @@ -146,8 +146,9 @@ int do_proc_interrupts(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("system", "interrupts"); - if(unlikely(!st)) st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED); + st = rrdset_find_bytype_localhost("system", "interrupts"); + if(unlikely(!st)) st = rrdset_create_localhost("system", "interrupts", NULL, "interrupts", NULL, "System interrupts" + , "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED); else rrdset_next(st); for(l = 0; l < lines ;l++) { @@ -159,7 +160,7 @@ int do_proc_interrupts(int update_every, usec_t dt) { if(unlikely(!irr->rd || strncmp(irr->rd->name, irr->name, MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_find(st, irr->id); if(unlikely(!irr->rd)) - irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); + irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); else rrddim_set_name(st, irr->rd, irr->name); @@ -181,11 +182,12 @@ int do_proc_interrupts(int update_every, usec_t dt) { char id[50+1]; snprintfz(id, 50, "cpu%d_interrupts", c); - st = rrdset_find_bytype("cpu", id); + st = rrdset_find_bytype_localhost("cpu", id); if(unlikely(!st)) { char title[100+1]; snprintfz(title, 100, "CPU%d Interrupts", c); - st = rrdset_create("cpu", id, NULL, "interrupts", "cpu.interrupts", title, "interrupts/s", 1100 + c, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("cpu", id, NULL, "interrupts", "cpu.interrupts", title, "interrupts/s", + 1100 + c, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st); @@ -195,7 +197,7 @@ int do_proc_interrupts(int update_every, usec_t dt) { if(unlikely(!irr->cpu[c].rd)) { irr->cpu[c].rd = rrddim_find(st, irr->id); if(unlikely(!irr->cpu[c].rd)) - irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); + irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); else rrddim_set_name(st, irr->cpu[c].rd, irr->name); } diff --git a/src/proc_loadavg.c b/src/proc_loadavg.c index 4b1779f7..e7863f11 100644 --- a/src/proc_loadavg.c +++ b/src/proc_loadavg.c @@ -50,12 +50,15 @@ int do_proc_loadavg(int update_every, usec_t dt) { if(next_loadavg_dt <= dt) { if(likely(do_loadavg)) { if(unlikely(!load_chart)) { - load_chart = rrdset_find_byname("system.load"); + load_chart = rrdset_find_byname_localhost("system.load"); if(unlikely(!load_chart)) { - load_chart = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE); - rrddim_add(load_chart, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(load_chart, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(load_chart, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE); + load_chart = rrdset_create_localhost("system", "load", NULL, "load", NULL, "System Load Average" + , "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) + ? MIN_LOADAVG_UPDATE_EVERY : update_every + , RRDSET_TYPE_LINE); + rrddim_add(load_chart, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(load_chart, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(load_chart, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } } else @@ -75,10 +78,12 @@ int do_proc_loadavg(int update_every, usec_t dt) { if(likely(do_all_processes)) { if(unlikely(!processes_chart)) { - processes_chart = rrdset_find_byname("system.active_processes"); + processes_chart = rrdset_find_byname_localhost("system.active_processes"); if(unlikely(!processes_chart)) { - processes_chart = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE); - rrddim_add(processes_chart, "active", NULL, 1, 1, RRDDIM_ABSOLUTE); + processes_chart = rrdset_create_localhost("system", "active_processes", NULL, "processes", NULL + , "System Active Processes", "processes", 750, update_every + , RRDSET_TYPE_LINE); + rrddim_add(processes_chart, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } } else rrdset_next(processes_chart); diff --git a/src/proc_meminfo.c b/src/proc_meminfo.c index da6a430b..6b0219cc 100644 --- a/src/proc_meminfo.c +++ b/src/proc_meminfo.c @@ -55,8 +55,8 @@ int do_proc_meminfo(int update_every, usec_t dt) { if(unlikely(!arl_base)) { do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1); - do_swap = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "system swap", CONFIG_ONDEMAND_ONDEMAND); - do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND); + do_swap = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "system swap", CONFIG_BOOLEAN_AUTO); + do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_BOOLEAN_AUTO); do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1); do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1); do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1); @@ -140,14 +140,15 @@ int do_proc_meminfo(int update_every, usec_t dt) { unsigned long long MemUsed = MemTotal - MemFree - Cached - Buffers; if(do_ram) { - st = rrdset_find("system.ram"); + st = rrdset_find_localhost("system.ram"); if(!st) { - st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every + , RRDSET_TYPE_STACKED); - rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "cached", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "cached", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "buffers", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -162,16 +163,17 @@ int do_proc_meminfo(int update_every, usec_t dt) { unsigned long long SwapUsed = SwapTotal - SwapFree; - if(SwapTotal || SwapUsed || SwapFree || do_swap == CONFIG_ONDEMAND_YES) { - do_swap = CONFIG_ONDEMAND_YES; + if(SwapTotal || SwapUsed || SwapFree || do_swap == CONFIG_BOOLEAN_YES) { + do_swap = CONFIG_BOOLEAN_YES; - st = rrdset_find("system.swap"); + st = rrdset_find_localhost("system.swap"); if(!st) { - st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; + st = rrdset_create_localhost("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every + , RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -182,15 +184,16 @@ int do_proc_meminfo(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(arl_hwcorrupted->flags & ARL_ENTRY_FLAG_FOUND && (do_hwcorrupt == CONFIG_ONDEMAND_YES || (do_hwcorrupt == CONFIG_ONDEMAND_ONDEMAND && HardwareCorrupted > 0))) { - do_hwcorrupt = CONFIG_ONDEMAND_YES; + if(arl_hwcorrupted->flags & ARL_ENTRY_FLAG_FOUND && (do_hwcorrupt == CONFIG_BOOLEAN_YES || (do_hwcorrupt == CONFIG_BOOLEAN_AUTO && HardwareCorrupted > 0))) { + do_hwcorrupt = CONFIG_BOOLEAN_YES; - st = rrdset_find("mem.hwcorrupt"); + st = rrdset_find_localhost("mem.hwcorrupt"); if(!st) { - st = rrdset_create("mem", "hwcorrupt", NULL, "ecc", NULL, "Hardware Corrupted ECC", "MB", 9000, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("mem", "hwcorrupt", NULL, "ecc", NULL, "Hardware Corrupted ECC", "MB", 9000 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -201,12 +204,13 @@ int do_proc_meminfo(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_committed) { - st = rrdset_find("mem.committed"); + st = rrdset_find_localhost("mem.committed"); if(!st) { - st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB" + , 5000, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -217,16 +221,17 @@ int do_proc_meminfo(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_writeback) { - st = rrdset_find("mem.writeback"); + st = rrdset_find_localhost("mem.writeback"); if(!st) { - st = rrdset_create("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "Dirty", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "Writeback", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "Bounce", NULL, 1, 1024, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "Dirty", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "Writeback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "Bounce", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -241,15 +246,16 @@ int do_proc_meminfo(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_kernel) { - st = rrdset_find("mem.kernel"); + st = rrdset_find_localhost("mem.kernel"); if(!st) { - st = rrdset_create("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; - - rrddim_add(st, "Slab", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "KernelStack", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "PageTables", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000 + , update_every, RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "Slab", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "KernelStack", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "PageTables", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -263,13 +269,14 @@ int do_proc_meminfo(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_slab) { - st = rrdset_find("mem.slab"); + st = rrdset_find_localhost("mem.slab"); if(!st) { - st = rrdset_create("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; + st = rrdset_create_localhost("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500 + , update_every, RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "reclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "reclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/proc_net_dev.c b/src/proc_net_dev.c index bb1e4c0f..9b942326 100644 --- a/src/proc_net_dev.c +++ b/src/proc_net_dev.c @@ -117,15 +117,15 @@ int do_proc_net_dev(int update_every, usec_t dt) { static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1; if(unlikely(enable_new_interfaces == -1)) { - enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND); + enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO); - do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND); - do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND); + do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_BOOLEAN_AUTO); + do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_BOOLEAN_AUTO); + do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_BOOLEAN_AUTO); + do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_BOOLEAN_AUTO); + do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_BOOLEAN_AUTO); + do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_BOOLEAN_AUTO); + do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_BOOLEAN_AUTO); disabled_list = simple_pattern_create( config_get("plugin:proc:/proc/net/dev", "disable by default interfaces matching", "lo fireqos* *-ifb") @@ -164,7 +164,7 @@ int do_proc_net_dev(int update_every, usec_t dt) { snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", d->name); d->enabled = config_get_boolean_ondemand(var_name, "enabled", d->enabled); - if(d->enabled == CONFIG_ONDEMAND_NO) + if(d->enabled == CONFIG_BOOLEAN_NO) continue; d->do_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", do_bandwidth); @@ -179,38 +179,38 @@ int do_proc_net_dev(int update_every, usec_t dt) { if(unlikely(!d->enabled)) continue; - if(likely(d->do_bandwidth != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_bandwidth != CONFIG_BOOLEAN_NO)) { d->rbytes = str2kernel_uint_t(procfile_lineword(ff, l, 1)); d->tbytes = str2kernel_uint_t(procfile_lineword(ff, l, 9)); } - if(likely(d->do_packets != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_packets != CONFIG_BOOLEAN_NO)) { d->rpackets = str2kernel_uint_t(procfile_lineword(ff, l, 2)); d->rmulticast = str2kernel_uint_t(procfile_lineword(ff, l, 8)); d->tpackets = str2kernel_uint_t(procfile_lineword(ff, l, 10)); } - if(likely(d->do_errors != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_errors != CONFIG_BOOLEAN_NO)) { d->rerrors = str2kernel_uint_t(procfile_lineword(ff, l, 3)); d->terrors = str2kernel_uint_t(procfile_lineword(ff, l, 11)); } - if(likely(d->do_drops != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_drops != CONFIG_BOOLEAN_NO)) { d->rdrops = str2kernel_uint_t(procfile_lineword(ff, l, 4)); d->tdrops = str2kernel_uint_t(procfile_lineword(ff, l, 12)); } - if(likely(d->do_fifo != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_fifo != CONFIG_BOOLEAN_NO)) { d->rfifo = str2kernel_uint_t(procfile_lineword(ff, l, 5)); d->tfifo = str2kernel_uint_t(procfile_lineword(ff, l, 13)); } - if(likely(d->do_compressed != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_compressed != CONFIG_BOOLEAN_NO)) { d->rcompressed = str2kernel_uint_t(procfile_lineword(ff, l, 7)); d->tcompressed = str2kernel_uint_t(procfile_lineword(ff, l, 16)); } - if(likely(d->do_events != CONFIG_ONDEMAND_NO)) { + if(likely(d->do_events != CONFIG_BOOLEAN_NO)) { d->rframe = str2kernel_uint_t(procfile_lineword(ff, l, 6)); d->tcollisions = str2kernel_uint_t(procfile_lineword(ff, l, 14)); d->tcarrier = str2kernel_uint_t(procfile_lineword(ff, l, 15)); @@ -218,18 +218,19 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (d->rbytes || d->tbytes)))) - d->do_bandwidth = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_bandwidth == CONFIG_BOOLEAN_AUTO && (d->rbytes || d->tbytes)))) + d->do_bandwidth = CONFIG_BOOLEAN_YES; - if(d->do_bandwidth == CONFIG_ONDEMAND_YES) { + if(d->do_bandwidth == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_bandwidth)) { - d->st_bandwidth = rrdset_find_bytype("net", d->name); + d->st_bandwidth = rrdset_find_bytype_localhost("net", d->name); if(!d->st_bandwidth) - d->st_bandwidth = rrdset_create("net", d->name, NULL, d->name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); + d->st_bandwidth = rrdset_create_localhost("net", d->name, NULL, d->name, "net.net", "Bandwidth" + , "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA); - d->rd_rbytes = rrddim_add(d->st_bandwidth, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - d->rd_tbytes = rrddim_add(d->st_bandwidth, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + d->rd_rbytes = rrddim_add(d->st_bandwidth, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + d->rd_tbytes = rrddim_add(d->st_bandwidth, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_bandwidth); @@ -240,21 +241,22 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_packets == CONFIG_ONDEMAND_ONDEMAND && (d->rpackets || d->tpackets || d->rmulticast)))) - d->do_packets = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_packets == CONFIG_BOOLEAN_AUTO && (d->rpackets || d->tpackets || d->rmulticast)))) + d->do_packets = CONFIG_BOOLEAN_YES; - if(d->do_packets == CONFIG_ONDEMAND_YES) { + if(d->do_packets == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_packets)) { - d->st_packets = rrdset_find_bytype("net_packets", d->name); + d->st_packets = rrdset_find_bytype_localhost("net_packets", d->name); if(!d->st_packets) - d->st_packets = rrdset_create("net_packets", d->name, NULL, d->name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE); - - d->st_packets->isdetail = 1; - - d->rd_rpackets = rrddim_add(d->st_packets, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - d->rd_tpackets = rrddim_add(d->st_packets, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); - d->rd_rmulticast = rrddim_add(d->st_packets, "multicast", NULL, 1, 1, RRDDIM_INCREMENTAL); + d->st_packets = rrdset_create_localhost("net_packets", d->name, NULL, d->name, "net.packets" + , "Packets", "packets/s", 7001, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(d->st_packets, RRDSET_FLAG_DETAIL); + + d->rd_rpackets = rrddim_add(d->st_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_tpackets = rrddim_add(d->st_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_rmulticast = rrddim_add(d->st_packets, "multicast", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_packets); @@ -266,20 +268,22 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_errors == CONFIG_ONDEMAND_ONDEMAND && (d->rerrors || d->terrors)))) - d->do_errors = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_errors == CONFIG_BOOLEAN_AUTO && (d->rerrors || d->terrors)))) + d->do_errors = CONFIG_BOOLEAN_YES; - if(d->do_errors == CONFIG_ONDEMAND_YES) { + if(d->do_errors == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_errors)) { - d->st_errors = rrdset_find_bytype("net_errors", d->name); + d->st_errors = rrdset_find_bytype_localhost("net_errors", d->name); if(!d->st_errors) - d->st_errors = rrdset_create("net_errors", d->name, NULL, d->name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE); + d->st_errors = rrdset_create_localhost("net_errors", d->name, NULL, d->name, "net.errors" + , "Interface Errors", "errors/s", 7002, update_every + , RRDSET_TYPE_LINE); - d->st_errors->isdetail = 1; + rrdset_flag_set(d->st_errors, RRDSET_FLAG_DETAIL); - d->rd_rerrors = rrddim_add(d->st_errors, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); - d->rd_terrors = rrddim_add(d->st_errors, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL); + d->rd_rerrors = rrddim_add(d->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_terrors = rrddim_add(d->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_errors); @@ -290,20 +294,22 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_drops == CONFIG_ONDEMAND_ONDEMAND && (d->rdrops || d->tdrops)))) - d->do_drops = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_drops == CONFIG_BOOLEAN_AUTO && (d->rdrops || d->tdrops)))) + d->do_drops = CONFIG_BOOLEAN_YES; - if(d->do_drops == CONFIG_ONDEMAND_YES) { + if(d->do_drops == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_drops)) { - d->st_drops = rrdset_find_bytype("net_drops", d->name); + d->st_drops = rrdset_find_bytype_localhost("net_drops", d->name); if(!d->st_drops) - d->st_drops = rrdset_create("net_drops", d->name, NULL, d->name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE); + d->st_drops = rrdset_create_localhost("net_drops", d->name, NULL, d->name, "net.drops" + , "Interface Drops", "drops/s", 7003, update_every + , RRDSET_TYPE_LINE); - d->st_drops->isdetail = 1; + rrdset_flag_set(d->st_drops, RRDSET_FLAG_DETAIL); - d->rd_rdrops = rrddim_add(d->st_drops, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL); - d->rd_tdrops = rrddim_add(d->st_drops, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL); + d->rd_rdrops = rrddim_add(d->st_drops, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_tdrops = rrddim_add(d->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_drops); @@ -314,20 +320,22 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_fifo == CONFIG_ONDEMAND_ONDEMAND && (d->rfifo || d->tfifo)))) - d->do_fifo = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_fifo == CONFIG_BOOLEAN_AUTO && (d->rfifo || d->tfifo)))) + d->do_fifo = CONFIG_BOOLEAN_YES; - if(d->do_fifo == CONFIG_ONDEMAND_YES) { + if(d->do_fifo == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_fifo)) { - d->st_fifo = rrdset_find_bytype("net_fifo", d->name); + d->st_fifo = rrdset_find_bytype_localhost("net_fifo", d->name); if(!d->st_fifo) - d->st_fifo = rrdset_create("net_fifo", d->name, NULL, d->name, "net.fifo", "Interface FIFO Buffer Errors", "errors", 7004, update_every, RRDSET_TYPE_LINE); + d->st_fifo = rrdset_create_localhost("net_fifo", d->name, NULL, d->name, "net.fifo" + , "Interface FIFO Buffer Errors", "errors", 7004, update_every + , RRDSET_TYPE_LINE); - d->st_fifo->isdetail = 1; + rrdset_flag_set(d->st_fifo, RRDSET_FLAG_DETAIL); - d->rd_rfifo = rrddim_add(d->st_fifo, "receive", NULL, 1, 1, RRDDIM_INCREMENTAL); - d->rd_tfifo = rrddim_add(d->st_fifo, "transmit", NULL, -1, 1, RRDDIM_INCREMENTAL); + d->rd_rfifo = rrddim_add(d->st_fifo, "receive", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_tfifo = rrddim_add(d->st_fifo, "transmit", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_fifo); @@ -338,19 +346,21 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_compressed == CONFIG_ONDEMAND_ONDEMAND && (d->rcompressed || d->tcompressed)))) - d->do_compressed = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_compressed == CONFIG_BOOLEAN_AUTO && (d->rcompressed || d->tcompressed)))) + d->do_compressed = CONFIG_BOOLEAN_YES; - if(d->do_compressed == CONFIG_ONDEMAND_YES) { + if(d->do_compressed == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_compressed)) { - d->st_compressed = rrdset_find_bytype("net_compressed", d->name); + d->st_compressed = rrdset_find_bytype_localhost("net_compressed", d->name); if(!d->st_compressed) - d->st_compressed = rrdset_create("net_compressed", d->name, NULL, d->name, "net.compressed", "Compressed Packets", "packets/s", 7005, update_every, RRDSET_TYPE_LINE); + d->st_compressed = rrdset_create_localhost("net_compressed", d->name, NULL, d->name + , "net.compressed", "Compressed Packets", "packets/s" + , 7005, update_every, RRDSET_TYPE_LINE); - d->st_compressed->isdetail = 1; + rrdset_flag_set(d->st_compressed, RRDSET_FLAG_DETAIL); - d->rd_rcompressed = rrddim_add(d->st_compressed, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - d->rd_tcompressed = rrddim_add(d->st_compressed, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + d->rd_rcompressed = rrddim_add(d->st_compressed, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_tcompressed = rrddim_add(d->st_compressed, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_compressed); @@ -361,20 +371,22 @@ int do_proc_net_dev(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(unlikely((d->do_events == CONFIG_ONDEMAND_ONDEMAND && (d->rframe || d->tcollisions || d->tcarrier)))) - d->do_events = CONFIG_ONDEMAND_YES; + if(unlikely((d->do_events == CONFIG_BOOLEAN_AUTO && (d->rframe || d->tcollisions || d->tcarrier)))) + d->do_events = CONFIG_BOOLEAN_YES; - if(d->do_events == CONFIG_ONDEMAND_YES) { + if(d->do_events == CONFIG_BOOLEAN_YES) { if(unlikely(!d->st_events)) { - d->st_events = rrdset_find_bytype("net_events", d->name); + d->st_events = rrdset_find_bytype_localhost("net_events", d->name); if(!d->st_events) - d->st_events = rrdset_create("net_events", d->name, NULL, d->name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE); + d->st_events = rrdset_create_localhost("net_events", d->name, NULL, d->name, "net.events" + , "Network Interface Events", "events/s", 7006, update_every + , RRDSET_TYPE_LINE); - d->st_events->isdetail = 1; + rrdset_flag_set(d->st_events, RRDSET_FLAG_DETAIL); - d->rd_rframe = rrddim_add(d->st_events, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL); - d->rd_tcollisions = rrddim_add(d->st_events, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL); - d->rd_tcarrier = rrddim_add(d->st_events, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL); + d->rd_rframe = rrddim_add(d->st_events, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_tcollisions = rrddim_add(d->st_events, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + d->rd_tcarrier = rrddim_add(d->st_events, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(d->st_events); diff --git a/src/proc_net_ip_vs_stats.c b/src/proc_net_ip_vs_stats.c index 96f4660f..16a3234d 100644 --- a/src/proc_net_ip_vs_stats.c +++ b/src/proc_net_ip_vs_stats.c @@ -40,11 +40,13 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_sockets) { - st = rrdset_find(RRD_TYPE_NET_IPVS ".sockets"); + st = rrdset_find_localhost(RRD_TYPE_NET_IPVS ".sockets"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS New Connections", "connections/s", 3101, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL + , "IPVS New Connections", "connections/s", 3101, update_every + , RRDSET_TYPE_LINE); - rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -55,12 +57,13 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_packets) { - st = rrdset_find(RRD_TYPE_NET_IPVS ".packets"); + st = rrdset_find_localhost(RRD_TYPE_NET_IPVS ".packets"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets", "packets/s", 3102, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets" + , "packets/s", 3102, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -72,12 +75,13 @@ int do_proc_net_ip_vs_stats(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_bandwidth) { - st = rrdset_find(RRD_TYPE_NET_IPVS ".net"); + st = rrdset_find_localhost(RRD_TYPE_NET_IPVS ".net"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth", "kilobits/s", 3100, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth" + , "kilobits/s", 3100, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_netstat.c b/src/proc_net_netstat.c index 2235e79b..2677a6c1 100644 --- a/src/proc_net_netstat.c +++ b/src/proc_net_netstat.c @@ -98,19 +98,19 @@ int do_proc_net_netstat(int update_every, usec_t dt) { hash_ipext = simple_hash("IpExt"); hash_tcpext = simple_hash("TcpExt"); - do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND); - do_inerrors = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND); - do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND); - do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND); - do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND); - do_bcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND); - do_ecn = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_ONDEMAND_ONDEMAND); - - do_tcpext_reorder = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_ofo = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND); - do_tcpext_memory = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_ONDEMAND_ONDEMAND); + do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_BOOLEAN_AUTO); + do_inerrors = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_BOOLEAN_AUTO); + do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_BOOLEAN_AUTO); + do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO); + do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_BOOLEAN_AUTO); + do_bcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_BOOLEAN_AUTO); + do_ecn = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_BOOLEAN_AUTO); + + do_tcpext_reorder = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_BOOLEAN_AUTO); + do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO); + do_tcpext_ofo = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO); + do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_BOOLEAN_AUTO); + do_tcpext_memory = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_BOOLEAN_AUTO); arl_ipext = arl_create("netstat/ipext", NULL, 60); arl_tcpext = arl_create("netstat/tcpext", NULL, 60); @@ -118,38 +118,38 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- // IPv4 - if(do_bandwidth != CONFIG_ONDEMAND_NO) { + if(do_bandwidth != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InOctets", &ipext_InOctets); arl_expect(arl_ipext, "OutOctets", &ipext_OutOctets); } - if(do_inerrors != CONFIG_ONDEMAND_NO) { + if(do_inerrors != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InNoRoutes", &ipext_InNoRoutes); arl_expect(arl_ipext, "InTruncatedPkts", &ipext_InTruncatedPkts); arl_expect(arl_ipext, "InCsumErrors", &ipext_InCsumErrors); } - if(do_mcast != CONFIG_ONDEMAND_NO) { + if(do_mcast != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets); arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets); } - if(do_mcast_p != CONFIG_ONDEMAND_NO) { + if(do_mcast_p != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InMcastPkts", &ipext_InMcastPkts); arl_expect(arl_ipext, "OutMcastPkts", &ipext_OutMcastPkts); } - if(do_bcast != CONFIG_ONDEMAND_NO) { + if(do_bcast != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InBcastPkts", &ipext_InBcastPkts); arl_expect(arl_ipext, "OutBcastPkts", &ipext_OutBcastPkts); } - if(do_bcast_p != CONFIG_ONDEMAND_NO) { + if(do_bcast_p != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InBcastOctets", &ipext_InBcastOctets); arl_expect(arl_ipext, "OutBcastOctets", &ipext_OutBcastOctets); } - if(do_ecn != CONFIG_ONDEMAND_NO) { + if(do_ecn != CONFIG_BOOLEAN_NO) { arl_expect(arl_ipext, "InNoECTPkts", &ipext_InNoECTPkts); arl_expect(arl_ipext, "InECT1Pkts", &ipext_InECT1Pkts); arl_expect(arl_ipext, "InECT0Pkts", &ipext_InECT0Pkts); @@ -159,27 +159,27 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- // IPv4 TCP - if(do_tcpext_reorder != CONFIG_ONDEMAND_NO) { + if(do_tcpext_reorder != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder); arl_expect(arl_tcpext, "TCPSACKReorder", &tcpext_TCPSACKReorder); arl_expect(arl_tcpext, "TCPRenoReorder", &tcpext_TCPRenoReorder); arl_expect(arl_tcpext, "TCPTSReorder", &tcpext_TCPTSReorder); } - if(do_tcpext_syscookies != CONFIG_ONDEMAND_NO) { + if(do_tcpext_syscookies != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "SyncookiesSent", &tcpext_SyncookiesSent); arl_expect(arl_tcpext, "SyncookiesRecv", &tcpext_SyncookiesRecv); arl_expect(arl_tcpext, "SyncookiesFailed", &tcpext_SyncookiesFailed); } - if(do_tcpext_ofo != CONFIG_ONDEMAND_NO) { + if(do_tcpext_ofo != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "TCPOFOQueue", &tcpext_TCPOFOQueue); arl_expect(arl_tcpext, "TCPOFODrop", &tcpext_TCPOFODrop); arl_expect(arl_tcpext, "TCPOFOMerge", &tcpext_TCPOFOMerge); arl_expect(arl_tcpext, "OfoPruned", &tcpext_OfoPruned); } - if(do_tcpext_connaborts != CONFIG_ONDEMAND_NO) { + if(do_tcpext_connaborts != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "TCPAbortOnData", &tcpext_TCPAbortOnData); arl_expect(arl_tcpext, "TCPAbortOnClose", &tcpext_TCPAbortOnClose); arl_expect(arl_tcpext, "TCPAbortOnMemory", &tcpext_TCPAbortOnMemory); @@ -188,7 +188,7 @@ int do_proc_net_netstat(int update_every, usec_t dt) { arl_expect(arl_tcpext, "TCPAbortFailed", &tcpext_TCPAbortFailed); } - if(do_tcpext_memory != CONFIG_ONDEMAND_NO) { + if(do_tcpext_memory != CONFIG_BOOLEAN_NO) { arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures); } } @@ -228,14 +228,15 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (ipext_InOctets || ipext_OutOctets))) { - do_bandwidth = CONFIG_ONDEMAND_YES; - st = rrdset_find("system.ipv4"); + if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (ipext_InOctets || ipext_OutOctets))) { + do_bandwidth = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("system.ipv4"); if(unlikely(!st)) { - st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s" + , 500, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "InOctets", "received", 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutOctets", "sent", -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -246,16 +247,17 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (ipext_InNoRoutes || ipext_InTruncatedPkts))) { - do_inerrors = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.inerrors"); + if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && (ipext_InNoRoutes || ipext_InTruncatedPkts))) { + do_inerrors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.inerrors"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors" + , "packets/s", 4000, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -267,15 +269,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (ipext_InMcastOctets || ipext_OutMcastOctets))) { - do_mcast = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.mcast"); + if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (ipext_InMcastOctets || ipext_OutMcastOctets))) { + do_mcast = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.mcast"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth" + , "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -286,15 +289,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (ipext_InBcastOctets || ipext_OutBcastOctets))) { - do_bcast = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.bcast"); + if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (ipext_InBcastOctets || ipext_OutBcastOctets))) { + do_bcast = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.bcast"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth" + , "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -305,15 +309,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (ipext_InMcastPkts || ipext_OutMcastPkts))) { - do_mcast_p = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.mcastpkts"); + if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InMcastPkts || ipext_OutMcastPkts))) { + do_mcast_p = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.mcastpkts"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets" + , "packets/s", 8600, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InMcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InMcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -324,15 +329,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (ipext_InBcastPkts || ipext_OutBcastPkts))) { - do_bcast_p = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.bcastpkts"); + if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InBcastPkts || ipext_OutBcastPkts))) { + do_bcast_p = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.bcastpkts"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets" + , "packets/s", 8500, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InBcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InBcastPkts", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -343,17 +349,18 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) { - do_ecn = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.ecnpkts"); + if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) { + do_ecn = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.ecnpkts"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics" + , "packets/s", 8700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -379,13 +386,14 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPMemoryPressures))) { - do_tcpext_memory = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpmemorypressures"); + if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && (tcpext_TCPMemoryPressures))) { + do_tcpext_memory = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpmemorypressures"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures" + , "events/s", 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "TCPMemoryPressures", "pressures", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "TCPMemoryPressures", "pressures", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -395,18 +403,19 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) { - do_tcpext_connaborts = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpconnaborts"); + if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) { + do_tcpext_connaborts = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpconnaborts"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortOnLinger", "linger", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPAbortFailed", "failed", -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts" + , "connections/s", 3010, update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortOnLinger", "linger", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPAbortFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -420,16 +429,18 @@ int do_proc_net_netstat(int update_every, usec_t dt) { } // -------------------------------------------------------------------- - if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) { - do_tcpext_reorder = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpreorders"); + if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) { + do_tcpext_reorder = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpreorders"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "TCPTSReorder", "timestamp", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPSACKReorder", "sack", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPFACKReorder", "fack", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPRenoReorder", "reno", 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("ipv4", "tcpreorders", NULL, "tcp", NULL + , "TCP Reordered Packets by Detection Method", "packets/s", 3020 + , update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "TCPTSReorder", "timestamp", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPSACKReorder", "sack", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPFACKReorder", "fack", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPRenoReorder", "reno", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -442,16 +453,17 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) { - do_tcpext_ofo = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpofo"); + if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) { + do_tcpext_ofo = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpofo"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue" + , "packets/s", 3050, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPOFODrop", "dropped", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "TCPOFOMerge", "merged", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OfoPruned", "pruned", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPOFODrop", "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "TCPOFOMerge", "merged", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OfoPruned", "pruned", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -464,15 +476,16 @@ int do_proc_net_netstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) { - do_tcpext_syscookies = CONFIG_ONDEMAND_YES; - st = rrdset_find("ipv4.tcpsyncookies"); + if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) { + do_tcpext_syscookies = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("ipv4.tcpsyncookies"); if(unlikely(!st)) { - st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies" + , "packets/s", 3100, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_rpc_nfs.c b/src/proc_net_rpc_nfs.c index e7f6bb6e..0df91963 100644 --- a/src/proc_net_rpc_nfs.c +++ b/src/proc_net_rpc_nfs.c @@ -269,13 +269,14 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_net == 2) { - st = rrdset_find_bytype("nfs", "net"); + st = rrdset_find_bytype_localhost("nfs", "net"); if(!st) { - st = rrdset_create("nfs", "net", NULL, "network", NULL, "NFS Client Network", "operations/s", 5007, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; + st = rrdset_create_localhost("nfs", "net", NULL, "network", NULL, "NFS Client Network", "operations/s", 5007 + , update_every, RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "udp", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "tcp", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -291,14 +292,15 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_rpc == 2) { - st = rrdset_find_bytype("nfs", "rpc"); + st = rrdset_find_bytype_localhost("nfs", "rpc"); if(!st) { - st = rrdset_create("nfs", "rpc", NULL, "rpc", NULL, "NFS Client Remote Procedure Calls Statistics", "calls/s", 5008, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("nfs", "rpc", NULL, "rpc", NULL, "NFS Client Remote Procedure Calls Statistics" + , "calls/s", 5008, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "calls", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "retransmits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "auth_refresh", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -312,12 +314,13 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { if(do_proc2 == 2) { unsigned int i; - st = rrdset_find_bytype("nfs", "proc2"); + st = rrdset_find_bytype_localhost("nfs", "proc2"); if(!st) { - st = rrdset_create("nfs", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Client Remote Procedure Calls", "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfs", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Client Remote Procedure Calls" + , "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfs_proc2_values[i].present ; i++) - rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -331,12 +334,13 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { if(do_proc3 == 2) { unsigned int i; - st = rrdset_find_bytype("nfs", "proc3"); + st = rrdset_find_bytype_localhost("nfs", "proc3"); if(!st) { - st = rrdset_create("nfs", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Client Remote Procedure Calls", "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfs", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Client Remote Procedure Calls" + , "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfs_proc3_values[i].present ; i++) - rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -350,12 +354,13 @@ int do_proc_net_rpc_nfs(int update_every, usec_t dt) { if(do_proc4 == 2) { unsigned int i; - st = rrdset_find_bytype("nfs", "proc4"); + st = rrdset_find_bytype_localhost("nfs", "proc4"); if(!st) { - st = rrdset_create("nfs", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Client Remote Procedure Calls", "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfs", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Client Remote Procedure Calls" + , "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfs_proc4_values[i].present ; i++) - rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_rpc_nfsd.c b/src/proc_net_rpc_nfsd.c index 969910f3..b0ed58d1 100644 --- a/src/proc_net_rpc_nfsd.c +++ b/src/proc_net_rpc_nfsd.c @@ -492,13 +492,14 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_rc == 2) { - st = rrdset_find_bytype("nfsd", "readcache"); + st = rrdset_find_bytype_localhost("nfsd", "readcache"); if(!st) { - st = rrdset_create("nfsd", "readcache", NULL, "cache", NULL, "NFS Server Read Cache", "reads/s", 5000, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfsd", "readcache", NULL, "cache", NULL, "NFS Server Read Cache", "reads/s" + , 5000, update_every, RRDSET_TYPE_STACKED); - rrddim_add(st, "hits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "nocache", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "nocache", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -511,16 +512,17 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_fh == 2) { - st = rrdset_find_bytype("nfsd", "filehandles"); + st = rrdset_find_bytype_localhost("nfsd", "filehandles"); if(!st) { - st = rrdset_create("nfsd", "filehandles", NULL, "filehandles", NULL, "NFS Server File Handles", "handles/s", 5001, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "stale", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "total_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("nfsd", "filehandles", NULL, "filehandles", NULL, "NFS Server File Handles" + , "handles/s", 5001, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "stale", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "total_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -535,12 +537,13 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_io == 2) { - st = rrdset_find_bytype("nfsd", "io"); + st = rrdset_find_bytype_localhost("nfsd", "io"); if(!st) { - st = rrdset_create("nfsd", "io", NULL, "io", NULL, "NFS Server I/O", "kilobytes/s", 5002, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("nfsd", "io", NULL, "io", NULL, "NFS Server I/O", "kilobytes/s", 5002 + , update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "read", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rrddim_add(st, "write", NULL, -1, 1000, RRDDIM_INCREMENTAL); + rrddim_add(st, "read", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "write", NULL, -1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -552,42 +555,47 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_th == 2) { - st = rrdset_find_bytype("nfsd", "threads"); + st = rrdset_find_bytype_localhost("nfsd", "threads"); if(!st) { - st = rrdset_create("nfsd", "threads", NULL, "threads", NULL, "NFS Server Threads", "threads", 5003, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("nfsd", "threads", NULL, "threads", NULL, "NFS Server Threads", "threads", 5003 + , update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "threads", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "threads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "threads", th_threads); rrdset_done(st); - st = rrdset_find_bytype("nfsd", "threads_fullcnt"); + st = rrdset_find_bytype_localhost("nfsd", "threads_fullcnt"); if(!st) { - st = rrdset_create("nfsd", "threads_fullcnt", NULL, "threads", NULL, "NFS Server Threads Full Count", "ops/s", 5004, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("nfsd", "threads_fullcnt", NULL, "threads", NULL + , "NFS Server Threads Full Count", "ops/s", 5004, update_every + , RRDSET_TYPE_LINE); - rrddim_add(st, "full_count", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "full_count", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "full_count", th_fullcnt); rrdset_done(st); - st = rrdset_find_bytype("nfsd", "threads_histogram"); + st = rrdset_find_bytype_localhost("nfsd", "threads_histogram"); if(!st) { - st = rrdset_create("nfsd", "threads_histogram", NULL, "threads", NULL, "NFS Server Threads Usage Histogram", "percentage", 5005, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "0%-10%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "10%-20%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "20%-30%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "30%-40%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "40%-50%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "50%-60%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "60%-70%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "70%-80%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "80%-90%", NULL, 1, 1000, RRDDIM_ABSOLUTE); - rrddim_add(st, "90%-100%", NULL, 1, 1000, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("nfsd", "threads_histogram", NULL, "threads", NULL + , "NFS Server Threads Usage Histogram", "percentage", 5005, update_every + , RRDSET_TYPE_LINE); + + rrddim_add(st, "0%-10%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "10%-20%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "20%-30%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "30%-40%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "40%-50%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "50%-60%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "60%-70%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "70%-80%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "80%-90%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "90%-100%", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -607,21 +615,22 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_ra == 2) { - st = rrdset_find_bytype("nfsd", "readahead"); + st = rrdset_find_bytype_localhost("nfsd", "readahead"); if(!st) { - st = rrdset_create("nfsd", "readahead", NULL, "readahead", NULL, "NFS Server Read Ahead Depth", "percentage", 5005, update_every, RRDSET_TYPE_STACKED); - - rrddim_add(st, "10%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "20%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "30%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "40%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "50%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "60%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "70%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "80%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "90%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "100%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); + st = rrdset_create_localhost("nfsd", "readahead", NULL, "readahead", NULL, "NFS Server Read Ahead Depth" + , "percentage", 5005, update_every, RRDSET_TYPE_STACKED); + + rrddim_add(st, "10%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "20%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "30%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "40%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "50%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "60%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "70%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "80%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "90%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "100%", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "misses", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); } else rrdset_next(st); @@ -645,13 +654,14 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_net == 2) { - st = rrdset_find_bytype("nfsd", "net"); + st = rrdset_find_bytype_localhost("nfsd", "net"); if(!st) { - st = rrdset_create("nfsd", "net", NULL, "network", NULL, "NFS Server Network Statistics", "packets/s", 5007, update_every, RRDSET_TYPE_STACKED); - st->isdetail = 1; + st = rrdset_create_localhost("nfsd", "net", NULL, "network", NULL, "NFS Server Network Statistics" + , "packets/s", 5007, update_every, RRDSET_TYPE_STACKED); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "udp", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "tcp", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -667,14 +677,16 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_rpc == 2) { - st = rrdset_find_bytype("nfsd", "rpc"); + st = rrdset_find_bytype_localhost("nfsd", "rpc"); if(!st) { - st = rrdset_create("nfsd", "rpc", NULL, "rpc", NULL, "NFS Server Remote Procedure Calls Statistics", "calls/s", 5008, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "calls", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "bad_format", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "bad_auth", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("nfsd", "rpc", NULL, "rpc", NULL + , "NFS Server Remote Procedure Calls Statistics", "calls/s", 5008, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "bad_format", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "bad_auth", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -691,12 +703,13 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { if(do_proc2 == 2) { unsigned int i; - st = rrdset_find_bytype("nfsd", "proc2"); + st = rrdset_find_bytype_localhost("nfsd", "proc2"); if(!st) { - st = rrdset_create("nfsd", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Server Remote Procedure Calls", "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfsd", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Server Remote Procedure Calls" + , "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd_proc2_values[i].present ; i++) - rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -710,12 +723,13 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { if(do_proc3 == 2) { unsigned int i; - st = rrdset_find_bytype("nfsd", "proc3"); + st = rrdset_find_bytype_localhost("nfsd", "proc3"); if(!st) { - st = rrdset_create("nfsd", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Server Remote Procedure Calls", "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfsd", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Server Remote Procedure Calls" + , "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd_proc3_values[i].present ; i++) - rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -729,12 +743,13 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { if(do_proc4 == 2) { unsigned int i; - st = rrdset_find_bytype("nfsd", "proc4"); + st = rrdset_find_bytype_localhost("nfsd", "proc4"); if(!st) { - st = rrdset_create("nfsd", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Server Remote Procedure Calls", "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfsd", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Server Remote Procedure Calls" + , "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd_proc4_values[i].present ; i++) - rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -748,12 +763,13 @@ int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { if(do_proc4ops == 2) { unsigned int i; - st = rrdset_find_bytype("nfsd", "proc4ops"); + st = rrdset_find_bytype_localhost("nfsd", "proc4ops"); if(!st) { - st = rrdset_create("nfsd", "proc4ops", NULL, "nfsv2ops", NULL, "NFS v4 Server Operations", "operations/s", 5012, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("nfsd", "proc4ops", NULL, "nfsv2ops", NULL, "NFS v4 Server Operations" + , "operations/s", 5012, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd4_ops_values[i].present ; i++) - rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_snmp.c b/src/proc_net_snmp.c index 7707d3b7..ba7b4001 100644 --- a/src/proc_net_snmp.c +++ b/src/proc_net_snmp.c @@ -392,14 +392,15 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_ip_packets) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".packets"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".packets"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets" + , "packets/s", 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InReceives", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutRequests", "sent", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InDelivers", "delivered", 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -413,14 +414,16 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_ip_fragsout) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsout"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsout"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "FragOKs", "ok", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "FragFails", "failed", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "FragCreates", "created", 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL + , "IPv4 Fragments Sent", "packets/s", 3010, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -433,14 +436,16 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_ip_fragsin) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".fragsin"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsin"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ReasmFails", "failed", -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ReasmReqds", "all", 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL + , "IPv4 Fragments Reassembly", "packets/s", 3011, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -453,19 +458,20 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_ip_errors) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".errors"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".errors"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors" + , "packets/s", 3002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -497,12 +503,13 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_icmp_packets) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".icmp"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s", 2602, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets" + , "packets/s", 2602, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -511,13 +518,15 @@ int do_proc_net_snmp(int update_every, usec_t dt) { rrdset_done(st); - st = rrdset_find(RRD_TYPE_NET_SNMP ".icmp_errors"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp_errors"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors", "packets/s", 2603, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp_errors", NULL, "icmp", NULL + , "IPv4 ICMP Errors", "packets/s", 2603, update_every + , RRDSET_TYPE_LINE); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -543,12 +552,13 @@ int do_proc_net_snmp(int update_every, usec_t dt) { if(do_icmpmsg) { int i; - st = rrdset_find(RRD_TYPE_NET_SNMP ".icmpmsg"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmpmsg"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages", "packets/s", 2604, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages" + , "packets/s", 2604, update_every, RRDSET_TYPE_LINE); for(i = 0; icmpmsg_data[i].name ;i++) - rrddim_add(st, icmpmsg_data[i].name, icmpmsg_data[i].label, icmpmsg_data[i].multiplier, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, icmpmsg_data[i].name, icmpmsg_data[i].label, icmpmsg_data[i].multiplier, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -578,11 +588,12 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html if(do_tcp_sockets) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".tcpsock"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcpsock"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections", "active connections", 2500, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections" + , "active connections", 2500, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "CurrEstab", "connections", 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -593,12 +604,13 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_tcp_packets) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".tcppackets"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcppackets"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets", "packets/s", 2600, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets" + , "packets/s", 2600, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -610,14 +622,15 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_tcp_errors) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".tcperrors"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcperrors"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors", "packets/s", 2700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors" + , "packets/s", 2700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -630,16 +643,18 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_tcp_handshake) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".tcphandshake"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcphandshake"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", NULL, "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutRsts", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", NULL + , "IPv4 TCP Handshake Issues", "events/s", 2900, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutRsts", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -671,12 +686,13 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // see http://net-snmp.sourceforge.net/docs/mibs/udp.html if(do_udp_packets) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".udppackets"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udppackets"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets", "packets/s", 2601, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets" + , "packets/s", 2601, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -688,17 +704,18 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_udp_errors) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".udperrors"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udperrors"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s", 2701, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors" + , "events/s", 2701, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -730,12 +747,14 @@ int do_proc_net_snmp(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_udplite_packets) { - st = rrdset_find(RRD_TYPE_NET_SNMP ".udplite"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "udplite", NULL, "udplite", NULL, "IPv4 UDPLite Packets", "packets/s", 2603, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite", NULL, "udplite", NULL + , "IPv4 UDPLite Packets", "packets/s", 2603, update_every + , RRDSET_TYPE_LINE); - rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -743,16 +762,18 @@ int do_proc_net_snmp(int update_every, usec_t dt) { rrddim_set(st, "OutDatagrams", *udplite_OutDatagrams); rrdset_done(st); - st = rrdset_find(RRD_TYPE_NET_SNMP ".udplite_errors"); + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite_errors"); if(!st) { - st = rrdset_create(RRD_TYPE_NET_SNMP, "udplite_errors", NULL, "udplite", NULL, "IPv4 UDPLite Errors", "packets/s", 2604, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite_errors", NULL, "udplite", NULL + , "IPv4 UDPLite Errors", "packets/s", 2604, update_every + , RRDSET_TYPE_LINE); + + rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_snmp6.c b/src/proc_net_snmp6.c index 27859215..8c4581c1 100644 --- a/src/proc_net_snmp6.c +++ b/src/proc_net_snmp6.c @@ -126,28 +126,28 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { static unsigned long long UdpLite6InCsumErrors = 0ULL; if(unlikely(!arl_base)) { - do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND); - do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND); - do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND); - do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND); - do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_ONDEMAND_ONDEMAND); - do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_ONDEMAND_ONDEMAND); - do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_ONDEMAND_ONDEMAND); - do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_ONDEMAND_ONDEMAND); - do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_ONDEMAND_ONDEMAND); - do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND); - do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND); - do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_ONDEMAND_ONDEMAND); - do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_ONDEMAND_ONDEMAND); - do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_ONDEMAND_ONDEMAND); - do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_ONDEMAND_ONDEMAND); + do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 packets", CONFIG_BOOLEAN_AUTO); + do_ip_fragsout = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO); + do_ip_fragsin = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 fragments assembly", CONFIG_BOOLEAN_AUTO); + do_ip_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 errors", CONFIG_BOOLEAN_AUTO); + do_udp_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP packets", CONFIG_BOOLEAN_AUTO); + do_udp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDP errors", CONFIG_BOOLEAN_AUTO); + do_udplite_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite packets", CONFIG_BOOLEAN_AUTO); + do_udplite_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ipv6 UDPlite errors", CONFIG_BOOLEAN_AUTO); + do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "bandwidth", CONFIG_BOOLEAN_AUTO); + do_mcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast bandwidth", CONFIG_BOOLEAN_AUTO); + do_bcast = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO); + do_mcast_p = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "multicast packets", CONFIG_BOOLEAN_AUTO); + do_icmp = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp", CONFIG_BOOLEAN_AUTO); + do_icmp_redir = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp redirects", CONFIG_BOOLEAN_AUTO); + do_icmp_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp errors", CONFIG_BOOLEAN_AUTO); + do_icmp_echos = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp echos", CONFIG_BOOLEAN_AUTO); + do_icmp_groupmemb = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp group membership", CONFIG_BOOLEAN_AUTO); + do_icmp_router = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp router", CONFIG_BOOLEAN_AUTO); + do_icmp_neighbor = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp neighbor", CONFIG_BOOLEAN_AUTO); + do_icmp_mldv2 = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp mldv2", CONFIG_BOOLEAN_AUTO); + do_icmp_types = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "icmp types", CONFIG_BOOLEAN_AUTO); + do_ect = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp6", "ect", CONFIG_BOOLEAN_AUTO); arl_base = arl_create("snmp6", NULL, 60); arl_expect(arl_base, "Ip6InReceives", &Ip6InReceives); @@ -276,14 +276,15 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (Ip6InOctets || Ip6OutOctets))) { - do_bandwidth = CONFIG_ONDEMAND_YES; - st = rrdset_find("system.ipv6"); + if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (Ip6InOctets || Ip6OutOctets))) { + do_bandwidth = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost("system.ipv6"); if(unlikely(!st)) { - st = rrdset_create("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500 + , update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -294,16 +295,17 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_packets == CONFIG_ONDEMAND_YES || (do_ip_packets == CONFIG_ONDEMAND_ONDEMAND && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) { - do_ip_packets = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".packets"); + if(do_ip_packets == CONFIG_BOOLEAN_YES || (do_ip_packets == CONFIG_BOOLEAN_AUTO && (Ip6InReceives || Ip6OutRequests || Ip6InDelivers || Ip6OutForwDatagrams))) { + do_ip_packets = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".packets"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "packets", NULL, "packets", NULL, "IPv6 Packets" + , "packets/s", 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "forwarded", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "delivers", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -316,16 +318,17 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_fragsout == CONFIG_ONDEMAND_YES || (do_ip_fragsout == CONFIG_ONDEMAND_ONDEMAND && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) { - do_ip_fragsout = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsout"); + if(do_ip_fragsout == CONFIG_BOOLEAN_YES || (do_ip_fragsout == CONFIG_BOOLEAN_AUTO && (Ip6FragOKs || Ip6FragFails || Ip6FragCreates))) { + do_ip_fragsout = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".fragsout"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent", "packets/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent" + , "packets/s", 3010, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -337,23 +340,25 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_fragsin == CONFIG_ONDEMAND_YES || (do_ip_fragsin == CONFIG_ONDEMAND_ONDEMAND + if(do_ip_fragsin == CONFIG_BOOLEAN_YES || (do_ip_fragsin == CONFIG_BOOLEAN_AUTO && ( Ip6ReasmOKs || Ip6ReasmFails || Ip6ReasmTimeout || Ip6ReasmReqds ))) { - do_ip_fragsin = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".fragsin"); + do_ip_fragsin = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".fragsin"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly", "packets/s", 3011, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "fragsin", NULL, "fragments", NULL + , "IPv6 Fragments Reassembly", "packets/s", 3011, update_every + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "ok", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "all", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -366,7 +371,7 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ip_errors == CONFIG_ONDEMAND_YES || (do_ip_errors == CONFIG_ONDEMAND_ONDEMAND + if(do_ip_errors == CONFIG_BOOLEAN_YES || (do_ip_errors == CONFIG_BOOLEAN_AUTO && ( Ip6InDiscards || Ip6OutDiscards @@ -377,23 +382,24 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Ip6InTruncatedPkts || Ip6InNoRoutes ))) { - do_ip_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".errors"); + do_ip_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".errors"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s" + , 3002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTooBigErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -413,14 +419,15 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_udp_packets == CONFIG_ONDEMAND_YES || (do_udp_packets == CONFIG_ONDEMAND_ONDEMAND && (Udp6InDatagrams || Udp6OutDatagrams))) { - do_udp_packets = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udppackets"); + if(do_udp_packets == CONFIG_BOOLEAN_YES || (do_udp_packets == CONFIG_BOOLEAN_AUTO && (Udp6InDatagrams || Udp6OutDatagrams))) { + do_udp_packets = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udppackets"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "udppackets", NULL, "udp", NULL, "IPv6 UDP Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udppackets", NULL, "udp", NULL, "IPv6 UDP Packets" + , "packets/s", 3601, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -431,7 +438,7 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_udp_errors == CONFIG_ONDEMAND_YES || (do_udp_errors == CONFIG_ONDEMAND_ONDEMAND + if(do_udp_errors == CONFIG_BOOLEAN_YES || (do_udp_errors == CONFIG_BOOLEAN_AUTO && ( Udp6InErrors || Udp6NoPorts @@ -440,18 +447,19 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Udp6InCsumErrors || Udp6IgnoredMulti ))) { - do_udp_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udperrors"); + do_udp_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udperrors"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "udperrors", NULL, "udp", NULL, "IPv6 UDP Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udperrors", NULL, "udp", NULL, "IPv6 UDP Errors" + , "events/s", 3701, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -466,14 +474,15 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_udplite_packets == CONFIG_ONDEMAND_YES || (do_udplite_packets == CONFIG_ONDEMAND_ONDEMAND && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) { - do_udplite_packets = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udplitepackets"); + if(do_udplite_packets == CONFIG_BOOLEAN_YES || (do_udplite_packets == CONFIG_BOOLEAN_AUTO && (UdpLite6InDatagrams || UdpLite6OutDatagrams))) { + do_udplite_packets = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udplitepackets"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "udplitepackets", NULL, "udplite", NULL, "IPv6 UDPlite Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udplitepackets", NULL, "udplite", NULL + , "IPv6 UDPlite Packets", "packets/s", 3601, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -484,7 +493,7 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_udplite_errors == CONFIG_ONDEMAND_YES || (do_udplite_errors == CONFIG_ONDEMAND_ONDEMAND + if(do_udplite_errors == CONFIG_BOOLEAN_YES || (do_udplite_errors == CONFIG_BOOLEAN_AUTO && ( UdpLite6InErrors || UdpLite6NoPorts @@ -493,17 +502,18 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Udp6InCsumErrors || UdpLite6InCsumErrors ))) { - do_udplite_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".udpliteerrors"); + do_udplite_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".udpliteerrors"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "udpliteerrors", NULL, "udplite", NULL, "IPv6 UDP Lite Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "udpliteerrors", NULL, "udplite", NULL + , "IPv6 UDP Lite Errors", "events/s", 3701, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -517,15 +527,17 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastOctets || Ip6InMcastOctets))) { - do_mcast = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcast"); + if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (Ip6OutMcastOctets || Ip6InMcastOctets))) { + do_mcast = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".mcast"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcast", NULL, "multicast", NULL, "IPv6 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "mcast", NULL, "multicast", NULL + , "IPv6 Multicast Bandwidth", "kilobits/s", 9000, update_every + , RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -536,15 +548,17 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutBcastOctets || Ip6InBcastOctets))) { - do_bcast = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".bcast"); + if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (Ip6OutBcastOctets || Ip6InBcastOctets))) { + do_bcast = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".bcast"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "bcast", NULL, "broadcast", NULL, "IPv6 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "bcast", NULL, "broadcast", NULL + , "IPv6 Broadcast Bandwidth", "kilobits/s", 8000, update_every + , RRDSET_TYPE_AREA); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -555,15 +569,16 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (Ip6OutMcastPkts || Ip6InMcastPkts))) { - do_mcast_p = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".mcastpkts"); + if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (Ip6OutMcastPkts || Ip6InMcastPkts))) { + do_mcast_p = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".mcastpkts"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "mcastpkts", NULL, "multicast", NULL, "IPv6 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "mcastpkts", NULL, "multicast", NULL + , "IPv6 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -574,14 +589,15 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp == CONFIG_ONDEMAND_YES || (do_icmp == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMsgs || Icmp6OutMsgs))) { - do_icmp = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmp"); + if(do_icmp == CONFIG_BOOLEAN_YES || (do_icmp == CONFIG_BOOLEAN_AUTO && (Icmp6InMsgs || Icmp6OutMsgs))) { + do_icmp = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmp"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages", "messages/s", 10000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages" + , "messages/s", 10000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -592,14 +608,15 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_redir == CONFIG_ONDEMAND_YES || (do_icmp_redir == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InRedirects || Icmp6OutRedirects))) { - do_icmp_redir = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpredir"); + if(do_icmp_redir == CONFIG_BOOLEAN_YES || (do_icmp_redir == CONFIG_BOOLEAN_AUTO && (Icmp6InRedirects || Icmp6OutRedirects))) { + do_icmp_redir = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpredir"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects", "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects" + , "redirects/s", 10050, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -610,7 +627,7 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_errors == CONFIG_ONDEMAND_YES || (do_icmp_errors == CONFIG_ONDEMAND_ONDEMAND + if(do_icmp_errors == CONFIG_BOOLEAN_YES || (do_icmp_errors == CONFIG_BOOLEAN_AUTO && ( Icmp6InErrors || Icmp6OutErrors @@ -624,23 +641,24 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutTimeExcds || Icmp6OutParmProblems ))) { - do_icmp_errors = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmperrors"); + do_icmp_errors = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmperrors"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL); - - rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors" + , "errors/s", 10100, update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + + rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InParmProblems", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutPktTooBigs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -660,22 +678,23 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_echos == CONFIG_ONDEMAND_YES || (do_icmp_echos == CONFIG_ONDEMAND_ONDEMAND + if(do_icmp_echos == CONFIG_BOOLEAN_YES || (do_icmp_echos == CONFIG_BOOLEAN_AUTO && ( Icmp6InEchos || Icmp6OutEchos || Icmp6InEchoReplies || Icmp6OutEchoReplies ))) { - do_icmp_echos = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpechos"); + do_icmp_echos = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpechos"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo" + , "messages/s", 10200, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InEchos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchos", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -688,7 +707,7 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_groupmemb == CONFIG_ONDEMAND_YES || (do_icmp_groupmemb == CONFIG_ONDEMAND_ONDEMAND + if(do_icmp_groupmemb == CONFIG_BOOLEAN_YES || (do_icmp_groupmemb == CONFIG_BOOLEAN_AUTO && ( Icmp6InGroupMembQueries || Icmp6OutGroupMembQueries @@ -697,17 +716,19 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6InGroupMembReductions || Icmp6OutGroupMembReductions ))) { - do_icmp_groupmemb = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".groupmemb"); + do_icmp_groupmemb = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".groupmemb"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "groupmemb", NULL, "icmp", NULL, "IPv6 ICMP Group Membership", "messages/s", 10300, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InQueries", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutQueries", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InResponses", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutResponses", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InReductions", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutReductions", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "groupmemb", NULL, "icmp", NULL + , "IPv6 ICMP Group Membership", "messages/s", 10300, update_every + , RRDSET_TYPE_LINE); + + rrddim_add(st, "InQueries", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutQueries", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InResponses", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutResponses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InReductions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutReductions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -722,22 +743,23 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_router == CONFIG_ONDEMAND_YES || (do_icmp_router == CONFIG_ONDEMAND_ONDEMAND + if(do_icmp_router == CONFIG_BOOLEAN_YES || (do_icmp_router == CONFIG_BOOLEAN_AUTO && ( Icmp6InRouterSolicits || Icmp6OutRouterSolicits || Icmp6InRouterAdvertisements || Icmp6OutRouterAdvertisements ))) { - do_icmp_router = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmprouter"); + do_icmp_router = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmprouter"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages" + , "messages/s", 10400, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -750,22 +772,24 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_neighbor == CONFIG_ONDEMAND_YES || (do_icmp_neighbor == CONFIG_ONDEMAND_ONDEMAND + if(do_icmp_neighbor == CONFIG_BOOLEAN_YES || (do_icmp_neighbor == CONFIG_BOOLEAN_AUTO && ( Icmp6InNeighborSolicits || Icmp6OutNeighborSolicits || Icmp6InNeighborAdvertisements || Icmp6OutNeighborAdvertisements ))) { - do_icmp_neighbor = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpneighbor"); + do_icmp_neighbor = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpneighbor"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpneighbor", NULL, "icmp", NULL + , "IPv6 Neighbor Messages", "messages/s", 10500, update_every + , RRDSET_TYPE_LINE); + + rrddim_add(st, "InSolicits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutSolicits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -778,14 +802,15 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_mldv2 == CONFIG_ONDEMAND_YES || (do_icmp_mldv2 == CONFIG_ONDEMAND_ONDEMAND && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) { - do_icmp_mldv2 = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmpmldv2"); + if(do_icmp_mldv2 == CONFIG_BOOLEAN_YES || (do_icmp_mldv2 == CONFIG_BOOLEAN_AUTO && (Icmp6InMLDv2Reports || Icmp6OutMLDv2Reports))) { + do_icmp_mldv2 = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmpmldv2"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmpmldv2", NULL, "icmp", NULL, "IPv6 ICMP MLDv2 Reports", "reports/s", 10600, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmpmldv2", NULL, "icmp", NULL, "IPv6 ICMP MLDv2 Reports" + , "reports/s", 10600, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -796,7 +821,7 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_icmp_types == CONFIG_ONDEMAND_YES || (do_icmp_types == CONFIG_ONDEMAND_ONDEMAND + if(do_icmp_types == CONFIG_BOOLEAN_YES || (do_icmp_types == CONFIG_BOOLEAN_AUTO && ( Icmp6InType1 || Icmp6InType128 @@ -809,21 +834,22 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { || Icmp6OutType135 || Icmp6OutType143 ))) { - do_icmp_types = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".icmptypes"); + do_icmp_types = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".icmptypes"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types", "messages/s", 10700, update_every, RRDSET_TYPE_LINE); - - rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types" + , "messages/s", 10700, update_every, RRDSET_TYPE_LINE); + + rrddim_add(st, "InType1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType128", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType129", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InType136", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType1", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -842,22 +868,23 @@ int do_proc_net_snmp6(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ect == CONFIG_ONDEMAND_YES || (do_ect == CONFIG_ONDEMAND_ONDEMAND + if(do_ect == CONFIG_BOOLEAN_YES || (do_ect == CONFIG_BOOLEAN_AUTO && ( Ip6InNoECTPkts || Ip6InECT1Pkts || Ip6InECT0Pkts || Ip6InCEPkts ))) { - do_ect = CONFIG_ONDEMAND_YES; - st = rrdset_find(RRD_TYPE_NET_SNMP6 ".ect"); + do_ect = CONFIG_BOOLEAN_YES; + st = rrdset_find_localhost(RRD_TYPE_NET_SNMP6 ".ect"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_SNMP6, "ect", NULL, "packets", NULL, "IPv6 ECT Packets", "packets/s", 10800, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_SNMP6, "ect", NULL, "packets", NULL, "IPv6 ECT Packets" + , "packets/s", 10800, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "InCEPkts", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "InNoECTPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InECT1Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InECT0Pkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "InCEPkts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_softnet_stat.c b/src/proc_net_softnet_stat.c index ed6d8db7..40946a7a 100644 --- a/src/proc_net_softnet_stat.c +++ b/src/proc_net_softnet_stat.c @@ -77,12 +77,13 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("system", "softnet_stat"); + st = rrdset_find_bytype_localhost("system", "softnet_stat"); if(unlikely(!st)) { - st = rrdset_create("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat", "events/s", 955, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat" + , "events/s", 955, update_every, RRDSET_TYPE_LINE); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) - rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -97,15 +98,16 @@ int do_proc_net_softnet_stat(int update_every, usec_t dt) { char id[50+1]; snprintfz(id, 50, "cpu%zu_softnet_stat", l); - st = rrdset_find_bytype("cpu", id); + st = rrdset_find_bytype_localhost("cpu", id); if(unlikely(!st)) { char title[100+1]; snprintfz(title, 100, "CPU%zu softnet_stat", l); - st = rrdset_create("cpu", id, NULL, "softnet_stat", NULL, title, "events/s", 4101 + l, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("cpu", id, NULL, "softnet_stat", NULL, title, "events/s", 4101 + l + , update_every, RRDSET_TYPE_LINE); for(w = 0; w < allocated_columns ;w++) if(unlikely(softnet_column_name(w))) - rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, softnet_column_name(w), NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_stat_conntrack.c b/src/proc_net_stat_conntrack.c index 7a90683b..e04b80a3 100644 --- a/src/proc_net_stat_conntrack.c +++ b/src/proc_net_stat_conntrack.c @@ -47,7 +47,7 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { if(!do_sockets && !read_full) return 1; - rrdvar_max = rrdvar_custom_host_variable_create(&localhost, "netfilter.conntrack.max"); + rrdvar_max = rrdvar_custom_host_variable_create(localhost, "netfilter.conntrack.max"); } if(likely(read_full)) { @@ -130,11 +130,13 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_sockets) { - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 3000, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL + , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections" + , "active connections", 3000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "connections", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -145,13 +147,15 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_new) { - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 3001, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL + , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections" + , "connections/s", 3001, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "ignore", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -164,14 +168,16 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_changes) { - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 3002, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "delete_list", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL + , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s" + , 3002, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "inserted", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "delete_list", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -184,14 +190,16 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_expect) { - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 3003, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL + , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations" + , "expectations/s", 3003, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "created", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "deleted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "new", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -204,14 +212,16 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_search) { - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 3010, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "restarted", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "found", NULL, 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL + , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches" + , "searches/s", 3010, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "searched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "restarted", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "found", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -224,15 +234,17 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(do_errors) { - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 3005, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "insert_failed", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "drop", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "early_drop", NULL, -1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL + , RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s" + , 3005, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "icmp_error", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "insert_failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "early_drop", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_net_stat_synproxy.c b/src/proc_net_stat_synproxy.c index 688e8c7c..5a1fc30e 100644 --- a/src/proc_net_stat_synproxy.c +++ b/src/proc_net_stat_synproxy.c @@ -10,10 +10,10 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { static procfile *ff = NULL; if(unlikely(do_entries == -1)) { - do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND); - do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND); - do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND); - do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND); + do_entries = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_BOOLEAN_AUTO); + do_cookies = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_BOOLEAN_AUTO); + do_syns = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_BOOLEAN_AUTO); + do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_BOOLEAN_AUTO); } if(unlikely(!ff)) { @@ -57,14 +57,16 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if((do_entries == CONFIG_ONDEMAND_ONDEMAND && events) || do_entries == CONFIG_ONDEMAND_YES) { - do_entries = CONFIG_ONDEMAND_YES; + if((do_entries == CONFIG_BOOLEAN_AUTO && events) || do_entries == CONFIG_BOOLEAN_YES) { + do_entries = CONFIG_BOOLEAN_YES; - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 3304, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL + , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 3304 + , update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "entries", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -74,14 +76,16 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if((do_syns == CONFIG_ONDEMAND_ONDEMAND && events) || do_syns == CONFIG_ONDEMAND_YES) { - do_syns = CONFIG_ONDEMAND_YES; + if((do_syns == CONFIG_BOOLEAN_AUTO && events) || do_syns == CONFIG_BOOLEAN_YES) { + do_syns = CONFIG_BOOLEAN_YES; - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 3301, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL + , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s" + , 3301, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -91,14 +95,16 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if((do_reopened == CONFIG_ONDEMAND_ONDEMAND && events) || do_reopened == CONFIG_ONDEMAND_YES) { - do_reopened = CONFIG_ONDEMAND_YES; + if((do_reopened == CONFIG_BOOLEAN_AUTO && events) || do_reopened == CONFIG_BOOLEAN_YES) { + do_reopened = CONFIG_BOOLEAN_YES; - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 3303, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL + , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened" + , "connections/s", 3303, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "reopened", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -108,16 +114,18 @@ int do_proc_net_stat_synproxy(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if((do_cookies == CONFIG_ONDEMAND_ONDEMAND && events) || do_cookies == CONFIG_ONDEMAND_YES) { - do_cookies = CONFIG_ONDEMAND_YES; + if((do_cookies == CONFIG_BOOLEAN_AUTO && events) || do_cookies == CONFIG_BOOLEAN_YES) { + do_cookies = CONFIG_BOOLEAN_YES; - st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies"); + st = rrdset_find_localhost(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies"); if(unlikely(!st)) { - st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 3302, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL + , RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 3302 + , update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "retransmits", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "valid", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "invalid", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "retransmits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); diff --git a/src/proc_self_mountinfo.c b/src/proc_self_mountinfo.c index 780c2af7..bb031a9a 100644 --- a/src/proc_self_mountinfo.c +++ b/src/proc_self_mountinfo.c @@ -293,7 +293,7 @@ struct mountinfo *mountinfo_read(int do_statvfs) { struct mountinfo *mt; for(mt = root; mt; mt = mt->next) { - if(unlikely(mt->st_dev == mi->st_dev && !(mi->flags & MOUNTINFO_NO_STAT))) { + if(unlikely(mt->st_dev == mi->st_dev && !(mt->flags & MOUNTINFO_IS_SAME_DEV))) { if(strlen(mi->mount_point) < strlen(mt->mount_point)) mt->flags |= MOUNTINFO_IS_SAME_DEV; else @@ -319,7 +319,7 @@ struct mountinfo *mountinfo_read(int do_statvfs) { } // check if it has size - if(do_statvfs) { + if(do_statvfs && !(mi->flags & MOUNTINFO_IS_DUMMY)) { struct statvfs buff_statvfs; if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) { mi->flags |= MOUNTINFO_NO_STAT; diff --git a/src/proc_softirqs.c b/src/proc_softirqs.c index 9eb72cd3..560e2acb 100644 --- a/src/proc_softirqs.c +++ b/src/proc_softirqs.c @@ -128,8 +128,9 @@ int do_proc_softirqs(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find_bytype("system", "softirqs"); - if(unlikely(!st)) st = rrdset_create("system", "softirqs", NULL, "softirqs", NULL, "System softirqs", "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED); + st = rrdset_find_bytype_localhost("system", "softirqs"); + if(unlikely(!st)) st = rrdset_create_localhost("system", "softirqs", NULL, "softirqs", NULL, "System softirqs" + , "softirqs/s", 950, update_every, RRDSET_TYPE_STACKED); else rrdset_next(st); for(l = 0; l < lines ;l++) { @@ -141,7 +142,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { if(unlikely(!irr->rd || strncmp(irr->name, irr->rd->name, MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_find(st, irr->id); if(unlikely(!irr->rd)) - irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); + irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); else rrddim_set_name(st, irr->rd, irr->name); @@ -163,7 +164,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { char id[50+1]; snprintfz(id, 50, "cpu%d_softirqs", c); - st = rrdset_find_bytype("cpu", id); + st = rrdset_find_bytype_localhost("cpu", id); if(unlikely(!st)) { // find if everything is zero unsigned long long core_sum = 0 ; @@ -176,7 +177,8 @@ int do_proc_softirqs(int update_every, usec_t dt) { char title[100+1]; snprintfz(title, 100, "CPU%d softirqs", c); - st = rrdset_create("cpu", id, NULL, "softirqs", "cpu.softirqs", title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost("cpu", id, NULL, "softirqs", "cpu.softirqs", title, "softirqs/s", 3000 + c + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st); @@ -186,7 +188,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { if(unlikely(!irr->cpu[c].rd)) { irr->cpu[c].rd = rrddim_find(st, irr->id); if(unlikely(!irr->cpu[c].rd)) - irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); + irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); else rrddim_set_name(st, irr->cpu[c].rd, irr->name); } diff --git a/src/proc_stat.c b/src/proc_stat.c index d52de1b2..04f0896c 100644 --- a/src/proc_stat.c +++ b/src/proc_stat.c @@ -91,24 +91,25 @@ int do_proc_stat(int update_every, usec_t dt) { } if(likely((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores))) { - st = rrdset_find_bytype(type, id); + st = rrdset_find_bytype_localhost(type, id); if(unlikely(!st)) { - st = rrdset_create(type, id, NULL, family, context, title, "percentage", priority, update_every, RRDSET_TYPE_STACKED); + st = rrdset_create_localhost(type, id, NULL, family, context, title, "percentage", priority + , update_every, RRDSET_TYPE_STACKED); long multiplier = 1; long divisor = 1; // sysconf(_SC_CLK_TCK); - rrddim_add(st, "guest_nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "guest", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "steal", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "softirq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "irq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "user", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "system", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - rrddim_add(st, "iowait", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); - - rrddim_add(st, "idle", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "guest_nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "guest", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "steal", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "softirq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "irq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "user", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "system", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + rrddim_add(st, "iowait", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); + + rrddim_add(st, "idle", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } else rrdset_next(st); @@ -132,12 +133,13 @@ int do_proc_stat(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(likely(do_interrupts)) { - st = rrdset_find_bytype("system", "intr"); + st = rrdset_find_bytype_localhost("system", "intr"); if(unlikely(!st)) { - st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts" + , "interrupts/s", 900, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -151,11 +153,12 @@ int do_proc_stat(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(likely(do_context)) { - st = rrdset_find_bytype("system", "ctxt"); + st = rrdset_find_bytype_localhost("system", "ctxt"); if(unlikely(!st)) { - st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches" + , "context switches/s", 800, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -177,12 +180,13 @@ int do_proc_stat(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(likely(do_forks)) { - st = rrdset_find_bytype("system", "forks"); + st = rrdset_find_bytype_localhost("system", "forks"); if(unlikely(!st)) { - st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; + st = rrdset_create_localhost("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s" + , 700, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); - rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); @@ -193,12 +197,13 @@ int do_proc_stat(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(likely(do_processes)) { - st = rrdset_find_bytype("system", "processes"); + st = rrdset_find_bytype_localhost("system", "processes"); if(unlikely(!st)) { - st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("system", "processes", NULL, "processes", NULL, "System Processes", "processes" + , 600, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE); + rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/proc_sys_kernel_random_entropy_avail.c b/src/proc_sys_kernel_random_entropy_avail.c index 25dbca83..fea8900d 100644 --- a/src/proc_sys_kernel_random_entropy_avail.c +++ b/src/proc_sys_kernel_random_entropy_avail.c @@ -17,10 +17,11 @@ int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) { unsigned long long entropy = str2ull(procfile_lineword(ff, 0, 0)); - RRDSET *st = rrdset_find_bytype("system", "entropy"); + RRDSET *st = rrdset_find_bytype_localhost("system", "entropy"); if(unlikely(!st)) { - st = rrdset_create("system", "entropy", NULL, "entropy", NULL, "Available Entropy", "entropy", 1000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "entropy", NULL, 1, 1, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "entropy", NULL, "entropy", NULL, "Available Entropy", "entropy", 1000 + , update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "entropy", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/proc_uptime.c b/src/proc_uptime.c index 8dd10b1f..f74cccb9 100644 --- a/src/proc_uptime.c +++ b/src/proc_uptime.c @@ -39,11 +39,12 @@ int do_proc_uptime(int update_every, usec_t dt) { // -------------------------------------------------------------------- if(unlikely(!st)) - st = rrdset_find("system.uptime"); + st = rrdset_find_localhost("system.uptime"); if(unlikely(!st)) { - st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "uptime", NULL, 1, 1000, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000 + , update_every, RRDSET_TYPE_LINE); + rrddim_add(st, "uptime", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/proc_vmstat.c b/src/proc_vmstat.c index 748fa348..84748736 100644 --- a/src/proc_vmstat.c +++ b/src/proc_vmstat.c @@ -25,10 +25,10 @@ int do_proc_vmstat(int update_every, usec_t dt) { static unsigned long long pswpout = 0ULL; if(unlikely(!arl_base)) { - do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_ONDEMAND_ONDEMAND); + do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_BOOLEAN_AUTO); do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1); do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1); - do_numa = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_ONDEMAND_ONDEMAND); + do_numa = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_BOOLEAN_AUTO); arl_base = arl_create("vmstat", NULL, 60); @@ -39,7 +39,7 @@ int do_proc_vmstat(int update_every, usec_t dt) { arl_expect(arl_base, "pswpin", &pswpin); arl_expect(arl_base, "pswpout", &pswpout); - if(do_numa == CONFIG_ONDEMAND_YES || (do_numa == CONFIG_ONDEMAND_ONDEMAND && get_numa_node_count() >= 2)) { + if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && get_numa_node_count() >= 2)) { arl_expect(arl_base, "numa_foreign", &numa_foreign); arl_expect(arl_base, "numa_hint_faults_local", &numa_hint_faults_local); arl_expect(arl_base, "numa_hint_faults", &numa_hint_faults); @@ -56,7 +56,7 @@ int do_proc_vmstat(int update_every, usec_t dt) { // when all the expected metrics are collected. // Also ARL will not parse their values. has_numa = 0; - do_numa = CONFIG_ONDEMAND_NO; + do_numa = CONFIG_BOOLEAN_NO; } } @@ -87,15 +87,16 @@ int do_proc_vmstat(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(pswpin || pswpout || do_swapio == CONFIG_ONDEMAND_YES) { - do_swapio = CONFIG_ONDEMAND_YES; + if(pswpin || pswpout || do_swapio == CONFIG_BOOLEAN_YES) { + do_swapio = CONFIG_BOOLEAN_YES; static RRDSET *st_swapio = NULL; if(unlikely(!st_swapio)) { - st_swapio = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA); + st_swapio = rrdset_create_localhost("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250 + , update_every, RRDSET_TYPE_AREA); - rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL); - rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL); + rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_swapio); @@ -109,10 +110,11 @@ int do_proc_vmstat(int update_every, usec_t dt) { if(do_io) { static RRDSET *st_io = NULL; if(unlikely(!st_io)) { - st_io = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA); + st_io = rrdset_create_localhost("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150 + , update_every, RRDSET_TYPE_AREA); - rrddim_add(st_io, "in", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_io, "out", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_io); @@ -126,11 +128,12 @@ int do_proc_vmstat(int update_every, usec_t dt) { if(do_pgfaults) { static RRDSET *st_pgfaults = NULL; if(unlikely(!st_pgfaults)) { - st_pgfaults = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE); - st_pgfaults->isdetail = 1; + st_pgfaults = rrdset_create_localhost("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults" + , "page faults/s", 500, update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st_pgfaults, RRDSET_FLAG_DETAIL); - rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_pgfaults); @@ -149,27 +152,28 @@ int do_proc_vmstat(int update_every, usec_t dt) { has_numa = (numa_local || numa_foreign || numa_interleave || numa_other || numa_pte_updates || numa_huge_pte_updates || numa_hint_faults || numa_hint_faults_local || numa_pages_migrated) ? 1 : 0; - if(do_numa == CONFIG_ONDEMAND_YES || (do_numa == CONFIG_ONDEMAND_ONDEMAND && has_numa)) { - do_numa = CONFIG_ONDEMAND_YES; + if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && has_numa)) { + do_numa = CONFIG_BOOLEAN_YES; static RRDSET *st_numa = NULL; if(unlikely(!st_numa)) { - st_numa = rrdset_create("mem", "numa", NULL, "numa", NULL, "NUMA events", "events/s", 800, update_every, RRDSET_TYPE_LINE); - st_numa->isdetail = 1; + st_numa = rrdset_create_localhost("mem", "numa", NULL, "numa", NULL, "NUMA events", "events/s", 800 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st_numa, RRDSET_FLAG_DETAIL); // These depend on CONFIG_NUMA in the kernel. - rrddim_add(st_numa, "local", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "foreign", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "interleave", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "other", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st_numa, "local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "foreign", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "interleave", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "other", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); // The following stats depend on CONFIG_NUMA_BALANCING in the // kernel. - rrddim_add(st_numa, "pte updates", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "huge pte updates", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "hint faults", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "hint faults local", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st_numa, "pages migrated", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(st_numa, "pte updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "huge pte updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "hint faults", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "hint faults local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st_numa, "pages migrated", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_numa); diff --git a/src/procfile.c b/src/procfile.c index dc4a5409..3a89e835 100644 --- a/src/procfile.c +++ b/src/procfile.c @@ -128,6 +128,8 @@ static inline void pflines_free(pflines *fl) { // The procfile void procfile_close(procfile *ff) { + if(unlikely(!ff)) return; + debug(D_PROCFILE, PF_PREFIX ": Closing file '%s'", procfile_filename(ff)); if(likely(ff->lines)) pflines_free(ff->lines); diff --git a/src/registry.c b/src/registry.c index d223cd6f..ec6fb83b 100644 --- a/src/registry.c +++ b/src/registry.c @@ -41,19 +41,19 @@ static inline void registry_set_person_cookie(struct web_client *w, REGISTRY_PER // ---------------------------------------------------------------------------- // JSON GENERATION -static inline void registry_json_header(struct web_client *w, const char *action, const char *status) { +static inline void registry_json_header(RRDHOST *host, struct web_client *w, const char *action, const char *status) { buffer_flush(w->response.data); w->response.data->contenttype = CT_APPLICATION_JSON; buffer_sprintf(w->response.data, "{\n\t\"action\": \"%s\",\n\t\"status\": \"%s\",\n\t\"hostname\": \"%s\",\n\t\"machine_guid\": \"%s\"", - action, status, registry.hostname, registry.machine_guid); + action, status, (host == localhost)?registry.hostname:host->hostname, host->machine_guid); } static inline void registry_json_footer(struct web_client *w) { buffer_strcat(w->response.data, "\n}\n"); } -static inline int registry_json_disabled(struct web_client *w, const char *action) { - registry_json_header(w, action, REGISTRY_STATUS_DISABLED); +static inline int registry_json_disabled(RRDHOST *host, struct web_client *w, const char *action) { + registry_json_header(host, w, action, REGISTRY_STATUS_DISABLED); buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"", registry.registry_to_announce); @@ -127,8 +127,8 @@ static inline int registry_person_url_callback_verify_machine_exists(void *entry // ---------------------------------------------------------------------------- // public HELLO request -int registry_request_hello_json(struct web_client *w) { - registry_json_header(w, "hello", REGISTRY_STATUS_OK); +int registry_request_hello_json(RRDHOST *host, struct web_client *w) { + registry_json_header(host, w, "hello", REGISTRY_STATUS_OK); buffer_sprintf(w->response.data, ",\n\t\"registry\": \"%s\"", registry.registry_to_announce); @@ -143,9 +143,9 @@ int registry_request_hello_json(struct web_client *w) { #define REGISTRY_VERIFY_COOKIES_GUID "give-me-back-this-cookie-now--please" // the main method for registering an access -int registry_request_access_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when) { +int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when) { if(unlikely(!registry.enabled)) - return registry_json_disabled(w, "access"); + return registry_json_disabled(host, w, "access"); // ------------------------------------------------------------------------ // verify the browser supports cookies @@ -167,7 +167,7 @@ int registry_request_access_json(struct web_client *w, char *person_guid, char * REGISTRY_PERSON *p = registry_request_access(person_guid, machine_guid, url, name, when); if(!p) { - registry_json_header(w, "access", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "access", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 412; @@ -177,7 +177,7 @@ int registry_request_access_json(struct web_client *w, char *person_guid, char * registry_set_person_cookie(w, p); // generate the response - registry_json_header(w, "access", REGISTRY_STATUS_OK); + registry_json_header(host, w, "access", REGISTRY_STATUS_OK); buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\",\n\t\"urls\": [", p->guid); struct registry_json_walk_person_urls_callback c = { p, NULL, w, 0 }; @@ -193,22 +193,22 @@ int registry_request_access_json(struct web_client *w, char *person_guid, char * // public DELETE request // the main method for deleting a URL from a person -int registry_request_delete_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) { +int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when) { if(!registry.enabled) - return registry_json_disabled(w, "delete"); + return registry_json_disabled(host, w, "delete"); registry_lock(); REGISTRY_PERSON *p = registry_request_delete(person_guid, machine_guid, url, delete_url, when); if(!p) { - registry_json_header(w, "delete", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "delete", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 412; } // generate the response - registry_json_header(w, "delete", REGISTRY_STATUS_OK); + registry_json_header(host, w, "delete", REGISTRY_STATUS_OK); registry_json_footer(w); registry_unlock(); return 200; @@ -218,21 +218,21 @@ int registry_request_delete_json(struct web_client *w, char *person_guid, char * // public SEARCH request // the main method for searching the URLs of a netdata -int registry_request_search_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) { +int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when) { if(!registry.enabled) - return registry_json_disabled(w, "search"); + return registry_json_disabled(host, w, "search"); registry_lock(); REGISTRY_MACHINE *m = registry_request_machine(person_guid, machine_guid, url, request_machine, when); if(!m) { - registry_json_header(w, "search", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "search", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 404; } - registry_json_header(w, "search", REGISTRY_STATUS_OK); + registry_json_header(host, w, "search", REGISTRY_STATUS_OK); buffer_strcat(w->response.data, ",\n\t\"urls\": ["); struct registry_json_walk_person_urls_callback c = { NULL, m, w, 0 }; @@ -248,9 +248,9 @@ int registry_request_search_json(struct web_client *w, char *person_guid, char * // SWITCH REQUEST // the main method for switching user identity -int registry_request_switch_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when) { +int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when) { if(!registry.enabled) - return registry_json_disabled(w, "switch"); + return registry_json_disabled(host, w, "switch"); (void)url; (void)when; @@ -259,7 +259,7 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char * REGISTRY_PERSON *op = registry_person_find(person_guid); if(!op) { - registry_json_header(w, "switch", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 430; @@ -267,7 +267,7 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char * REGISTRY_PERSON *np = registry_person_find(new_person_guid); if(!np) { - registry_json_header(w, "switch", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 431; @@ -275,7 +275,7 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char * REGISTRY_MACHINE *m = registry_machine_find(machine_guid); if(!m) { - registry_json_header(w, "switch", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 432; @@ -286,7 +286,7 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char * // verify the old person has access to this machine avl_traverse(&op->person_urls, registry_person_url_callback_verify_machine_exists, &data); if(!data.count) { - registry_json_header(w, "switch", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 433; @@ -296,7 +296,7 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char * data.count = 0; avl_traverse(&np->person_urls, registry_person_url_callback_verify_machine_exists, &data); if(!data.count) { - registry_json_header(w, "switch", REGISTRY_STATUS_FAILED); + registry_json_header(host, w, "switch", REGISTRY_STATUS_FAILED); registry_json_footer(w); registry_unlock(); return 434; @@ -307,7 +307,7 @@ int registry_request_switch_json(struct web_client *w, char *person_guid, char * registry_set_person_cookie(w, np); // generate the response - registry_json_header(w, "switch", REGISTRY_STATUS_OK); + registry_json_header(host, w, "switch", REGISTRY_STATUS_OK); buffer_sprintf(w->response.data, ",\n\t\"person_guid\": \"%s\"", np->guid); registry_json_footer(w); @@ -323,11 +323,13 @@ void registry_statistics(void) { static RRDSET *sts = NULL, *stc = NULL, *stm = NULL; - if(!sts) sts = rrdset_find("netdata.registry_sessions"); + if(!sts) sts = rrdset_find_localhost("netdata.registry_sessions"); if(!sts) { - sts = rrdset_create("netdata", "registry_sessions", NULL, "registry", NULL, "NetData Registry Sessions", "session", 131000, rrd_update_every, RRDSET_TYPE_LINE); + sts = rrdset_create_localhost("netdata", "registry_sessions", NULL, "registry", NULL + , "NetData Registry Sessions", "session", 131000, localhost->rrd_update_every + , RRDSET_TYPE_LINE); - rrddim_add(sts, "sessions", NULL, 1, 1, RRDDIM_ABSOLUTE); + rrddim_add(sts, "sessions", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(sts); @@ -336,15 +338,16 @@ void registry_statistics(void) { // ------------------------------------------------------------------------ - if(!stc) stc = rrdset_find("netdata.registry_entries"); + if(!stc) stc = rrdset_find_localhost("netdata.registry_entries"); if(!stc) { - stc = rrdset_create("netdata", "registry_entries", NULL, "registry", NULL, "NetData Registry Entries", "entries", 131100, rrd_update_every, RRDSET_TYPE_LINE); - - rrddim_add(stc, "persons", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(stc, "machines", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(stc, "urls", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(stc, "persons_urls", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(stc, "machines_urls", NULL, 1, 1, RRDDIM_ABSOLUTE); + stc = rrdset_create_localhost("netdata", "registry_entries", NULL, "registry", NULL, "NetData Registry Entries" + , "entries", 131100, localhost->rrd_update_every, RRDSET_TYPE_LINE); + + rrddim_add(stc, "persons", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stc, "machines", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stc, "urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stc, "persons_urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stc, "machines_urls", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(stc); @@ -357,15 +360,16 @@ void registry_statistics(void) { // ------------------------------------------------------------------------ - if(!stm) stm = rrdset_find("netdata.registry_mem"); + if(!stm) stm = rrdset_find_localhost("netdata.registry_mem"); if(!stm) { - stm = rrdset_create("netdata", "registry_mem", NULL, "registry", NULL, "NetData Registry Memory", "KB", 131300, rrd_update_every, RRDSET_TYPE_STACKED); - - rrddim_add(stm, "persons", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(stm, "machines", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(stm, "urls", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(stm, "persons_urls", NULL, 1, 1024, RRDDIM_ABSOLUTE); - rrddim_add(stm, "machines_urls", NULL, 1, 1024, RRDDIM_ABSOLUTE); + stm = rrdset_create_localhost("netdata", "registry_mem", NULL, "registry", NULL, "NetData Registry Memory", "KB" + , 131300, localhost->rrd_update_every, RRDSET_TYPE_STACKED); + + rrddim_add(stm, "persons", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stm, "machines", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stm, "urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stm, "persons_urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(stm, "machines_urls", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(stm); diff --git a/src/registry.h b/src/registry.h index 4947486c..2c4592b9 100644 --- a/src/registry.h +++ b/src/registry.h @@ -60,13 +60,16 @@ extern int registry_init(void); extern void registry_free(void); // HTTP requests handled by the registry -extern int registry_request_access_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when); -extern int registry_request_delete_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); -extern int registry_request_search_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when); -extern int registry_request_switch_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when); -extern int registry_request_hello_json(struct web_client *w); +extern int registry_request_access_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when); +extern int registry_request_delete_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); +extern int registry_request_search_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when); +extern int registry_request_switch_json(RRDHOST *host, struct web_client *w, char *person_guid, char *machine_guid, char *url, char *new_person_guid, time_t when); +extern int registry_request_hello_json(RRDHOST *host, struct web_client *w); // update the registry monitoring charts extern void registry_statistics(void); +extern char *registry_get_this_machine_guid(void); +extern int regenerate_guid(const char *guid, char *result); + #endif /* NETDATA_REGISTRY_H */ diff --git a/src/registry_init.c b/src/registry_init.c index a846f861..09167260 100644 --- a/src/registry_init.c +++ b/src/registry_init.c @@ -4,46 +4,52 @@ int registry_init(void) { char filename[FILENAME_MAX + 1]; // registry enabled? - registry.enabled = config_get_boolean("registry", "enabled", 0); + if(web_server_mode != WEB_SERVER_MODE_NONE) { + registry.enabled = config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0); + } + else { + info("Registry is disabled - use the central netdata"); + config_set_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0); + registry.enabled = 0; + } // pathnames snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir); - registry.pathname = config_get("registry", "registry db directory", filename); + registry.pathname = config_get(CONFIG_SECTION_REGISTRY, "registry db directory", filename); if(mkdir(registry.pathname, 0770) == -1 && errno != EEXIST) fatal("Cannot create directory '%s'.", registry.pathname); // filenames snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname); - registry.machine_guid_filename = config_get("registry", "netdata unique id file", filename); - registry_get_this_machine_guid(); + registry.machine_guid_filename = config_get(CONFIG_SECTION_REGISTRY, "netdata unique id file", filename); snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname); - registry.db_filename = config_get("registry", "registry db file", filename); + registry.db_filename = config_get(CONFIG_SECTION_REGISTRY, "registry db file", filename); snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname); - registry.log_filename = config_get("registry", "registry log file", filename); + registry.log_filename = config_get(CONFIG_SECTION_REGISTRY, "registry log file", filename); // configuration options - registry.save_registry_every_entries = (unsigned long long)config_get_number("registry", "registry save db every new entries", 1000000); - registry.persons_expiration = config_get_number("registry", "registry expire idle persons days", 365) * 86400; - registry.registry_domain = config_get("registry", "registry domain", ""); - registry.registry_to_announce = config_get("registry", "registry to announce", "https://registry.my-netdata.io"); - registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", localhost.hostname)); - registry.verify_cookies_redirects = config_get_boolean("registry", "verify browser cookies support", 1); + registry.save_registry_every_entries = (unsigned long long)config_get_number(CONFIG_SECTION_REGISTRY, "registry save db every new entries", 1000000); + registry.persons_expiration = config_get_number(CONFIG_SECTION_REGISTRY, "registry expire idle persons days", 365) * 86400; + registry.registry_domain = config_get(CONFIG_SECTION_REGISTRY, "registry domain", ""); + registry.registry_to_announce = config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io"); + registry.hostname = config_get(CONFIG_SECTION_REGISTRY, "registry hostname", config_get(CONFIG_SECTION_GLOBAL, "hostname", "localhost")); + registry.verify_cookies_redirects = config_get_boolean(CONFIG_SECTION_REGISTRY, "verify browser cookies support", 1); setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1); setenv("NETDATA_REGISTRY_URL", registry.registry_to_announce, 1); - registry.max_url_length = (size_t)config_get_number("registry", "max URL length", 1024); + registry.max_url_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL length", 1024); if(registry.max_url_length < 10) { registry.max_url_length = 10; - config_set_number("registry", "max URL length", (long long)registry.max_url_length); + config_set_number(CONFIG_SECTION_REGISTRY, "max URL length", (long long)registry.max_url_length); } - registry.max_name_length = (size_t)config_get_number("registry", "max URL name length", 50); + registry.max_name_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL name length", 50); if(registry.max_name_length < 10) { registry.max_name_length = 10; - config_set_number("registry", "max URL name length", (long long)registry.max_name_length); + config_set_number(CONFIG_SECTION_REGISTRY, "max URL name length", (long long)registry.max_name_length); } // initialize entries counters diff --git a/src/registry_internals.c b/src/registry_internals.c index d32d549e..9ec91ba4 100644 --- a/src/registry_internals.c +++ b/src/registry_internals.c @@ -7,7 +7,7 @@ struct registry registry; // parse a GUID and re-generated to be always lower case // this is used as a protection against the variations of GUIDs -int registry_regenerate_guid(const char *guid, char *result) { +int regenerate_guid(const char *guid, char *result) { uuid_t uuid; if(unlikely(uuid_parse(guid, uuid) == -1)) { info("Registry: GUID '%s' is not a valid GUID.", guid); @@ -18,7 +18,7 @@ int registry_regenerate_guid(const char *guid, char *result) { #ifdef NETDATA_INTERNAL_CHECKS if(strcmp(guid, result)) - info("Registry: source GUID '%s' and re-generated GUID '%s' differ!", guid, result); + info("GUID '%s' and re-generated GUID '%s' differ!", guid, result); #endif /* NETDATA_INTERNAL_CHECKS */ } @@ -96,14 +96,14 @@ REGISTRY_PERSON_URL *registry_verify_request(char *person_guid, char *machine_gu url = registry_fix_url(url, NULL); // make sure the person GUID is valid - if(registry_regenerate_guid(person_guid, pbuf) == -1) { + if(regenerate_guid(person_guid, pbuf) == -1) { info("Registry Request Verification: invalid person GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } person_guid = pbuf; // make sure the machine GUID is valid - if(registry_regenerate_guid(machine_guid, mbuf) == -1) { + if(regenerate_guid(machine_guid, mbuf) == -1) { info("Registry Request Verification: invalid machine GUID, person: '%s', machine '%s', url '%s'", person_guid, machine_guid, url); return NULL; } @@ -226,7 +226,7 @@ REGISTRY_MACHINE *registry_request_machine(char *person_guid, char *machine_guid if(!pu || !p || !m) return NULL; // make sure the machine GUID is valid - if(registry_regenerate_guid(request_machine, mbuf) == -1) { + if(regenerate_guid(request_machine, mbuf) == -1) { info("Registry Machine URLs request: invalid machine GUID, person: '%s', machine '%s', url '%s', request machine '%s'", p->guid, m->guid, pu->url->url, request_machine); return NULL; } @@ -275,8 +275,10 @@ static inline int is_machine_guid_blacklisted(const char *guid) { } char *registry_get_this_machine_guid(void) { - if(likely(registry.machine_guid[0])) - return registry.machine_guid; + static char guid[GUID_LEN + 1] = ""; + + if(likely(guid[0])) + return guid; // read it from disk int fd = open(registry.machine_guid_filename, O_RDONLY); @@ -286,38 +288,38 @@ char *registry_get_this_machine_guid(void) { error("Failed to read machine GUID from '%s'", registry.machine_guid_filename); else { buf[GUID_LEN] = '\0'; - if(registry_regenerate_guid(buf, registry.machine_guid) == -1) { + if(regenerate_guid(buf, guid) == -1) { error("Failed to validate machine GUID '%s' from '%s'. Ignoring it - this might mean this netdata will appear as duplicate in the registry.", buf, registry.machine_guid_filename); - registry.machine_guid[0] = '\0'; + guid[0] = '\0'; } - else if(is_machine_guid_blacklisted(registry.machine_guid)) - registry.machine_guid[0] = '\0'; + else if(is_machine_guid_blacklisted(guid)) + guid[0] = '\0'; } close(fd); } // generate a new one? - if(!registry.machine_guid[0]) { + if(!guid[0]) { uuid_t uuid; uuid_generate_time(uuid); - uuid_unparse_lower(uuid, registry.machine_guid); - registry.machine_guid[GUID_LEN] = '\0'; + uuid_unparse_lower(uuid, guid); + guid[GUID_LEN] = '\0'; // save it fd = open(registry.machine_guid_filename, O_WRONLY|O_CREAT|O_TRUNC, 444); if(fd == -1) fatal("Cannot create unique machine id file '%s'. Please fix this.", registry.machine_guid_filename); - if(write(fd, registry.machine_guid, GUID_LEN) != GUID_LEN) + if(write(fd, guid, GUID_LEN) != GUID_LEN) fatal("Cannot write the unique machine id file '%s'. Please fix this.", registry.machine_guid_filename); close(fd); } - setenv("NETDATA_REGISTRY_UNIQUE_ID", registry.machine_guid, 1); + setenv("NETDATA_REGISTRY_UNIQUE_ID", guid, 1); - return registry.machine_guid; + return guid; } diff --git a/src/registry_internals.h b/src/registry_internals.h index 9c0b7445..27c2fe07 100644 --- a/src/registry_internals.h +++ b/src/registry_internals.h @@ -14,8 +14,6 @@ struct registry { int enabled; - char machine_guid[GUID_LEN + 1]; - // entries counters / statistics unsigned long long persons_count; unsigned long long machines_count; @@ -61,7 +59,7 @@ struct registry { pthread_mutex_t lock; }; -extern int registry_regenerate_guid(const char *guid, char *result); +extern int regenerate_guid(const char *guid, char *result); #include "registry_url.h" #include "registry_machine.h" @@ -70,8 +68,6 @@ extern int registry_regenerate_guid(const char *guid, char *result); extern struct registry registry; -extern char *registry_get_this_machine_guid(void); - // REGISTRY LOW-LEVEL REQUESTS (in registry-internals.c) extern REGISTRY_PERSON *registry_request_access(char *person_guid, char *machine_guid, char *url, char *name, time_t when); extern REGISTRY_PERSON *registry_request_delete(char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when); diff --git a/src/registry_machine.c b/src/registry_machine.c index 3510736d..6dc8200d 100644 --- a/src/registry_machine.c +++ b/src/registry_machine.c @@ -58,7 +58,7 @@ REGISTRY_MACHINE *registry_machine_get(const char *machine_guid, time_t when) { if(likely(machine_guid && *machine_guid)) { // validate it is a GUID char buf[GUID_LEN + 1]; - if(unlikely(registry_regenerate_guid(machine_guid, buf) == -1)) + if(unlikely(regenerate_guid(machine_guid, buf) == -1)) info("Registry: machine guid '%s' is not a valid guid. Ignoring it.", machine_guid); else { machine_guid = buf; diff --git a/src/registry_person.c b/src/registry_person.c index 5f9099c9..409c7692 100644 --- a/src/registry_person.c +++ b/src/registry_person.c @@ -183,7 +183,7 @@ REGISTRY_PERSON *registry_person_get(const char *person_guid, time_t when) { if(person_guid && *person_guid) { char buf[GUID_LEN + 1]; // validate it is a GUID - if(unlikely(registry_regenerate_guid(person_guid, buf) == -1)) + if(unlikely(regenerate_guid(person_guid, buf) == -1)) info("Registry: person guid '%s' is not a valid guid. Ignoring it.", person_guid); else { person_guid = buf; diff --git a/src/rrd.c b/src/rrd.c index a1770439..a9ff6243 100644 --- a/src/rrd.c +++ b/src/rrd.c @@ -1,7 +1,6 @@ +#define NETDATA_RRD_INTERNALS 1 #include "common.h" -#define RRD_DEFAULT_GAP_INTERPOLATIONS 1 - // ---------------------------------------------------------------------------- // globals @@ -12,394 +11,124 @@ int rrd_delete_unupdated_dimensions = 0; */ -int rrd_update_every = UPDATE_EVERY; -int rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; -int rrd_memory_mode = RRD_MEMORY_MODE_SAVE; +int default_rrd_update_every = UPDATE_EVERY; +int default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; +RRD_MEMORY_MODE default_rrd_memory_mode = RRD_MEMORY_MODE_SAVE; -static int rrdset_compare(void* a, void* b); -static int rrdset_compare_name(void* a, void* b); -static int rrdfamily_compare(void *a, void *b); // ---------------------------------------------------------------------------- -// RRDHOST - -RRDHOST localhost = { - .hostname = "localhost", - .rrdset_root = NULL, - .rrdset_root_rwlock = PTHREAD_RWLOCK_INITIALIZER, - .rrdset_root_index = { - { NULL, rrdset_compare }, - AVL_LOCK_INITIALIZER - }, - .rrdset_root_index_name = { - { NULL, rrdset_compare_name }, - AVL_LOCK_INITIALIZER - }, - .rrdfamily_root_index = { - { NULL, rrdfamily_compare }, - AVL_LOCK_INITIALIZER - }, - .variables_root_index = { - { NULL, rrdvar_compare }, - AVL_LOCK_INITIALIZER - }, - .health_log = { - .next_log_id = 1, - .next_alarm_id = 1, - .count = 0, - .max = 1000, - .alarms = NULL, - .alarm_log_rwlock = PTHREAD_RWLOCK_INITIALIZER - } -}; - -void rrdhost_init(char *hostname) { - localhost.hostname = hostname; - localhost.health_log.next_log_id = - localhost.health_log.next_alarm_id = now_realtime_sec(); -} - -void rrdhost_rwlock(RRDHOST *host) { - pthread_rwlock_wrlock(&host->rrdset_root_rwlock); -} - -void rrdhost_rdlock(RRDHOST *host) { - pthread_rwlock_rdlock(&host->rrdset_root_rwlock); -} - -void rrdhost_unlock(RRDHOST *host) { - pthread_rwlock_unlock(&host->rrdset_root_rwlock); -} - -void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) { - int ret = pthread_rwlock_trywrlock(&host->rrdset_root_rwlock); - - if(ret == 0) - fatal("RRDHOST '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file); -} - -void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) { - int ret = pthread_rwlock_tryrdlock(&host->rrdset_root_rwlock); - - if(ret == 0) - fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file); -} - -// ---------------------------------------------------------------------------- -// RRDFAMILY index - -static int rrdfamily_compare(void *a, void *b) { - if(((RRDFAMILY *)a)->hash_family < ((RRDFAMILY *)b)->hash_family) return -1; - else if(((RRDFAMILY *)a)->hash_family > ((RRDFAMILY *)b)->hash_family) return 1; - else return strcmp(((RRDFAMILY *)a)->family, ((RRDFAMILY *)b)->family); -} - -#define rrdfamily_index_add(host, rc) (RRDFAMILY *)avl_insert_lock(&((host)->rrdfamily_root_index), (avl *)(rc)) -#define rrdfamily_index_del(host, rc) (RRDFAMILY *)avl_remove_lock(&((host)->rrdfamily_root_index), (avl *)(rc)) - -static RRDFAMILY *rrdfamily_index_find(RRDHOST *host, const char *id, uint32_t hash) { - RRDFAMILY tmp; - tmp.family = id; - tmp.hash_family = (hash)?hash:simple_hash(tmp.family); - - return (RRDFAMILY *)avl_search_lock(&(host->rrdfamily_root_index), (avl *) &tmp); -} - -RRDFAMILY *rrdfamily_create(const char *id) { - RRDFAMILY *rc = rrdfamily_index_find(&localhost, id, 0); - if(!rc) { - rc = callocz(1, sizeof(RRDFAMILY)); +// RRD - memory modes - rc->family = strdupz(id); - rc->hash_family = simple_hash(rc->family); - - // initialize the variables index - avl_init_lock(&rc->variables_root_index, rrdvar_compare); - - RRDFAMILY *ret = rrdfamily_index_add(&localhost, rc); - if(ret != rc) - fatal("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE"); - } - - rc->use_count++; - return rc; -} +inline const char *rrd_memory_mode_name(RRD_MEMORY_MODE id) { + switch(id) { + case RRD_MEMORY_MODE_RAM: + return RRD_MEMORY_MODE_RAM_NAME; -void rrdfamily_free(RRDFAMILY *rc) { - rc->use_count--; - if(!rc->use_count) { - RRDFAMILY *ret = rrdfamily_index_del(&localhost, rc); - if(ret != rc) - fatal("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE"); + case RRD_MEMORY_MODE_MAP: + return RRD_MEMORY_MODE_MAP_NAME; - if(rc->variables_root_index.avl_tree.root != NULL) - fatal("RRDFAMILY: INTERNAL ERROR: Variables index of RRDFAMILY '%s' that is freed, is not empty.", rc->family); + case RRD_MEMORY_MODE_NONE: + return RRD_MEMORY_MODE_NONE_NAME; - freez((void *)rc->family); - freez(rc); + case RRD_MEMORY_MODE_SAVE: + default: + return RRD_MEMORY_MODE_SAVE_NAME; } } -// ---------------------------------------------------------------------------- -// RRDSET index +RRD_MEMORY_MODE rrd_memory_mode_id(const char *name) { + if(unlikely(!strcmp(name, RRD_MEMORY_MODE_RAM_NAME))) + return RRD_MEMORY_MODE_RAM; + else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_MAP_NAME))) + return RRD_MEMORY_MODE_MAP; + else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_NONE_NAME))) + return RRD_MEMORY_MODE_NONE; -static int rrdset_compare(void* a, void* b) { - if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1; - else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1; - else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id); + return RRD_MEMORY_MODE_SAVE; } -#define rrdset_index_add(host, st) (RRDSET *)avl_insert_lock(&((host)->rrdset_root_index), (avl *)(st)) -#define rrdset_index_del(host, st) (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index), (avl *)(st)) - -static RRDSET *rrdset_index_find(RRDHOST *host, const char *id, uint32_t hash) { - RRDSET tmp; - strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX); - tmp.hash = (hash)?hash:simple_hash(tmp.id); - - return (RRDSET *)avl_search_lock(&(host->rrdset_root_index), (avl *) &tmp); -} // ---------------------------------------------------------------------------- -// RRDSET name index +// RRD - algorithms types -#define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname))) +RRD_ALGORITHM rrd_algorithm_id(const char *name) { + if(strcmp(name, RRD_ALGORITHM_INCREMENTAL_NAME) == 0) + return RRD_ALGORITHM_INCREMENTAL; -static int rrdset_compare_name(void* a, void* b) { - RRDSET *A = rrdset_from_avlname(a); - RRDSET *B = rrdset_from_avlname(b); + else if(strcmp(name, RRD_ALGORITHM_ABSOLUTE_NAME) == 0) + return RRD_ALGORITHM_ABSOLUTE; - // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name); + else if(strcmp(name, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL_NAME) == 0) + return RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL; - if(A->hash_name < B->hash_name) return -1; - else if(A->hash_name > B->hash_name) return 1; - else return strcmp(A->name, B->name); -} + else if(strcmp(name, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL_NAME) == 0) + return RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL; -RRDSET *rrdset_index_add_name(RRDHOST *host, RRDSET *st) { - void *result; - // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name); - result = avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname)); - if(result) return rrdset_from_avlname(result); - return NULL; + else + return RRD_ALGORITHM_ABSOLUTE; } -RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st) { - void *result; - // fprintf(stderr, "DELETING: %s (name: %s)\n", st->id, st->name); - result = (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index_name), (avl *)(&st->avlname)); - if(result) return rrdset_from_avlname(result); - return NULL; -} +const char *rrd_algorithm_name(RRD_ALGORITHM algorithm) { + switch(algorithm) { + case RRD_ALGORITHM_ABSOLUTE: + default: + return RRD_ALGORITHM_ABSOLUTE_NAME; -static RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t hash) { - void *result = NULL; - RRDSET tmp; - tmp.name = name; - tmp.hash_name = (hash)?hash:simple_hash(tmp.name); + case RRD_ALGORITHM_INCREMENTAL: + return RRD_ALGORITHM_INCREMENTAL_NAME; - // fprintf(stderr, "SEARCHING: %s\n", name); - result = avl_search_lock(&host->rrdset_root_index_name, (avl *) (&(tmp.avlname))); - if(result) { - RRDSET *st = rrdset_from_avlname(result); - if(strcmp(st->magic, RRDSET_MAGIC)) - error("Search for RRDSET %s returned an invalid RRDSET %s (name %s)", name, st->id, st->name); + case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL: + return RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL_NAME; - // fprintf(stderr, "FOUND: %s\n", name); - return rrdset_from_avlname(result); + case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL: + return RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL_NAME; } - // fprintf(stderr, "NOT FOUND: %s\n", name); - return NULL; } // ---------------------------------------------------------------------------- -// RRDDIM index +// RRD - chart types -static int rrddim_compare(void* a, void* b) { - if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1; - else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1; - else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id); -} - -#define rrddim_index_add(st, rd) (RRDDIM *)avl_insert_lock(&((st)->dimensions_index), (avl *)(rd)) -#define rrddim_index_del(st,rd ) (RRDDIM *)avl_remove_lock(&((st)->dimensions_index), (avl *)(rd)) +inline RRDSET_TYPE rrdset_type_id(const char *name) { + if(unlikely(strcmp(name, RRDSET_TYPE_AREA_NAME) == 0)) + return RRDSET_TYPE_AREA; -static RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) { - RRDDIM tmp; - strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX); - tmp.hash = (hash)?hash:simple_hash(tmp.id); + else if(unlikely(strcmp(name, RRDSET_TYPE_STACKED_NAME) == 0)) + return RRDSET_TYPE_STACKED; - return (RRDDIM *)avl_search_lock(&(st->dimensions_index), (avl *) &tmp); + else // if(unlikely(strcmp(name, RRDSET_TYPE_LINE_NAME) == 0)) + return RRDSET_TYPE_LINE; } -// ---------------------------------------------------------------------------- -// chart types - -int rrdset_type_id(const char *name) -{ - if(unlikely(strcmp(name, RRDSET_TYPE_AREA_NAME) == 0)) return RRDSET_TYPE_AREA; - else if(unlikely(strcmp(name, RRDSET_TYPE_STACKED_NAME) == 0)) return RRDSET_TYPE_STACKED; - else if(unlikely(strcmp(name, RRDSET_TYPE_LINE_NAME) == 0)) return RRDSET_TYPE_LINE; - return RRDSET_TYPE_LINE; -} - -const char *rrdset_type_name(int chart_type) -{ - static char line[] = RRDSET_TYPE_LINE_NAME; - static char area[] = RRDSET_TYPE_AREA_NAME; - static char stacked[] = RRDSET_TYPE_STACKED_NAME; - +const char *rrdset_type_name(RRDSET_TYPE chart_type) { switch(chart_type) { case RRDSET_TYPE_LINE: - return line; + default: + return RRDSET_TYPE_LINE_NAME; case RRDSET_TYPE_AREA: - return area; + return RRDSET_TYPE_AREA_NAME; case RRDSET_TYPE_STACKED: - return stacked; + return RRDSET_TYPE_STACKED_NAME; } - return line; } -// ---------------------------------------------------------------------------- -// load / save - -const char *rrd_memory_mode_name(int id) -{ - static const char ram[] = RRD_MEMORY_MODE_RAM_NAME; - static const char map[] = RRD_MEMORY_MODE_MAP_NAME; - static const char save[] = RRD_MEMORY_MODE_SAVE_NAME; - - switch(id) { - case RRD_MEMORY_MODE_RAM: - return ram; - - case RRD_MEMORY_MODE_MAP: - return map; - - case RRD_MEMORY_MODE_SAVE: - default: - return save; - } - - return save; -} - -int rrd_memory_mode_id(const char *name) -{ - if(unlikely(!strcmp(name, RRD_MEMORY_MODE_RAM_NAME))) - return RRD_MEMORY_MODE_RAM; - else if(unlikely(!strcmp(name, RRD_MEMORY_MODE_MAP_NAME))) - return RRD_MEMORY_MODE_MAP; - - return RRD_MEMORY_MODE_SAVE; -} - -// ---------------------------------------------------------------------------- -// algorithms types - -int rrddim_algorithm_id(const char *name) -{ - if(strcmp(name, RRDDIM_INCREMENTAL_NAME) == 0) return RRDDIM_INCREMENTAL; - if(strcmp(name, RRDDIM_ABSOLUTE_NAME) == 0) return RRDDIM_ABSOLUTE; - if(strcmp(name, RRDDIM_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_ROW_TOTAL; - if(strcmp(name, RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRDDIM_PCENT_OVER_DIFF_TOTAL; - return RRDDIM_ABSOLUTE; -} - -const char *rrddim_algorithm_name(int chart_type) -{ - static char absolute[] = RRDDIM_ABSOLUTE_NAME; - static char incremental[] = RRDDIM_INCREMENTAL_NAME; - static char percentage_of_absolute_row[] = RRDDIM_PCENT_OVER_ROW_TOTAL_NAME; - static char percentage_of_incremental_row[] = RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME; - - switch(chart_type) { - case RRDDIM_ABSOLUTE: - return absolute; - - case RRDDIM_INCREMENTAL: - return incremental; - - case RRDDIM_PCENT_OVER_ROW_TOTAL: - return percentage_of_absolute_row; - - case RRDDIM_PCENT_OVER_DIFF_TOTAL: - return percentage_of_incremental_row; - } - return absolute; -} - -// ---------------------------------------------------------------------------- -// chart names - -char *rrdset_strncpyz_name(char *to, const char *from, size_t length) -{ - char c, *p = to; - - while (length-- && (c = *from++)) { - if(c != '.' && !isalnum(c)) - c = '_'; - - *p++ = c; - } - - *p = '\0'; - - return to; -} - -void rrdset_set_name(RRDSET *st, const char *name) -{ - if(unlikely(st->name && !strcmp(st->name, name))) - return; - - debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name); - - char b[CONFIG_MAX_VALUE + 1]; - char n[RRD_ID_LENGTH_MAX + 1]; - - snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); - rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE); - - if(st->name) { - rrdset_index_del_name(&localhost, st); - st->name = config_set_default(st->id, "name", b); - st->hash_name = simple_hash(st->name); - rrdsetvar_rename_all(st); - } - else { - st->name = config_get(st->id, "name", b); - st->hash_name = simple_hash(st->name); - } - - pthread_rwlock_wrlock(&st->rwlock); - RRDDIM *rd; - for(rd = st->dimensions; rd ;rd = rd->next) - rrddimvar_rename_all(rd); - pthread_rwlock_unlock(&st->rwlock); - - if(unlikely(rrdset_index_add_name(&localhost, st) != st)) - error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name); -} // ---------------------------------------------------------------------------- -// cache directory +// RRD - cache directory -char *rrdset_cache_dir(const char *id) -{ +char *rrdset_cache_dir(RRDHOST *host, const char *id, const char *config_section) { char *ret = NULL; char b[FILENAME_MAX + 1]; char n[FILENAME_MAX + 1]; rrdset_strncpyz_name(b, id, FILENAME_MAX); - snprintfz(n, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, b); - ret = config_get(id, "cache directory", n); + snprintfz(n, FILENAME_MAX, "%s/%s", host->cache_dir, b); + ret = config_get(config_section, "cache directory", n); - if(rrd_memory_mode == RRD_MEMORY_MODE_MAP || rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { + if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { int r = mkdir(ret, 0775); if(r != 0 && errno != EEXIST) error("Cannot create directory '%s'", ret); @@ -407,1236 +136,3 @@ char *rrdset_cache_dir(const char *id) return ret; } - -// ---------------------------------------------------------------------------- -// core functions - -void rrdset_reset(RRDSET *st) -{ - debug(D_RRD_CALLS, "rrdset_reset() %s", st->name); - - st->last_collected_time.tv_sec = 0; - st->last_collected_time.tv_usec = 0; - st->last_updated.tv_sec = 0; - st->last_updated.tv_usec = 0; - st->current_entry = 0; - st->counter = 0; - st->counter_done = 0; - - RRDDIM *rd; - for(rd = st->dimensions; rd ; rd = rd->next) { - rd->last_collected_time.tv_sec = 0; - rd->last_collected_time.tv_usec = 0; - rd->counter = 0; - memset(rd->values, 0, rd->entries * sizeof(storage_number)); - } -} -static inline long align_entries_to_pagesize(long entries) { - if(entries < 5) entries = 5; - if(entries > RRD_HISTORY_ENTRIES_MAX) entries = RRD_HISTORY_ENTRIES_MAX; - -#ifdef NETDATA_LOG_ALLOCATIONS - long page = (size_t)sysconf(_SC_PAGESIZE); - - long size = sizeof(RRDDIM) + entries * sizeof(storage_number); - if(size % page) { - size -= (size % page); - size += page; - - long n = (size - sizeof(RRDDIM)) / sizeof(storage_number); - return n; - } - - return entries; -#else - return entries; -#endif -} - -static inline void timeval_align(struct timeval *tv, int update_every) { - tv->tv_sec -= tv->tv_sec % update_every; - tv->tv_usec = 500000; -} - -RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type) -{ - if(!type || !type[0]) { - fatal("Cannot create rrd stats without a type."); - return NULL; - } - - if(!id || !id[0]) { - fatal("Cannot create rrd stats without an id."); - return NULL; - } - - char fullid[RRD_ID_LENGTH_MAX + 1]; - char fullfilename[FILENAME_MAX + 1]; - - snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); - - RRDSET *st = rrdset_find(fullid); - if(st) { - debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid); - return st; - } - - long rentries = config_get_number(fullid, "history", rrd_default_history_entries); - long entries = align_entries_to_pagesize(rentries); - if(entries != rentries) entries = config_set_number(fullid, "history", entries); - - int enabled = config_get_boolean(fullid, "enabled", 1); - if(!enabled) entries = 5; - - unsigned long size = sizeof(RRDSET); - char *cache_dir = rrdset_cache_dir(fullid); - - debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id); - - snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir); - if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0); - if(st) { - if(strcmp(st->magic, RRDSET_MAGIC) != 0) { - errno = 0; - info("Initializing file %s.", fullfilename); - memset(st, 0, size); - } - else if(strcmp(st->id, fullid) != 0) { - errno = 0; - error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid); - // munmap(st, size); - // st = NULL; - memset(st, 0, size); - } - else if(st->memsize != size || st->entries != entries) { - errno = 0; - error("File %s does not have the desired size. Clearing it.", fullfilename); - memset(st, 0, size); - } - else if(st->update_every != update_every) { - errno = 0; - error("File %s does not have the desired update frequency. Clearing it.", fullfilename); - memset(st, 0, size); - } - else if((now_realtime_sec() - st->last_updated.tv_sec) > update_every * entries) { - errno = 0; - error("File %s is too old. Clearing it.", fullfilename); - memset(st, 0, size); - } - - // make sure the database is aligned - if(st->last_updated.tv_sec) - timeval_align(&st->last_updated, update_every); - } - - if(st) { - st->name = NULL; - st->type = NULL; - st->family = NULL; - st->context = NULL; - st->title = NULL; - st->units = NULL; - st->dimensions = NULL; - st->next = NULL; - st->mapped = rrd_memory_mode; - st->variables = NULL; - st->alarms = NULL; - memset(&st->rwlock, 0, sizeof(pthread_rwlock_t)); - memset(&st->avl, 0, sizeof(avl)); - memset(&st->avlname, 0, sizeof(avl)); - memset(&st->variables_root_index, 0, sizeof(avl_tree_lock)); - memset(&st->dimensions_index, 0, sizeof(avl_tree_lock)); - } - else { - st = callocz(1, size); - st->mapped = RRD_MEMORY_MODE_RAM; - } - - st->memsize = size; - st->entries = entries; - st->update_every = update_every; - - if(st->current_entry >= st->entries) st->current_entry = 0; - - strcpy(st->cache_filename, fullfilename); - strcpy(st->magic, RRDSET_MAGIC); - - strcpy(st->id, fullid); - st->hash = simple_hash(st->id); - - st->cache_dir = cache_dir; - - st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type))); - st->type = config_get(st->id, "type", type); - st->family = config_get(st->id, "family", family?family:st->type); - st->units = config_get(st->id, "units", units?units:""); - - st->context = config_get(st->id, "context", context?context:st->id); - st->hash_context = simple_hash(st->context); - - st->priority = config_get_number(st->id, "priority", priority); - st->enabled = enabled; - - st->isdetail = 0; - st->debug = 0; - - // if(!strcmp(st->id, "disk_util.dm-0")) { - // st->debug = 1; - // error("enabled debugging for '%s'", st->id); - // } - // else error("not enabled debugging for '%s'", st->id); - - st->green = NAN; - st->red = NAN; - - st->last_collected_time.tv_sec = 0; - st->last_collected_time.tv_usec = 0; - st->counter_done = 0; - - st->gap_when_lost_iterations_above = (int) ( - config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2); - - avl_init_lock(&st->dimensions_index, rrddim_compare); - avl_init_lock(&st->variables_root_index, rrdvar_compare); - - pthread_rwlock_init(&st->rwlock, NULL); - rrdhost_rwlock(&localhost); - - if(name && *name) rrdset_set_name(st, name); - else rrdset_set_name(st, id); - - { - char varvalue[CONFIG_MAX_VALUE + 1]; - char varvalue2[CONFIG_MAX_VALUE + 1]; - snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name); - json_escape_string(varvalue2, varvalue, sizeof(varvalue2)); - st->title = config_get(st->id, "title", varvalue2); - } - - st->rrdfamily = rrdfamily_create(st->family); - st->rrdhost = &localhost; - - st->next = localhost.rrdset_root; - localhost.rrdset_root = st; - - if(health_enabled) { - rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, 0); - rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, 0); - rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, 0); - rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, 0); - rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, 0); - } - - if(unlikely(rrdset_index_add(&localhost, st) != st)) - error("RRDSET: INTERNAL ERROR: attempt to index duplicate chart '%s'", st->id); - - rrdsetcalc_link_matching(st); - rrdcalctemplate_link_matching(st); - - rrdhost_unlock(&localhost); - - return(st); -} - -RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier, long divisor, int algorithm) -{ - RRDDIM *rd = rrddim_find(st, id); - if(rd) { - debug(D_RRD_CALLS, "Cannot create rrd dimension '%s/%s', it already exists.", st->id, name?name:""); - return rd; - } - - char filename[FILENAME_MAX + 1]; - char fullfilename[FILENAME_MAX + 1]; - - char varname[CONFIG_MAX_NAME + 1]; - unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number)); - - debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id); - - rrdset_strncpyz_name(filename, id, FILENAME_MAX); - snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename); - - if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) - rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1); - - if(rd) { - struct timeval now; - now_realtime_timeval(&now); - - if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) { - errno = 0; - info("Initializing file %s.", fullfilename); - memset(rd, 0, size); - } - else if(rd->memsize != size) { - errno = 0; - error("File %s does not have the desired size. Clearing it.", fullfilename); - memset(rd, 0, size); - } - else if(rd->multiplier != multiplier) { - errno = 0; - error("File %s does not have the same multiplier. Clearing it.", fullfilename); - memset(rd, 0, size); - } - else if(rd->divisor != divisor) { - errno = 0; - error("File %s does not have the same divisor. Clearing it.", fullfilename); - memset(rd, 0, size); - } - else if(rd->update_every != st->update_every) { - errno = 0; - error("File %s does not have the same refresh frequency. Clearing it.", fullfilename); - memset(rd, 0, size); - } - else if(dt_usec(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * USEC_PER_SEC)) { - errno = 0; - error("File %s is too old. Clearing it.", fullfilename); - memset(rd, 0, size); - } - else if(strcmp(rd->id, id) != 0) { - errno = 0; - error("File %s contents are not for dimension %s. Clearing it.", fullfilename, id); - // munmap(rd, size); - // rd = NULL; - memset(rd, 0, size); - } - - if(rd->algorithm && rd->algorithm != algorithm) - error("File %s does not have the expected algorithm (expected %d '%s', found %d '%s'). Previous values may be wrong.", fullfilename, algorithm, rrddim_algorithm_name(algorithm), rd->algorithm, rrddim_algorithm_name(rd->algorithm)); - } - - if(rd) { - // we have a file mapped for rd - rd->mapped = rrd_memory_mode; - rd->flags = 0x00000000; - rd->variables = NULL; - rd->next = NULL; - rd->name = NULL; - memset(&rd->avl, 0, sizeof(avl)); - } - else { - // if we didn't manage to get a mmap'd dimension, just create one - - rd = callocz(1, size); - rd->mapped = RRD_MEMORY_MODE_RAM; - } - rd->memsize = size; - - strcpy(rd->magic, RRDDIMENSION_MAGIC); - strcpy(rd->cache_filename, fullfilename); - strncpyz(rd->id, id, RRD_ID_LENGTH_MAX); - rd->hash = simple_hash(rd->id); - - snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); - rd->name = config_get(st->id, varname, (name && *name)?name:rd->id); - - snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id); - rd->algorithm = rrddim_algorithm_id(config_get(st->id, varname, rrddim_algorithm_name(algorithm))); - - snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id); - rd->multiplier = config_get_number(st->id, varname, multiplier); - - snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id); - rd->divisor = config_get_number(st->id, varname, divisor); - if(!rd->divisor) rd->divisor = 1; - - rd->entries = st->entries; - rd->update_every = st->update_every; - - // prevent incremental calculation spikes - rd->counter = 0; - rd->updated = 0; - rd->calculated_value = 0; - rd->last_calculated_value = 0; - rd->collected_value = 0; - rd->last_collected_value = 0; - rd->collected_volume = 0; - rd->stored_volume = 0; - rd->last_stored_value = 0; - rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); - rd->last_collected_time.tv_sec = 0; - rd->last_collected_time.tv_usec = 0; - rd->rrdset = st; - - // append this dimension - pthread_rwlock_wrlock(&st->rwlock); - if(!st->dimensions) - st->dimensions = rd; - else { - RRDDIM *td = st->dimensions; - for(; td->next; td = td->next) ; - td->next = rd; - } - - if(health_enabled) { - rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, 0); - rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, 0); - rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, 0); - } - - pthread_rwlock_unlock(&st->rwlock); - - if(unlikely(rrddim_index_add(st, rd) != rd)) - error("RRDDIM: INTERNAL ERROR: attempt to index duplicate dimension '%s' on chart '%s'", rd->id, st->id); - - return(rd); -} - -void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) -{ - if(unlikely(rd->name && !strcmp(rd->name, name))) - return; - - debug(D_RRD_CALLS, "rrddim_set_name() from %s.%s to %s.%s", st->name, rd->name, st->name, name); - - char varname[CONFIG_MAX_NAME + 1]; - snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); - rd->name = config_set_default(st->id, varname, name); - - rrddimvar_rename_all(rd); -} - -void rrddim_free(RRDSET *st, RRDDIM *rd) -{ - debug(D_RRD_CALLS, "rrddim_free() %s.%s", st->name, rd->name); - - if(rd == st->dimensions) - st->dimensions = rd->next; - else { - RRDDIM *i; - for (i = st->dimensions; i && i->next != rd; i = i->next) ; - - if (i && i->next == rd) - i->next = rd->next; - else - error("Request to free dimension '%s.%s' but it is not linked.", st->id, rd->name); - } - rd->next = NULL; - - while(rd->variables) - rrddimvar_free(rd->variables); - - if(unlikely(rrddim_index_del(st, rd) != rd)) - error("RRDDIM: INTERNAL ERROR: attempt to remove from index dimension '%s' on chart '%s', removed a different dimension.", rd->id, st->id); - - // free(rd->annotations); - if(rd->mapped == RRD_MEMORY_MODE_SAVE) { - debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename); - savememory(rd->cache_filename, rd, rd->memsize); - - debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name); - munmap(rd, rd->memsize); - } - else if(rd->mapped == RRD_MEMORY_MODE_MAP) { - debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name); - munmap(rd, rd->memsize); - } - else { - debug(D_RRD_CALLS, "Removing dimension '%s'.", rd->name); - freez(rd); - } -} - -void rrdset_free_all(void) -{ - info("Freeing all memory..."); - - rrdhost_rwlock(&localhost); - - RRDSET *st; - for(st = localhost.rrdset_root; st ;) { - RRDSET *next = st->next; - - pthread_rwlock_wrlock(&st->rwlock); - - while(st->variables) - rrdsetvar_free(st->variables); - - while(st->alarms) - rrdsetcalc_unlink(st->alarms); - - while(st->dimensions) - rrddim_free(st, st->dimensions); - - if(unlikely(rrdset_index_del(&localhost, st) != st)) - error("RRDSET: INTERNAL ERROR: attempt to remove from index chart '%s', removed a different chart.", st->id); - - rrdset_index_del_name(&localhost, st); - - st->rrdfamily->use_count--; - if(!st->rrdfamily->use_count) - rrdfamily_free(st->rrdfamily); - - pthread_rwlock_unlock(&st->rwlock); - - if(st->mapped == RRD_MEMORY_MODE_SAVE || st->mapped == RRD_MEMORY_MODE_MAP) { - debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name); - munmap(st, st->memsize); - } - else - freez(st); - - st = next; - } - localhost.rrdset_root = NULL; - - rrdhost_unlock(&localhost); - - info("Memory cleanup completed..."); -} - -void rrdset_save_all(void) { - info("Saving database..."); - - RRDSET *st; - RRDDIM *rd; - - // we get an write lock - // to ensure only one thread is saving the database - rrdhost_rwlock(&localhost); - - for(st = localhost.rrdset_root; st ; st = st->next) { - pthread_rwlock_rdlock(&st->rwlock); - - if(st->mapped == RRD_MEMORY_MODE_SAVE) { - debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename); - savememory(st->cache_filename, st, st->memsize); - } - - for(rd = st->dimensions; rd ; rd = rd->next) { - if(likely(rd->mapped == RRD_MEMORY_MODE_SAVE)) { - debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename); - savememory(rd->cache_filename, rd, rd->memsize); - } - } - - pthread_rwlock_unlock(&st->rwlock); - } - - rrdhost_unlock(&localhost); -} - - -RRDSET *rrdset_find(const char *id) -{ - debug(D_RRD_CALLS, "rrdset_find() for chart %s", id); - - RRDSET *st = rrdset_index_find(&localhost, id, 0); - return(st); -} - -RRDSET *rrdset_find_bytype(const char *type, const char *id) -{ - debug(D_RRD_CALLS, "rrdset_find_bytype() for chart %s.%s", type, id); - - char buf[RRD_ID_LENGTH_MAX + 1]; - - strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1); - strcat(buf, "."); - int len = (int) strlen(buf); - strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len)); - - return(rrdset_find(buf)); -} - -RRDSET *rrdset_find_byname(const char *name) -{ - debug(D_RRD_CALLS, "rrdset_find_byname() for chart %s", name); - - RRDSET *st = rrdset_index_find_name(&localhost, name, 0); - return(st); -} - -RRDDIM *rrddim_find(RRDSET *st, const char *id) -{ - debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", st->name, id); - - return rrddim_index_find(st, id, 0); -} - -int rrddim_hide(RRDSET *st, const char *id) -{ - debug(D_RRD_CALLS, "rrddim_hide() for chart %s, dimension %s", st->name, id); - - RRDDIM *rd = rrddim_find(st, id); - if(unlikely(!rd)) { - error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id); - return 1; - } - - rd->flags |= RRDDIM_FLAG_HIDDEN; - return 0; -} - -int rrddim_unhide(RRDSET *st, const char *id) -{ - debug(D_RRD_CALLS, "rrddim_unhide() for chart %s, dimension %s", st->name, id); - - RRDDIM *rd = rrddim_find(st, id); - if(unlikely(!rd)) { - error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id); - return 1; - } - - if(rd->flags & RRDDIM_FLAG_HIDDEN) rd->flags ^= RRDDIM_FLAG_HIDDEN; - return 0; -} - -collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value) -{ - debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value); - - now_realtime_timeval(&rd->last_collected_time); - rd->collected_value = value; - rd->updated = 1; - rd->counter++; - - // fprintf(stderr, "%s.%s %llu " COLLECTED_NUMBER_FORMAT " dt %0.6f" " rate " CALCULATED_NUMBER_FORMAT "\n", st->name, rd->name, st->usec_since_last_update, value, (float)((double)st->usec_since_last_update / (double)1000000), (calculated_number)((value - rd->last_collected_value) * (calculated_number)rd->multiplier / (calculated_number)rd->divisor * 1000000.0 / (calculated_number)st->usec_since_last_update)); - - return rd->last_collected_value; -} - -collected_number rrddim_set(RRDSET *st, const char *id, collected_number value) -{ - RRDDIM *rd = rrddim_find(st, id); - if(unlikely(!rd)) { - error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id); - return 0; - } - - return rrddim_set_by_pointer(st, rd, value); -} - -void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds) -{ - if(unlikely(!st->last_collected_time.tv_sec || !microseconds)) { - // the first entry - microseconds = st->update_every * USEC_PER_SEC; - } - st->usec_since_last_update = microseconds; -} - -void rrdset_next_usec(RRDSET *st, usec_t microseconds) -{ - struct timeval now; - now_realtime_timeval(&now); - - if(unlikely(!st->last_collected_time.tv_sec)) { - // the first entry - microseconds = st->update_every * USEC_PER_SEC; - } - else if(unlikely(!microseconds)) { - // no dt given by the plugin - microseconds = dt_usec(&now, &st->last_collected_time); - } - else { - // microseconds has the time since the last collection -#ifdef NETDATA_INTERNAL_CHECKS - usec_t now_usec = timeval_usec(&now); - usec_t last_usec = timeval_usec(&st->last_collected_time); -#endif - usec_t since_last_usec = dt_usec(&now, &st->last_collected_time); - - // verify the microseconds given is good - if(unlikely(microseconds > since_last_usec)) { - debug(D_RRD_CALLS, "dt %llu usec given is too big - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, microseconds - since_last_usec, st->name, st->id); - -#ifdef NETDATA_INTERNAL_CHECKS - if(unlikely(last_usec + microseconds > now_usec + 1000)) - error("dt %llu usec given is too big - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, microseconds - since_last_usec, st->name, st->id); -#endif - - microseconds = since_last_usec; - } - else if(unlikely(microseconds < since_last_usec * 0.8)) { - debug(D_RRD_CALLS, "dt %llu usec given is too small - expected %llu usec up to -20%%, for chart '%s' (%s).", microseconds, since_last_usec, st->name, st->id); - -#ifdef NETDATA_INTERNAL_CHECKS - error("dt %llu usec given is too small - expected %llu usec up to -20%%, for chart '%s' (%s).", microseconds, since_last_usec, st->name, st->id); -#endif - microseconds = since_last_usec; - } - } - debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds); - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds); - st->usec_since_last_update = microseconds; -} - -usec_t rrdset_done(RRDSET *st) -{ - if(unlikely(netdata_exit)) return 0; - - debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name); - - RRDDIM *rd; - - int - pthreadoldcancelstate; // store the old cancelable pthread state, to restore it at the end - - char - store_this_entry = 1, // boolean: 1 = store this entry, 0 = don't store this entry - first_entry = 0; // boolean: 1 = this is the first entry seen for this chart, 0 = all other entries - - unsigned int - stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done() - - usec_t - last_collect_ut, // the timestamp in microseconds, of the last collected value - now_collect_ut, // the timestamp in microseconds, of this collected value (this is NOW) - last_stored_ut, // the timestamp in microseconds, of the last stored entry in the db - next_store_ut, // the timestamp in microseconds, of the next entry to store in the db - update_every_ut = st->update_every * USEC_PER_SEC; // st->update_every in microseconds - - if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0)) - error("Cannot set pthread cancel state to DISABLE."); - - // a read lock is OK here - pthread_rwlock_rdlock(&st->rwlock); - -/* - // enable the chart, if it was disabled - if(unlikely(rrd_delete_unupdated_dimensions) && !st->enabled) - st->enabled = 1; -*/ - - // check if the chart has a long time to be updated - if(unlikely(st->usec_since_last_update > st->entries * update_every_ut)) { - info("%s: took too long to be updated (%0.3Lf secs). Resetting it.", st->name, (long double)(st->usec_since_last_update / 1000000.0)); - rrdset_reset(st); - st->usec_since_last_update = update_every_ut; - first_entry = 1; - } - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: microseconds since last update: %llu", st->name, st->usec_since_last_update); - - // set last_collected_time - if(unlikely(!st->last_collected_time.tv_sec)) { - // it is the first entry - // set the last_collected_time to now - now_realtime_timeval(&st->last_collected_time); - timeval_align(&st->last_collected_time, st->update_every); - - last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - update_every_ut; - - // the first entry should not be stored - store_this_entry = 0; - first_entry = 1; - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: has not set last_collected_time. Setting it now. Will not store the next entry.", st->name); - } - else { - // it is not the first entry - // calculate the proper last_collected_time, using usec_since_last_update - last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec; - usec_t ut = last_collect_ut + st->usec_since_last_update; - st->last_collected_time.tv_sec = (time_t) (ut / USEC_PER_SEC); - st->last_collected_time.tv_usec = (suseconds_t) (ut % USEC_PER_SEC); - } - - // if this set has not been updated in the past - // we fake the last_update time to be = now - usec_since_last_update - if(unlikely(!st->last_updated.tv_sec)) { - // it has never been updated before - // set a fake last_updated, in the past using usec_since_last_update - usec_t ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - st->usec_since_last_update; - st->last_updated.tv_sec = (time_t) (ut / USEC_PER_SEC); - st->last_updated.tv_usec = (suseconds_t) (ut % USEC_PER_SEC); - - // the first entry should not be stored - store_this_entry = 0; - first_entry = 1; - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: initializing last_updated to now - %llu microseconds (%0.3Lf). Will not store the next entry.", st->name, st->usec_since_last_update, (long double)ut/1000000.0); - } - - // check if we will re-write the entire data set - if(unlikely(dt_usec(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) { - info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Resetting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec); - rrdset_reset(st); - - st->usec_since_last_update = update_every_ut; - - now_realtime_timeval(&st->last_collected_time); - timeval_align(&st->last_collected_time, st->update_every); - - usec_t ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - st->usec_since_last_update; - st->last_updated.tv_sec = (time_t) (ut / USEC_PER_SEC); - st->last_updated.tv_usec = (suseconds_t) (ut % USEC_PER_SEC); - - // the first entry should not be stored - store_this_entry = 0; - first_entry = 1; - } - - // these are the 3 variables that will help us in interpolation - // last_stored_ut = the last time we added a value to the storage - // now_collect_ut = the time the current value has been collected - // next_store_ut = the time of the next interpolation point - last_stored_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec; - now_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec; - next_store_ut = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC; - - if(unlikely(st->debug)) { - debug(D_RRD_STATS, "%s: last_collect_ut = %0.3Lf (last collection time)", st->name, (long double)last_collect_ut/1000000.0); - debug(D_RRD_STATS, "%s: now_collect_ut = %0.3Lf (current collection time)", st->name, (long double)now_collect_ut/1000000.0); - debug(D_RRD_STATS, "%s: last_stored_ut = %0.3Lf (last updated time)", st->name, (long double)last_stored_ut/1000000.0); - debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0); - } - - if(unlikely(!st->counter_done)) { - store_this_entry = 0; - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: Will not store the next entry.", st->name); - } - st->counter_done++; - - // calculate totals and count the dimensions - int dimensions; - st->collected_total = 0; - for( rd = st->dimensions, dimensions = 0 ; rd ; rd = rd->next, dimensions++ ) - if(likely(rd->updated)) st->collected_total += rd->collected_value; - - uint32_t storage_flags = SN_EXISTS; - - // process all dimensions to calculate their values - // based on the collected figures only - // at this stage we do not interpolate anything - for( rd = st->dimensions ; rd ; rd = rd->next ) { - - if(unlikely(!rd->updated)) { - rd->calculated_value = 0; - continue; - } - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: START " - " last_collected_value = " COLLECTED_NUMBER_FORMAT - " collected_value = " COLLECTED_NUMBER_FORMAT - " last_calculated_value = " CALCULATED_NUMBER_FORMAT - " calculated_value = " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , rd->last_collected_value - , rd->collected_value - , rd->last_calculated_value - , rd->calculated_value - ); - - switch(rd->algorithm) { - case RRDDIM_ABSOLUTE: - rd->calculated_value = (calculated_number)rd->collected_value - * (calculated_number)rd->multiplier - / (calculated_number)rd->divisor; - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN " - CALCULATED_NUMBER_FORMAT " = " - COLLECTED_NUMBER_FORMAT - " * " CALCULATED_NUMBER_FORMAT - " / " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , rd->calculated_value - , rd->collected_value - , (calculated_number)rd->multiplier - , (calculated_number)rd->divisor - ); - break; - - case RRDDIM_PCENT_OVER_ROW_TOTAL: - if(unlikely(!st->collected_total)) - rd->calculated_value = 0; - else - // the percentage of the current value - // over the total of all dimensions - rd->calculated_value = - (calculated_number)100 - * (calculated_number)rd->collected_value - / (calculated_number)st->collected_total; - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC PCENT-ROW " - CALCULATED_NUMBER_FORMAT " = 100" - " * " COLLECTED_NUMBER_FORMAT - " / " COLLECTED_NUMBER_FORMAT - , st->id, rd->name - , rd->calculated_value - , rd->collected_value - , st->collected_total - ); - break; - - case RRDDIM_INCREMENTAL: - if(unlikely(rd->counter <= 1)) { - rd->calculated_value = 0; - continue; - } - - // if the new is smaller than the old (an overflow, or reset), set the old equal to the new - // to reset the calculation (it will give zero as the calculation for this second) - if(unlikely(rd->last_collected_value > rd->collected_value)) { - debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT - , st->name, rd->name - , rd->last_collected_value - , rd->collected_value); - if(!(rd->flags & RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)) storage_flags = SN_EXISTS_RESET; - rd->last_collected_value = rd->collected_value; - } - - rd->calculated_value += - (calculated_number)(rd->collected_value - rd->last_collected_value) - * (calculated_number)rd->multiplier - / (calculated_number)rd->divisor; - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC INC PRE " - CALCULATED_NUMBER_FORMAT " = (" - COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT - ")" - " * " CALCULATED_NUMBER_FORMAT - " / " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , rd->calculated_value - , rd->collected_value, rd->last_collected_value - , (calculated_number)rd->multiplier - , (calculated_number)rd->divisor - ); - break; - - case RRDDIM_PCENT_OVER_DIFF_TOTAL: - if(unlikely(rd->counter <= 1)) { - rd->calculated_value = 0; - continue; - } - - // if the new is smaller than the old (an overflow, or reset), set the old equal to the new - // to reset the calculation (it will give zero as the calculation for this second) - if(unlikely(rd->last_collected_value > rd->collected_value)) { - debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT - , st->name, rd->name - , rd->last_collected_value - , rd->collected_value); - if(!(rd->flags & RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)) storage_flags = SN_EXISTS_RESET; - rd->last_collected_value = rd->collected_value; - } - - // the percentage of the current increment - // over the increment of all dimensions together - if(unlikely(st->collected_total == st->last_collected_total)) - rd->calculated_value = 0; - else - rd->calculated_value = - (calculated_number)100 - * (calculated_number)(rd->collected_value - rd->last_collected_value) - / (calculated_number)(st->collected_total - st->last_collected_total); - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF " - CALCULATED_NUMBER_FORMAT " = 100" - " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" - " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" - , st->id, rd->name - , rd->calculated_value - , rd->collected_value, rd->last_collected_value - , st->collected_total, st->last_collected_total - ); - break; - - default: - // make the default zero, to make sure - // it gets noticed when we add new types - rd->calculated_value = 0; - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC " - CALCULATED_NUMBER_FORMAT " = 0" - , st->id, rd->name - , rd->calculated_value - ); - break; - } - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: PHASE2 " - " last_collected_value = " COLLECTED_NUMBER_FORMAT - " collected_value = " COLLECTED_NUMBER_FORMAT - " last_calculated_value = " CALCULATED_NUMBER_FORMAT - " calculated_value = " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , rd->last_collected_value - , rd->collected_value - , rd->last_calculated_value - , rd->calculated_value - ); - - } - - // at this point we have all the calculated values ready - // it is now time to interpolate values on a second boundary - - if(unlikely(now_collect_ut < next_store_ut)) { - // this is collected in the same interpolation point - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name); -#ifdef NETDATA_INTERNAL_CHECKS - info("%s is collected in the same interpolation point: short by %llu microseconds", st->name, next_store_ut - now_collect_ut); -#endif - } - - usec_t first_ut = last_stored_ut; - long long iterations = (now_collect_ut - last_stored_ut) / (update_every_ut); - if((now_collect_ut % (update_every_ut)) == 0) iterations++; - - for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) { -#ifdef NETDATA_INTERNAL_CHECKS - if(iterations < 0) { error("%s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", st->name, first_ut, last_stored_ut, next_store_ut, now_collect_ut); } -#endif - - if(unlikely(st->debug)) { - debug(D_RRD_STATS, "%s: last_stored_ut = %0.3Lf (last updated time)", st->name, (long double)last_stored_ut/1000000.0); - debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0); - } - - st->last_updated.tv_sec = (time_t) (next_store_ut / USEC_PER_SEC); - st->last_updated.tv_usec = 0; - - for( rd = st->dimensions ; likely(rd) ; rd = rd->next ) { - calculated_number new_value; - - switch(rd->algorithm) { - case RRDDIM_INCREMENTAL: - new_value = (calculated_number) - ( rd->calculated_value - * (calculated_number)(next_store_ut - last_collect_ut) - / (calculated_number)(now_collect_ut - last_collect_ut) - ); - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC2 INC " - CALCULATED_NUMBER_FORMAT " = " - CALCULATED_NUMBER_FORMAT - " * %llu" - " / %llu" - , st->id, rd->name - , new_value - , rd->calculated_value - , (next_store_ut - last_stored_ut) - , (now_collect_ut - last_stored_ut) - ); - - rd->calculated_value -= new_value; - new_value += rd->last_calculated_value; - rd->last_calculated_value = 0; - new_value /= (calculated_number)st->update_every; - - if(unlikely(next_store_ut - last_stored_ut < update_every_ut)) { - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: COLLECTION POINT IS SHORT " CALCULATED_NUMBER_FORMAT " - EXTRAPOLATING", - st->id, rd->name - , (calculated_number)(next_store_ut - last_stored_ut) - ); - new_value = new_value * (calculated_number)(st->update_every * 1000000) / (calculated_number)(next_store_ut - last_stored_ut); - } - break; - - case RRDDIM_ABSOLUTE: - case RRDDIM_PCENT_OVER_ROW_TOTAL: - case RRDDIM_PCENT_OVER_DIFF_TOTAL: - default: - if(iterations == 1) { - // this is the last iteration - // do not interpolate - // just show the calculated value - - new_value = rd->calculated_value; - } - else { - // we have missed an update - // interpolate in the middle values - - new_value = (calculated_number) - ( ( (rd->calculated_value - rd->last_calculated_value) - * (calculated_number)(next_store_ut - last_collect_ut) - / (calculated_number)(now_collect_ut - last_collect_ut) - ) - + rd->last_calculated_value - ); - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: CALC2 DEF " - CALCULATED_NUMBER_FORMAT " = (((" - "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")" - " * %llu" - " / %llu) + " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , new_value - , rd->calculated_value, rd->last_calculated_value - , (next_store_ut - first_ut) - , (now_collect_ut - first_ut), rd->last_calculated_value - ); - } - break; - } - - if(unlikely(!store_this_entry)) { - rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); - continue; - } - - if(likely(rd->updated && rd->counter > 1 && iterations < st->gap_when_lost_iterations_above)) { - rd->values[st->current_entry] = pack_storage_number(new_value, storage_flags ); - rd->last_stored_value = new_value; - - if(unlikely(st->debug)) - debug(D_RRD_STATS, "%s/%s: STORE[%ld] " - CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , st->current_entry - , unpack_storage_number(rd->values[st->current_entry]), new_value - ); - } - else { - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: STORE[%ld] = NON EXISTING " - , st->id, rd->name - , st->current_entry - ); - rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); - rd->last_stored_value = NAN; - } - - stored_entries++; - - if(unlikely(st->debug)) { - calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor; - calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]); - calculated_number accuracy = accuracy_loss(t1, t2); - debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)" - , st->id, rd->name - , st->current_entry - , t2 - , get_storage_number_flags(rd->values[st->current_entry]) - , t1 - , accuracy - , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : "" - ); - - rd->collected_volume += t1; - rd->stored_volume += t2; - accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume); - debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s" - , st->id, rd->name - , st->current_entry - , rd->stored_volume - , rd->collected_volume - , accuracy - , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : "" - ); - - } - } - // reset the storage flags for the next point, if any; - storage_flags = SN_EXISTS; - - st->counter++; - st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1; - last_stored_ut = next_store_ut; - } - - st->last_collected_total = st->collected_total; - - for( rd = st->dimensions; rd ; rd = rd->next ) { - if(unlikely(!rd->updated)) continue; - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_collected_value, rd->collected_value); - rd->last_collected_value = rd->collected_value; - - switch(rd->algorithm) { - case RRDDIM_INCREMENTAL: - if(unlikely(!first_entry)) { - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value + rd->calculated_value, rd->calculated_value); - rd->last_calculated_value += rd->calculated_value; - } - else { - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s: THIS IS THE FIRST POINT", st->name); - } - break; - - case RRDDIM_ABSOLUTE: - case RRDDIM_PCENT_OVER_ROW_TOTAL: - case RRDDIM_PCENT_OVER_DIFF_TOTAL: - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value, rd->calculated_value); - rd->last_calculated_value = rd->calculated_value; - break; - } - - rd->calculated_value = 0; - rd->collected_value = 0; - rd->updated = 0; - - if(unlikely(st->debug)) debug(D_RRD_STATS, "%s/%s: END " - " last_collected_value = " COLLECTED_NUMBER_FORMAT - " collected_value = " COLLECTED_NUMBER_FORMAT - " last_calculated_value = " CALCULATED_NUMBER_FORMAT - " calculated_value = " CALCULATED_NUMBER_FORMAT - , st->id, rd->name - , rd->last_collected_value - , rd->collected_value - , rd->last_calculated_value - , rd->calculated_value - ); - } - - // ALL DONE ABOUT THE DATA UPDATE - // -------------------------------------------------------------------- - -/* - // find if there are any obsolete dimensions (not updated recently) - if(unlikely(rrd_delete_unupdated_dimensions)) { - - for( rd = st->dimensions; likely(rd) ; rd = rd->next ) - if((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec) - break; - - if(unlikely(rd)) { - RRDDIM *last; - // there is dimension to free - // upgrade our read lock to a write lock - pthread_rwlock_unlock(&st->rwlock); - pthread_rwlock_wrlock(&st->rwlock); - - for( rd = st->dimensions, last = NULL ; likely(rd) ; ) { - // remove it only it is not updated in rrd_delete_unupdated_dimensions seconds - - if(unlikely((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)) { - info("Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id); - - if(unlikely(!last)) { - st->dimensions = rd->next; - rd->next = NULL; - rrddim_free(st, rd); - rd = st->dimensions; - continue; - } - else { - last->next = rd->next; - rd->next = NULL; - rrddim_free(st, rd); - rd = last->next; - continue; - } - } - - last = rd; - rd = rd->next; - } - - if(unlikely(!st->dimensions)) { - info("Disabling chart %s (%s) since it does not have any dimensions", st->name, st->id); - st->enabled = 0; - } - } - } -*/ - - pthread_rwlock_unlock(&st->rwlock); - - if(unlikely(pthread_setcancelstate(pthreadoldcancelstate, NULL) != 0)) - error("Cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate); - - return(st->usec_since_last_update); -} diff --git a/src/rrd.h b/src/rrd.h index 4189d36c..ec794477 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -3,20 +3,17 @@ #define UPDATE_EVERY 1 #define UPDATE_EVERY_MAX 3600 -extern int rrd_update_every; #define RRD_DEFAULT_HISTORY_ENTRIES 3600 #define RRD_HISTORY_ENTRIES_MAX (86400*10) -extern int rrd_default_history_entries; -// time in seconds to delete unupdated dimensions -// set to zero to disable this feature -extern int rrd_delete_unupdated_dimensions; +extern int default_rrd_update_every; +extern int default_rrd_history_entries; -#define RRD_ID_LENGTH_MAX 400 +#define RRD_ID_LENGTH_MAX 200 -#define RRDSET_MAGIC "NETDATA RRD SET FILE V018" -#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V018" +#define RRDSET_MAGIC "NETDATA RRD SET FILE V019" +#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V019" typedef long long total_number; #define TOTAL_NUMBER_FORMAT "%lld" @@ -24,59 +21,61 @@ typedef long long total_number; // ---------------------------------------------------------------------------- // chart types +typedef enum rrdset_type { + RRDSET_TYPE_LINE = 0, + RRDSET_TYPE_AREA = 1, + RRDSET_TYPE_STACKED = 2 +} RRDSET_TYPE; + #define RRDSET_TYPE_LINE_NAME "line" #define RRDSET_TYPE_AREA_NAME "area" #define RRDSET_TYPE_STACKED_NAME "stacked" -#define RRDSET_TYPE_LINE 0 -#define RRDSET_TYPE_AREA 1 -#define RRDSET_TYPE_STACKED 2 - -int rrdset_type_id(const char *name); -const char *rrdset_type_name(int chart_type); +RRDSET_TYPE rrdset_type_id(const char *name); +const char *rrdset_type_name(RRDSET_TYPE chart_type); // ---------------------------------------------------------------------------- // memory mode +typedef enum rrd_memory_mode { + RRD_MEMORY_MODE_NONE = 0, + RRD_MEMORY_MODE_RAM = 1, + RRD_MEMORY_MODE_MAP = 2, + RRD_MEMORY_MODE_SAVE = 3 +} RRD_MEMORY_MODE; + +#define RRD_MEMORY_MODE_NONE_NAME "none" #define RRD_MEMORY_MODE_RAM_NAME "ram" #define RRD_MEMORY_MODE_MAP_NAME "map" #define RRD_MEMORY_MODE_SAVE_NAME "save" -#define RRD_MEMORY_MODE_RAM 0 -#define RRD_MEMORY_MODE_MAP 1 -#define RRD_MEMORY_MODE_SAVE 2 - -extern int rrd_memory_mode; +extern RRD_MEMORY_MODE default_rrd_memory_mode; -extern const char *rrd_memory_mode_name(int id); -extern int rrd_memory_mode_id(const char *name); +extern const char *rrd_memory_mode_name(RRD_MEMORY_MODE id); +extern RRD_MEMORY_MODE rrd_memory_mode_id(const char *name); // ---------------------------------------------------------------------------- // algorithms types -#define RRDDIM_ABSOLUTE_NAME "absolute" -#define RRDDIM_INCREMENTAL_NAME "incremental" -#define RRDDIM_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row" -#define RRDDIM_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row" +typedef enum rrd_algorithm { + RRD_ALGORITHM_ABSOLUTE = 0, + RRD_ALGORITHM_INCREMENTAL = 1, + RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL = 2, + RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL = 3 +} RRD_ALGORITHM; -#define RRDDIM_ABSOLUTE 0 -#define RRDDIM_INCREMENTAL 1 -#define RRDDIM_PCENT_OVER_DIFF_TOTAL 2 -#define RRDDIM_PCENT_OVER_ROW_TOTAL 3 - -extern int rrddim_algorithm_id(const char *name); -extern const char *rrddim_algorithm_name(int chart_type); - -// ---------------------------------------------------------------------------- -// flags +#define RRD_ALGORITHM_ABSOLUTE_NAME "absolute" +#define RRD_ALGORITHM_INCREMENTAL_NAME "incremental" +#define RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row" +#define RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row" -#define RRDDIM_FLAG_HIDDEN 0x00000001 // this dimension will not be offered to callers -#define RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS 0x00000002 // do not offer RESET or OVERFLOW info to callers +extern RRD_ALGORITHM rrd_algorithm_id(const char *name); +extern const char *rrd_algorithm_name(RRD_ALGORITHM algorithm); // ---------------------------------------------------------------------------- -// RRD CONTEXT +// RRD FAMILY struct rrdfamily { avl avl; @@ -90,8 +89,25 @@ struct rrdfamily { }; typedef struct rrdfamily RRDFAMILY; + +// ---------------------------------------------------------------------------- +// flags +// use this for configuration flags, not for state control +// flags are set/unset in a manner that is not thread safe +// and may lead to missing information. + +typedef enum rrddim_flags { + RRDDIM_FLAG_HIDDEN = 1 << 0, // this dimension will not be offered to callers + RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = 1 << 1 // do not offer RESET or OVERFLOW info to callers +} RRDDIM_FLAGS; + +#define rrddim_flag_check(rd, flag) ((rd)->flags & flag) +#define rrddim_flag_set(rd, flag) (rd)->flags |= flag +#define rrddim_flag_clear(rd, flag) (rd)->flags &= ~flag + + // ---------------------------------------------------------------------------- -// RRD DIMENSION +// RRD DIMENSION - this is a metric struct rrddim { // ------------------------------------------------------------------------ @@ -102,18 +118,20 @@ struct rrddim { // ------------------------------------------------------------------------ // the dimension definition - char id[RRD_ID_LENGTH_MAX + 1]; // the id of this dimension (for internal identification) - + const char *id; // the id of this dimension (for internal identification) const char *name; // the name of this dimension (as presented to user) // this is a pointer to the config structure // since the config always has a higher priority // (the user overwrites the name of the charts) + // DO NOT FREE THIS - IT IS ALLOCATED IN CONFIG - int algorithm; // the algorithm that is applied to add new collected values - long multiplier; // the multiplier of the collected values - long divisor; // the divider of the collected values + RRD_ALGORITHM algorithm; // the algorithm that is applied to add new collected values + RRD_MEMORY_MODE rrd_memory_mode; // the memory mode for this dimension - int mapped; // if set to non zero, this dimension is mapped to a file + collected_number multiplier; // the multiplier of the collected values + collected_number divisor; // the divider of the collected values + + uint32_t flags; // configuration flags for the dimension // ------------------------------------------------------------------------ // members for temporary data we need for calculations @@ -122,18 +140,15 @@ struct rrddim { // instead of strcmp() every item in the binary index // we first compare the hashes - // FIXME - // we need the hash_name too! - // needed at rrdr_disable_not_selected_dimensions() - - uint32_t flags; + uint32_t hash_name; // a simple hash of the name - char cache_filename[FILENAME_MAX+1]; // the filename we load/save from/to this set + char *cache_filename; // the filename we load/save from/to this set - unsigned long counter; // the number of times we added values to this rrdim + size_t collections_counter; // the number of times we added values to this rrdim + size_t unused[10]; - int updated; // set to 0 after each calculation, to 1 after each collected value - // we use this to detect that a dimension is not updated + int updated:1; // 1 when the dimension has been updated since the last processing + int exposed:1; // 1 when set what have sent this dimension to the central netdata struct timeval last_collected_time; // when was this dimension last updated // this is actual date time we updated the last_collected_value @@ -164,7 +179,7 @@ struct rrddim { int update_every; // every how many seconds is this updated - unsigned long memsize; // the memory allocated for this dimension + size_t memsize; // the memory allocated for this dimension char magic[sizeof(RRDDIMENSION_MAGIC) + 1]; // a string to be saved, used to identify our data file @@ -177,9 +192,33 @@ struct rrddim { }; typedef struct rrddim RRDDIM; +// ---------------------------------------------------------------------------- +// these loop macros make sure the linked list is accessed with the right lock + +#define rrddim_foreach_read(rd, st) \ + for(rd = st->dimensions, rrdset_check_rdlock(st); rd ; rd = rd->next) + +#define rrddim_foreach_write(rd, st) \ + for(rd = st->dimensions, rrdset_check_wrlock(st); rd ; rd = rd->next) + // ---------------------------------------------------------------------------- -// RRDSET +// RRDSET - this is a chart + +// use this for configuration flags, not for state control +// flags are set/unset in a manner that is not thread safe +// and may lead to missing information. + +typedef enum rrdset_flags { + RRDSET_FLAG_ENABLED = 1 << 0, // enables or disables a chart + RRDSET_FLAG_DETAIL = 1 << 1, // if set, the data set should be considered as a detail of another + // (the master data set should be the one that has the same family and is not detail) + RRDSET_FLAG_DEBUG = 1 << 2 // enables or disables debugging for a chart +} RRDSET_FLAGS; + +#define rrdset_flag_check(st, flag) ((st)->flags & flag) +#define rrdset_flag_set(st, flag) (st)->flags |= flag +#define rrdset_flag_clear(st, flag) (st)->flags &= ~flag struct rrdset { // ------------------------------------------------------------------------ @@ -198,6 +237,8 @@ struct rrdset { // since the config always has a higher priority // (the user overwrites the name of the charts) + char *config_section; // the config section for the chart + char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options) char *family; // grouping sets under the same family char *title; // title shown to user @@ -206,7 +247,7 @@ struct rrdset { char *context; // the template of this data set uint32_t hash_context; - int chart_type; + RRDSET_TYPE chart_type; int update_every; // every how many seconds is this updated? @@ -215,30 +256,27 @@ struct rrdset { long current_entry; // the entry that is currently being updated // it goes around in a round-robin fashion - int enabled; + uint32_t flags; // configuration flags int gap_when_lost_iterations_above; // after how many lost iterations a gap should be stored // netdata will interpolate values for gaps lower than this long priority; - int isdetail; // if set, the data set should be considered as a detail of another - // (the master data set should be the one that has the same family and is not detail) // ------------------------------------------------------------------------ // members for temporary data we need for calculations - int mapped; // if set to 1, this is memory mapped - - int debug; + RRD_MEMORY_MODE rrd_memory_mode; // if set to 1, this is memory mapped char *cache_dir; // the directory to store dimensions char cache_filename[FILENAME_MAX+1]; // the filename to store this set - pthread_rwlock_t rwlock; + pthread_rwlock_t rrdset_rwlock; // protects dimensions linked list - unsigned long counter; // the number of times we added values to this rrd - unsigned long counter_done; // the number of times we added values to this rrd + size_t counter; // the number of times we added values to this database + size_t counter_done; // the number of times rrdset_done() has been called + size_t unused[10]; uint32_t hash; // a simple hash on the id, to speed up searching // we first compare hashes, and only if the hashes are equal we do string comparisons @@ -284,83 +322,220 @@ struct rrdset { }; typedef struct rrdset RRDSET; +#define rrdset_rdlock(st) pthread_rwlock_rdlock(&((st)->rrdset_rwlock)) +#define rrdset_wrlock(st) pthread_rwlock_wrlock(&((st)->rrdset_rwlock)) +#define rrdset_unlock(st) pthread_rwlock_unlock(&((st)->rrdset_rwlock)) + +// ---------------------------------------------------------------------------- +// these loop macros make sure the linked list is accessed with the right lock + +#define rrdset_foreach_read(st, host) \ + for(st = host->rrdset_root, rrdhost_check_rdlock(host); st ; st = st->next) + +#define rrdset_foreach_write(st, host) \ + for(st = host->rrdset_root, rrdhost_check_wrlock(host); st ; st = st->next) + + // ---------------------------------------------------------------------------- // RRD HOST struct rrdhost { - avl avl; + avl avl; // the index of hosts + + // ------------------------------------------------------------------------ + // host information - char *hostname; + char *hostname; // the hostname of this host + uint32_t hash_hostname; // the hostname hash - RRDSET *rrdset_root; - pthread_rwlock_t rrdset_root_rwlock; + char machine_guid[GUID_LEN + 1]; // the unique ID of this host + uint32_t hash_machine_guid; // the hash of the unique ID - avl_tree_lock rrdset_root_index; - avl_tree_lock rrdset_root_index_name; + char *os; // the O/S type of the host + int rrd_update_every; // the update frequency of the host + int rrd_history_entries; // the number of history entries for the host's charts + RRD_MEMORY_MODE rrd_memory_mode; // the memory more for the charts of this host + + char *cache_dir; // the directory to save RRD cache files + char *varlib_dir; // the directory to save health log + + + // ------------------------------------------------------------------------ + // streaming of data to remote hosts - rrdpush + + int rrdpush_enabled:1; // 1 when this host sends metrics to another netdata + char *rrdpush_destination; // where to send metrics to + char *rrdpush_api_key; // the api key at the receiving netdata + volatile int rrdpush_connected:1; // 1 when the sender is ready to push metrics + volatile int rrdpush_spawn:1; // 1 when the sender thread has been spawn + volatile int rrdpush_error_shown:1; // 1 when we have logged a communication error + int rrdpush_socket; // the fd of the socket to the remote host, or -1 + pthread_t rrdpush_thread; // the sender thread + pthread_mutex_t rrdpush_mutex; // exclusive access to rrdpush_buffer + int rrdpush_pipe[2]; // collector to sender thread communication + BUFFER *rrdpush_buffer; // collector fills it, sender sends them - avl_tree_lock rrdfamily_root_index; - avl_tree_lock variables_root_index; + + // ------------------------------------------------------------------------ + // streaming of data from remote hosts - rrdpush + + volatile size_t connected_senders; // when remote hosts are streaming to this + // host, this is the counter of connected clients + + time_t senders_disconnected_time; // the time the last sender was disconnected + + // ------------------------------------------------------------------------ + // health monitoring options + + int health_enabled:1; // 1 when this host has health enabled + time_t health_delay_up_to; // a timestamp to delay alarms processing up to + char *health_default_exec; // the full path of the alarms notifications program + char *health_default_recipient; // the default recipient for all alarms + char *health_log_filename; // the alarms event log filename + size_t health_log_entries_written; // the number of alarm events writtern to the alarms event log + FILE *health_log_fp; // the FILE pointer to the open alarms event log file // all RRDCALCs are primarily allocated and linked here // RRDCALCs may be linked to charts at any point // (charts may or may not exist when these are loaded) RRDCALC *alarms; - ALARM_LOG health_log; + ALARM_LOG health_log; // alarms historical events (event log) + + // templates of alarms + // these are used to create alarms when charts + // are created or renamed, that match them RRDCALCTEMPLATE *templates; + + + // ------------------------------------------------------------------------ + // the charts of the host + + RRDSET *rrdset_root; // the host charts + + + // ------------------------------------------------------------------------ + // locks + + pthread_rwlock_t rrdhost_rwlock; // lock for this RRDHOST (protects rrdset_root linked list) + + avl_tree_lock rrdset_root_index; // the host's charts index (by id) + avl_tree_lock rrdset_root_index_name; // the host's charts index (by name) + + avl_tree_lock rrdfamily_root_index; // the host's chart families index + avl_tree_lock variables_root_index; // the host's chart variables index + + struct rrdhost *next; }; typedef struct rrdhost RRDHOST; -extern RRDHOST localhost; -extern void rrdhost_init(char *hostname); +extern RRDHOST *localhost; + +#define rrdhost_rdlock(h) pthread_rwlock_rdlock(&((h)->rrdhost_rwlock)) +#define rrdhost_wrlock(h) pthread_rwlock_wrlock(&((h)->rrdhost_rwlock)) +#define rrdhost_unlock(h) pthread_rwlock_unlock(&((h)->rrdhost_rwlock)) + +// ---------------------------------------------------------------------------- +// these loop macros make sure the linked list is accessed with the right lock + +#define rrdhost_foreach_read(var) \ + for(var = localhost, rrd_check_rdlock(); var ; var = var->next) + +#define rrdhost_foreach_write(var) \ + for(var = localhost, rrd_check_wrlock(); var ; var = var->next) + + +// ---------------------------------------------------------------------------- +// global lock for all RRDHOSTs + +extern pthread_rwlock_t rrd_rwlock; +#define rrd_rdlock() pthread_rwlock_rdlock(&rrd_rwlock) +#define rrd_wrlock() pthread_rwlock_wrlock(&rrd_rwlock) +#define rrd_unlock() pthread_rwlock_unlock(&rrd_rwlock) + +// ---------------------------------------------------------------------------- + +extern time_t rrdhost_free_orphan_time; + +extern void rrd_init(char *hostname); + +extern RRDHOST *rrdhost_find_guid(const char *guid, uint32_t hash); +extern RRDHOST *rrdhost_find_or_create( + const char *hostname + , const char *guid + , const char *os + , int update_every + , int history + , RRD_MEMORY_MODE mode + , int health_enabled + , int rrdpush_enabled + , char *rrdpush_destination + , char *rrdpush_api_key +); #ifdef NETDATA_INTERNAL_CHECKS -#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__) +extern void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line); +extern void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line); +extern void rrdset_check_rdlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line); +extern void rrdset_check_wrlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line); +extern void rrd_check_rdlock_int(const char *file, const char *function, const unsigned long line); +extern void rrd_check_wrlock_int(const char *file, const char *function, const unsigned long line); + #define rrdhost_check_rdlock(host) rrdhost_check_rdlock_int(host, __FILE__, __FUNCTION__, __LINE__) +#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__) +#define rrdset_check_rdlock(st) rrdset_check_rdlock_int(st, __FILE__, __FUNCTION__, __LINE__) +#define rrdset_check_wrlock(st) rrdset_check_wrlock_int(st, __FILE__, __FUNCTION__, __LINE__) +#define rrd_check_rdlock() rrd_check_rdlock_int(__FILE__, __FUNCTION__, __LINE__) +#define rrd_check_wrlock() rrd_check_wrlock_int(__FILE__, __FUNCTION__, __LINE__) + #else #define rrdhost_check_rdlock(host) (void)0 #define rrdhost_check_wrlock(host) (void)0 +#define rrdset_check_rdlock(host) (void)0 +#define rrdset_check_wrlock(host) (void)0 +#define rrd_check_rdlock() (void)0 +#define rrd_check_wrlock() (void)0 #endif -extern void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line); -extern void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line); - -extern void rrdhost_rwlock(RRDHOST *host); -extern void rrdhost_rdlock(RRDHOST *host); -extern void rrdhost_unlock(RRDHOST *host); - // ---------------------------------------------------------------------------- -// RRD SET functions +// RRDSET functions -extern char *rrdset_strncpyz_name(char *to, const char *from, size_t length); extern void rrdset_set_name(RRDSET *st, const char *name); -extern char *rrdset_cache_dir(const char *id); +extern RRDSET *rrdset_create(RRDHOST *host + , const char *type + , const char *id + , const char *name + , const char *family + , const char *context + , const char *title + , const char *units + , long priority + , int update_every + , RRDSET_TYPE chart_type); -extern void rrdset_reset(RRDSET *st); +#define rrdset_create_localhost(type, id, name, family, context, title, units, priority, update_every, chart_type) rrdset_create(localhost, type, id, name, family, context, title, units, priority, update_every, chart_type) -extern RRDSET *rrdset_create(const char *type - , const char *id - , const char *name - , const char *family - , const char *context - , const char *title - , const char *units - , long priority - , int update_every - , int chart_type); +extern void rrdhost_free_all(void); +extern void rrdhost_save_all(void); + +extern void rrdhost_cleanup_remote_stale(RRDHOST *protected); +extern void rrdhost_free(RRDHOST *host); +extern void rrdhost_save(RRDHOST *host); -extern void rrdset_free_all(void); -extern void rrdset_save_all(void); +extern RRDSET *rrdset_find(RRDHOST *host, const char *id); +#define rrdset_find_localhost(id) rrdset_find(localhost, id) -extern RRDSET *rrdset_find(const char *id); -extern RRDSET *rrdset_find_bytype(const char *type, const char *id); -extern RRDSET *rrdset_find_byname(const char *name); +extern RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id); +#define rrdset_find_bytype_localhost(type, id) rrdset_find_bytype(localhost, type, id) + +extern RRDSET *rrdset_find_byname(RRDHOST *host, const char *name); +#define rrdset_find_byname_localhost(name) rrdset_find_byname(localhost, name) extern void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds); extern void rrdset_next_usec(RRDSET *st, usec_t microseconds); #define rrdset_next(st) rrdset_next_usec(st, 0ULL) -extern usec_t rrdset_done(RRDSET *st); +extern void rrdset_done(RRDSET *st); // get the total duration in seconds of the round robin database #define rrdset_duration(st) ((time_t)( (((st)->counter >= ((unsigned long)(st)->entries))?(unsigned long)(st)->entries:(st)->counter) * (st)->update_every )) @@ -398,11 +573,9 @@ extern usec_t rrdset_done(RRDSET *st); // ---------------------------------------------------------------------------- // RRD DIMENSION functions -extern RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier, long divisor, int algorithm); +extern RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm); extern void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name); -extern void rrddim_free(RRDSET *st, RRDDIM *rd); - extern RRDDIM *rrddim_find(RRDSET *st, const char *id); extern int rrddim_hide(RRDSET *st, const char *id); @@ -411,4 +584,37 @@ extern int rrddim_unhide(RRDSET *st, const char *id); extern collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value); extern collected_number rrddim_set(RRDSET *st, const char *id, collected_number value); +extern long align_entries_to_pagesize(RRD_MEMORY_MODE mode, long entries); + + +// ---------------------------------------------------------------------------- +// RRD internal functions + +#ifdef NETDATA_RRD_INTERNALS + +extern void rrdset_free(RRDSET *st); +extern avl_tree_lock rrdhost_root_index; + +extern char *rrdset_strncpyz_name(char *to, const char *from, size_t length); +extern char *rrdset_cache_dir(RRDHOST *host, const char *id, const char *config_section); + +extern void rrdset_reset(RRDSET *st); + +extern void rrddim_free(RRDSET *st, RRDDIM *rd); + +extern int rrddim_compare(void* a, void* b); +extern int rrdset_compare(void* a, void* b); +extern int rrdset_compare_name(void* a, void* b); +extern int rrdfamily_compare(void *a, void *b); + +extern RRDFAMILY *rrdfamily_create(RRDHOST *host, const char *id); +extern void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc); + +#define rrdset_index_add(host, st) (RRDSET *)avl_insert_lock(&((host)->rrdset_root_index), (avl *)(st)) +#define rrdset_index_del(host, st) (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index), (avl *)(st)) +extern RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st); + +#endif /* NETDATA_RRD_INTERNALS */ + + #endif /* NETDATA_RRD_H */ diff --git a/src/rrd2json.c b/src/rrd2json.c index b886b25f..84db4043 100644 --- a/src/rrd2json.c +++ b/src/rrd2json.c @@ -2,7 +2,7 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used) { - pthread_rwlock_rdlock(&st->rwlock); + rrdset_rdlock(st); buffer_sprintf(wb, "\t\t{\n" @@ -29,7 +29,7 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions , st->context , st->title , st->priority - , st->enabled?"true":"false" + , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?"true":"false" , st->units , st->name , rrdset_type_name(st->chart_type) @@ -43,8 +43,8 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions size_t dimensions = 0; RRDDIM *rd; - for(rd = st->dimensions; rd ; rd = rd->next) { - if(rd->flags & RRDDIM_FLAG_HIDDEN) continue; + rrddim_foreach_read(rd, st) { + if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) continue; memory += rd->memsize; @@ -71,14 +71,14 @@ void rrd_stats_api_v1_chart_with_data(RRDSET *st, BUFFER *wb, size_t *dimensions "\n\t\t}" ); - pthread_rwlock_unlock(&st->rwlock); + rrdset_unlock(st); } void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) { rrd_stats_api_v1_chart_with_data(st, wb, NULL, NULL); } -void rrd_stats_api_v1_charts(BUFFER *wb) +void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb) { size_t c, dimensions = 0, memory = 0, alarms = 0; RRDSET *st; @@ -90,16 +90,17 @@ void rrd_stats_api_v1_charts(BUFFER *wb) ",\n\t\"update_every\": %d" ",\n\t\"history\": %d" ",\n\t\"charts\": {" - , localhost.hostname + , host->hostname , program_version - , os_type - , rrd_update_every - , rrd_default_history_entries + , host->os + , host->rrd_update_every + , host->rrd_history_entries ); - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); - for(st = localhost.rrdset_root, c = 0; st ; st = st->next) { - if(st->enabled && st->dimensions) { + c = 0; + rrdhost_rdlock(host); + rrdset_foreach_read(st, host) { + if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { if(c) buffer_strcat(wb, ","); buffer_strcat(wb, "\n\t\t\""); buffer_strcat(wb, st->id); @@ -110,11 +111,11 @@ void rrd_stats_api_v1_charts(BUFFER *wb) } RRDCALC *rc; - for(rc = localhost.alarms; rc ; rc = rc->next) { + for(rc = host->alarms; rc ; rc = rc->next) { if(rc->rrdset) alarms++; } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + rrdhost_unlock(host); buffer_sprintf(wb, "\n\t}" ",\n\t\"charts_count\": %zu" @@ -149,35 +150,34 @@ static inline size_t prometheus_name_copy(char *d, const char *s, size_t usable) #define PROMETHEUS_ELEMENT_MAX 256 -void rrd_stats_api_v1_charts_allmetrics_prometheus(BUFFER *wb) -{ - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); +void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb) { + rrdhost_rdlock(host); - char host[PROMETHEUS_ELEMENT_MAX + 1]; - prometheus_name_copy(host, config_get("global", "hostname", "localhost"), PROMETHEUS_ELEMENT_MAX); + char hostname[PROMETHEUS_ELEMENT_MAX + 1]; + prometheus_name_copy(hostname, host->hostname, PROMETHEUS_ELEMENT_MAX); // for each chart RRDSET *st; - for(st = localhost.rrdset_root; st ; st = st->next) { + rrdset_foreach_read(st, host) { char chart[PROMETHEUS_ELEMENT_MAX + 1]; prometheus_name_copy(chart, st->id, PROMETHEUS_ELEMENT_MAX); buffer_strcat(wb, "\n"); - if(st->enabled && st->dimensions) { - pthread_rwlock_rdlock(&st->rwlock); + if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { + rrdset_rdlock(st); // for each dimension RRDDIM *rd; - for(rd = st->dimensions; rd ; rd = rd->next) { - if(rd->counter) { + rrddim_foreach_read(rd, st) { + if(rd->collections_counter) { char dimension[PROMETHEUS_ELEMENT_MAX + 1]; prometheus_name_copy(dimension, rd->id, PROMETHEUS_ELEMENT_MAX); // buffer_sprintf(wb, "# HELP %s.%s %s\n", st->id, rd->id, st->units); switch(rd->algorithm) { - case RRDDIM_INCREMENTAL: - case RRDDIM_PCENT_OVER_DIFF_TOTAL: + case RRD_ALGORITHM_INCREMENTAL: + case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL: buffer_sprintf(wb, "# TYPE %s_%s counter\n", chart, dimension); break; @@ -191,17 +191,17 @@ void rrd_stats_api_v1_charts_allmetrics_prometheus(BUFFER *wb) // (unsigned long long)((rd->last_collected_time.tv_sec * 1000) + (rd->last_collected_time.tv_usec / 1000))); buffer_sprintf(wb, "%s_%s{instance=\"%s\"} " COLLECTED_NUMBER_FORMAT " %llu\n", - chart, dimension, host, rd->last_collected_value, + chart, dimension, hostname, rd->last_collected_value, (unsigned long long)((rd->last_collected_time.tv_sec * 1000) + (rd->last_collected_time.tv_usec / 1000))); } } - pthread_rwlock_unlock(&st->rwlock); + rrdset_unlock(st); } } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + rrdhost_unlock(host); } // ---------------------------------------------------------------------------- @@ -224,28 +224,24 @@ static inline size_t shell_name_copy(char *d, const char *s, size_t usable) { #define SHELL_ELEMENT_MAX 100 -void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) -{ - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); - - char host[SHELL_ELEMENT_MAX + 1]; - shell_name_copy(host, config_get("global", "hostname", "localhost"), SHELL_ELEMENT_MAX); +void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) { + rrdhost_rdlock(host); // for each chart RRDSET *st; - for(st = localhost.rrdset_root; st ; st = st->next) { + rrdset_foreach_read(st, host) { calculated_number total = 0.0; char chart[SHELL_ELEMENT_MAX + 1]; shell_name_copy(chart, st->id, SHELL_ELEMENT_MAX); buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name); - if(st->enabled && st->dimensions) { - pthread_rwlock_rdlock(&st->rwlock); + if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { + rrdset_rdlock(st); // for each dimension RRDDIM *rd; - for(rd = st->dimensions; rd ; rd = rd->next) { - if(rd->counter) { + rrddim_foreach_read(rd, st) { + if(rd->collections_counter) { char dimension[SHELL_ELEMENT_MAX + 1]; shell_name_copy(dimension, rd->id, SHELL_ELEMENT_MAX); @@ -256,7 +252,7 @@ void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) else { if(rd->multiplier < 0 || rd->divisor < 0) n = -n; n = roundl(n); - if(!(rd->flags & RRDDIM_FLAG_HIDDEN)) total += n; + if(!rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) total += n; buffer_sprintf(wb, "NETDATA_%s_%s=\"%0.0Lf\" # %s\n", chart, dimension, n, st->units); } } @@ -264,14 +260,14 @@ void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) total = roundl(total); buffer_sprintf(wb, "NETDATA_%s_VISIBLETOTAL=\"%0.0Lf\" # %s\n", chart, total, st->units); - pthread_rwlock_unlock(&st->rwlock); + rrdset_unlock(st); } } buffer_strcat(wb, "\n# NETDATA ALARMS RUNNING\n"); RRDCALC *rc; - for(rc = localhost.alarms; rc ;rc = rc->next) { + for(rc = host->alarms; rc ;rc = rc->next) { if(!rc->rrdset) continue; char chart[SHELL_ELEMENT_MAX + 1]; @@ -292,7 +288,7 @@ void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb) buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status)); } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + rrdhost_unlock(host); } // ---------------------------------------------------------------------------- @@ -301,7 +297,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) { time_t now = now_realtime_sec(); - pthread_rwlock_rdlock(&st->rwlock); + rrdset_rdlock(st); buffer_sprintf(wb, "\t\t{\n" @@ -335,7 +331,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) , st->context , st->title , st->priority - , st->enabled + , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?1:0 , st->units , st->name, options?options:"" , rrdset_type_name(st->chart_type) @@ -346,7 +342,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) , rrdset_last_entry_t(st) , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st) , st->update_every - , st->isdetail + , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?1:0 , st->usec_since_last_update , st->collected_total , st->last_collected_total @@ -355,7 +351,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) unsigned long memory = st->memsize; RRDDIM *rd; - for(rd = st->dimensions; rd ; rd = rd->next) { + rrddim_foreach_read(rd, st) { memory += rd->memsize; @@ -366,8 +362,8 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) "\t\t\t\t\t\"entries\": %ld,\n" "\t\t\t\t\t\"isHidden\": %d,\n" "\t\t\t\t\t\"algorithm\": \"%s\",\n" - "\t\t\t\t\t\"multiplier\": %ld,\n" - "\t\t\t\t\t\"divisor\": %ld,\n" + "\t\t\t\t\t\"multiplier\": " COLLECTED_NUMBER_FORMAT ",\n" + "\t\t\t\t\t\"divisor\": " COLLECTED_NUMBER_FORMAT ",\n" "\t\t\t\t\t\"last_entry_t\": %ld,\n" "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n" "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n" @@ -378,8 +374,8 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) , rd->id , rd->name , rd->entries - , (rd->flags & RRDDIM_FLAG_HIDDEN)?1:0 - , rrddim_algorithm_name(rd->algorithm) + , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0 + , rrd_algorithm_name(rd->algorithm) , rd->multiplier , rd->divisor , rd->last_collected_time.tv_sec @@ -399,7 +395,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb) , memory ); - pthread_rwlock_unlock(&st->rwlock); + rrdset_unlock(st); return memory; } @@ -413,23 +409,23 @@ void rrd_stats_graph_json(RRDSET *st, char *options, BUFFER *wb) buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER); } -void rrd_stats_all_json(BUFFER *wb) +void rrd_stats_all_json(RRDHOST *host, BUFFER *wb) { unsigned long memory = 0; - long c; + long c = 0; RRDSET *st; buffer_strcat(wb, RRD_GRAPH_JSON_HEADER); - pthread_rwlock_rdlock(&localhost.rrdset_root_rwlock); - for(st = localhost.rrdset_root, c = 0; st ; st = st->next) { - if(st->enabled && st->dimensions) { + rrdhost_rdlock(host); + rrdset_foreach_read(st, host) { + if(rrdset_flag_check(st, RRDSET_FLAG_ENABLED) && st->dimensions) { if(c) buffer_strcat(wb, ",\n"); memory += rrd_stats_one_json(st, NULL, wb); c++; } } - pthread_rwlock_unlock(&localhost.rrdset_root_rwlock); + rrdhost_unlock(host); buffer_sprintf(wb, "\n\t],\n" "\t\"hostname\": \"%s\",\n" @@ -437,9 +433,9 @@ void rrd_stats_all_json(BUFFER *wb) "\t\"history\": %d,\n" "\t\"memory\": %lu\n" "}\n" - , localhost.hostname - , rrd_update_every - , rrd_default_history_entries + , host->hostname + , host->rrd_update_every + , host->rrd_history_entries , memory ); } @@ -546,8 +542,9 @@ static void rrdr_dump(RRDR *r) } */ -void rrdr_disable_not_selected_dimensions(RRDR *r, uint32_t options, const char *dims) -{ +void rrdr_disable_not_selected_dimensions(RRDR *r, uint32_t options, const char *dims) { + rrdset_check_rdlock(r->st); + if(unlikely(!dims || !*dims)) return; char b[strlen(dims) + 1]; @@ -568,7 +565,7 @@ void rrdr_disable_not_selected_dimensions(RRDR *r, uint32_t options, const char // find it and enable it for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { - if(unlikely((hash == d->hash && !strcmp(d->id, tok)) || !strcmp(d->name, tok))) { + if(unlikely((hash == d->hash && !strcmp(d->id, tok)) || (hash == d->hash_name && !strcmp(d->name, tok)))) { if(likely(r->od[c] & RRDR_HIDDEN)) { r->od[c] |= RRDR_SELECTED; @@ -653,6 +650,8 @@ void rrdr_buffer_print_format(BUFFER *wb, uint32_t format) uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims) { + rrdset_check_rdlock(r->st); + (void)dims; if(options & RRDR_OPTION_NONZERO) { @@ -688,6 +687,8 @@ uint32_t rrdr_check_options(RRDR *r, uint32_t options, const char *dims) void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value) { + rrdset_check_rdlock(r->st); + long rows = rrdr_rows(r); long c, i; RRDDIM *rd; @@ -869,6 +870,8 @@ void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t option static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable) { + rrdset_check_rdlock(r->st); + //info("RRD2JSON(): %s: BEGIN", r->st->id); int row_annotations = 0, dates, dates_with_new = 0; char kq[2] = "", // key quote @@ -1095,6 +1098,8 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable) static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline, const char *betweenlines) { + rrdset_check_rdlock(r->st); + //info("RRD2CSV(): %s: BEGIN", r->st->id); long c, i; RRDDIM *d; @@ -1200,6 +1205,8 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin } inline static calculated_number rrdr2value(RRDR *r, long i, uint32_t options, int *all_values_are_null) { + rrdset_check_rdlock(r->st); + long c; RRDDIM *d; @@ -1350,7 +1357,7 @@ inline static void rrdr_lock_rrdset(RRDR *r) { return; } - pthread_rwlock_rdlock(&r->st->rwlock); + rrdset_rdlock(r->st); r->has_st_lock = 1; } @@ -1361,7 +1368,7 @@ inline static void rrdr_unlock_rrdset(RRDR *r) { } if(likely(r->has_st_lock)) { - pthread_rwlock_unlock(&r->st->rwlock); + rrdset_unlock(r->st); r->has_st_lock = 0; } } @@ -1400,7 +1407,7 @@ static RRDR *rrdr_create(RRDSET *st, long n) rrdr_lock_rrdset(r); RRDDIM *rd; - for(rd = st->dimensions ; rd ; rd = rd->next) r->d++; + rrddim_foreach_read(rd, st) r->d++; r->n = n; @@ -1412,8 +1419,10 @@ static RRDR *rrdr_create(RRDSET *st, long n) // set the hidden flag on hidden dimensions int c; for(c = 0, rd = st->dimensions ; rd ; c++, rd = rd->next) { - if(unlikely(rd->flags & RRDDIM_FLAG_HIDDEN)) r->od[c] = RRDR_HIDDEN; - else r->od[c] = 0; + if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN))) + r->od[c] = RRDR_HIDDEN; + else + r->od[c] = 0; } r->c = -1; @@ -1425,7 +1434,7 @@ static RRDR *rrdr_create(RRDSET *st, long n) RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int group_method, int aligned) { - int debug = st->debug; + int debug = rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?1:0; int absolute_period_requested = -1; time_t first_entry_t = rrdset_first_entry_t(st); @@ -1601,6 +1610,7 @@ RRDR *rrd2rrdr(RRDSET *st, long points, long long after, long long before, int g // initialize them RRDDIM *rd; long c; + rrdset_check_rdlock(st); for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { last_values[c] = 0; group_values[c] = (group_method == GROUP_MAX || group_method == GROUP_MIN)?NAN:0; @@ -1996,7 +2006,7 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, int group_method, time_t after, time_t before, int only_non_zero) { int c; - pthread_rwlock_rdlock(&st->rwlock); + rrdset_rdlock(st); // ------------------------------------------------------------------------- @@ -2038,9 +2048,9 @@ time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, int dimensions = 0; RRDDIM *rd; - for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++; + rrddim_foreach_read(rd, st) dimensions++; if(!dimensions) { - pthread_rwlock_unlock(&st->rwlock); + rrdset_unlock(st); buffer_strcat(wb, "No dimensions yet."); return 0; } @@ -2060,7 +2070,7 @@ time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, // ------------------------------------------------------------------------- // checks for debugging - if(st->debug) { + if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)) { debug(D_RRD_STATS, "%s first_entry_t = %ld, last_entry_t = %ld, duration = %ld, after = %ld, before = %ld, duration = %ld, entries_to_show = %ld, group = %ld" , st->id , rrdset_first_entry_t(st) @@ -2092,7 +2102,7 @@ time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, // initialize them for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) { group_values[c] = 0; - print_hidden[c] = (rd->flags & RRDDIM_FLAG_HIDDEN)?1:0; + print_hidden[c] = rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0; found_non_zero[c] = 0; found_non_existing[c] = 0; } @@ -2153,7 +2163,8 @@ time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, long count = 0, printed = 0, group_count = 0; last_timestamp = 0; - if(st->debug) debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld" + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld" , st->id , (uint32_t)after , (uint32_t)before @@ -2173,7 +2184,8 @@ time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, int print_this = 0; - if(st->debug) debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s" + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s" , st->id , t , count + 1 @@ -2311,6 +2323,6 @@ time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long points, long group, debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %zu bytes", st->name, wb->len); - pthread_rwlock_unlock(&st->rwlock); + rrdset_unlock(st); return last_timestamp; } diff --git a/src/rrd2json.h b/src/rrd2json.h index 7b140197..18d54b7b 100644 --- a/src/rrd2json.h +++ b/src/rrd2json.h @@ -59,16 +59,16 @@ #define RRDR_OPTION_NOT_ALIGNED 0x00001000 // do not align charts for persistant timeframes extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb); -extern void rrd_stats_api_v1_charts(BUFFER *wb); +extern void rrd_stats_api_v1_charts(RRDHOST *host, BUFFER *wb); -extern void rrd_stats_api_v1_charts_allmetrics_shell(BUFFER *wb); -extern void rrd_stats_api_v1_charts_allmetrics_prometheus(BUFFER *wb); +extern void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb); +extern void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb); extern unsigned long rrd_stats_one_json(RRDSET *st, char *options, BUFFER *wb); extern void rrd_stats_graph_json(RRDSET *st, char *options, BUFFER *wb); -extern void rrd_stats_all_json(BUFFER *wb); +extern void rrd_stats_all_json(RRDHOST *host, BUFFER *wb); extern time_t rrd_stats_json(int type, RRDSET *st, BUFFER *wb, long entries_to_show, long group, int group_method, time_t after, time_t before, int only_non_zero); diff --git a/src/rrdcalc.c b/src/rrdcalc.c new file mode 100644 index 00000000..1f184540 --- /dev/null +++ b/src/rrdcalc.c @@ -0,0 +1,415 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDCALC management + +inline const char *rrdcalc_status2string(int status) { + switch(status) { + case RRDCALC_STATUS_REMOVED: + return "REMOVED"; + + case RRDCALC_STATUS_UNDEFINED: + return "UNDEFINED"; + + case RRDCALC_STATUS_UNINITIALIZED: + return "UNINITIALIZED"; + + case RRDCALC_STATUS_CLEAR: + return "CLEAR"; + + case RRDCALC_STATUS_RAISED: + return "RAISED"; + + case RRDCALC_STATUS_WARNING: + return "WARNING"; + + case RRDCALC_STATUS_CRITICAL: + return "CRITICAL"; + + default: + error("Unknown alarm status %d", status); + return "UNKNOWN"; + } +} + +static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) { + debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, st->rrdhost->hostname); + + rc->last_status_change = now_realtime_sec(); + rc->rrdset = st; + + rc->rrdset_next = st->alarms; + rc->rrdset_prev = NULL; + + if(rc->rrdset_next) + rc->rrdset_next->rrdset_prev = rc; + + st->alarms = rc; + + if(rc->update_every < rc->rrdset->update_every) { + error("Health alarm '%s.%s' has update every %d, less than chart update every %d. Setting alarm update frequency to %d.", rc->rrdset->id, rc->name, rc->update_every, rc->rrdset->update_every, rc->rrdset->update_every); + rc->update_every = rc->rrdset->update_every; + } + + if(!isnan(rc->green) && isnan(st->green)) { + debug(D_HEALTH, "Health alarm '%s.%s' green threshold set from %Lf to %Lf.", rc->rrdset->id, rc->name, rc->rrdset->green, rc->green); + st->green = rc->green; + } + + if(!isnan(rc->red) && isnan(st->red)) { + debug(D_HEALTH, "Health alarm '%s.%s' red threshold set from %Lf to %Lf.", rc->rrdset->id, rc->name, rc->rrdset->red, rc->red); + st->red = rc->red; + } + + rc->local = rrdvar_create_and_index("local", &st->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); + rc->family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value); + + char fullname[RRDVAR_MAX_LENGTH + 1]; + snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name); + rc->hostid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); + + snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name); + rc->hostname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value); + + if(!rc->units) rc->units = strdupz(st->units); + + { + time_t now = now_realtime_sec(); + health_alarm_log( + st->rrdhost, + rc->id, + rc->next_event_id++, + now, + rc->name, + rc->rrdset->id, + rc->rrdset->family, + rc->exec, + rc->recipient, + now - rc->last_status_change, + rc->old_value, + rc->value, + rc->status, + RRDCALC_STATUS_UNINITIALIZED, + rc->source, + rc->units, + rc->info, + 0, + 0 + ); + } +} + +static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) { + if( (rc->hash_chart == st->hash && !strcmp(rc->chart, st->id)) || + (rc->hash_chart == st->hash_name && !strcmp(rc->chart, st->name))) + return 1; + + return 0; +} + +// this has to be called while the RRDHOST is locked +inline void rrdsetcalc_link_matching(RRDSET *st) { + // debug(D_HEALTH, "find matching alarms for chart '%s'", st->id); + + RRDCALC *rc; + for(rc = st->rrdhost->alarms; rc ; rc = rc->next) { + if(unlikely(rc->rrdset)) + continue; + + if(unlikely(rrdcalc_is_matching_this_rrdset(rc, st))) + rrdsetcalc_link(st, rc); + } +} + +// this has to be called while the RRDHOST is locked +inline void rrdsetcalc_unlink(RRDCALC *rc) { + RRDSET *st = rc->rrdset; + + if(!st) { + debug(D_HEALTH, "Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rc->chart?rc->chart:"NOCHART", rc->name); + error("Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rc->chart?rc->chart:"NOCHART", rc->name); + return; + } + + { + time_t now = now_realtime_sec(); + health_alarm_log( + st->rrdhost, + rc->id, + rc->next_event_id++, + now, + rc->name, + rc->rrdset->id, + rc->rrdset->family, + rc->exec, + rc->recipient, + now - rc->last_status_change, + rc->old_value, + rc->value, + rc->status, + RRDCALC_STATUS_REMOVED, + rc->source, + rc->units, + rc->info, + 0, + 0 + ); + } + + RRDHOST *host = st->rrdhost; + + debug(D_HEALTH, "Health unlinking alarm '%s.%s' from chart '%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, st->id, host->hostname); + + // unlink it + if(rc->rrdset_prev) + rc->rrdset_prev->rrdset_next = rc->rrdset_next; + + if(rc->rrdset_next) + rc->rrdset_next->rrdset_prev = rc->rrdset_prev; + + if(st->alarms == rc) + st->alarms = rc->rrdset_next; + + rc->rrdset_prev = rc->rrdset_next = NULL; + + rrdvar_free(st->rrdhost, &st->variables_root_index, rc->local); + rc->local = NULL; + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rc->family); + rc->family = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostid); + rc->hostid = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostname); + rc->hostname = NULL; + + rc->rrdset = NULL; + + // RRDCALC will remain in RRDHOST + // so that if the matching chart is found in the future + // it will be applied automatically +} + +RRDCALC *rrdcalc_find(RRDSET *st, const char *name) { + RRDCALC *rc; + uint32_t hash = simple_hash(name); + + for( rc = st->alarms; rc ; rc = rc->rrdset_next ) { + if(unlikely(rc->hash == hash && !strcmp(rc->name, name))) + return rc; + } + + return NULL; +} + +inline int rrdcalc_exists(RRDHOST *host, const char *chart, const char *name, uint32_t hash_chart, uint32_t hash_name) { + RRDCALC *rc; + + if(unlikely(!chart)) { + error("attempt to find RRDCALC '%s' without giving a chart name", name); + return 1; + } + + if(unlikely(!hash_chart)) hash_chart = simple_hash(chart); + if(unlikely(!hash_name)) hash_name = simple_hash(name); + + // make sure it does not already exist + for(rc = host->alarms; rc ; rc = rc->next) { + if (unlikely(rc->chart && rc->hash == hash_name && rc->hash_chart == hash_chart && !strcmp(name, rc->name) && !strcmp(chart, rc->chart))) { + debug(D_HEALTH, "Health alarm '%s.%s' already exists in host '%s'.", chart, name, host->hostname); + error("Health alarm '%s.%s' already exists in host '%s'.", chart, name, host->hostname); + return 1; + } + } + + return 0; +} + +inline uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const char *name, uint32_t *next_event_id) { + if(chart && name) { + uint32_t hash_chart = simple_hash(chart); + uint32_t hash_name = simple_hash(name); + + // re-use old IDs, by looking them up in the alarm log + ALARM_ENTRY *ae; + for(ae = host->health_log.alarms; ae ;ae = ae->next) { + if(unlikely(ae->hash_name == hash_name && ae->hash_chart == hash_chart && !strcmp(name, ae->name) && !strcmp(chart, ae->chart))) { + if(next_event_id) *next_event_id = ae->alarm_event_id + 1; + return ae->alarm_id; + } + } + } + + return host->health_log.next_alarm_id++; +} + +inline void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc) { + rrdhost_check_rdlock(host); + + if(rc->calculation) { + rc->calculation->status = &rc->status; + rc->calculation->this = &rc->value; + rc->calculation->after = &rc->db_after; + rc->calculation->before = &rc->db_before; + rc->calculation->rrdcalc = rc; + } + + if(rc->warning) { + rc->warning->status = &rc->status; + rc->warning->this = &rc->value; + rc->warning->after = &rc->db_after; + rc->warning->before = &rc->db_before; + rc->warning->rrdcalc = rc; + } + + if(rc->critical) { + rc->critical->status = &rc->status; + rc->critical->this = &rc->value; + rc->critical->after = &rc->db_after; + rc->critical->before = &rc->db_before; + rc->critical->rrdcalc = rc; + } + + // link it to the host + if(likely(host->alarms)) { + // append it + RRDCALC *t; + for(t = host->alarms; t && t->next ; t = t->next) ; + t->next = rc; + } + else { + host->alarms = rc; + } + + // link it to its chart + RRDSET *st; + rrdset_foreach_read(st, host) { + if(rrdcalc_is_matching_this_rrdset(rc, st)) { + rrdsetcalc_link(st, rc); + break; + } + } +} + +inline RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart) { + + debug(D_HEALTH, "Health creating dynamic alarm (from template) '%s.%s'", chart, rt->name); + + if(rrdcalc_exists(host, chart, rt->name, 0, 0)) + return NULL; + + RRDCALC *rc = callocz(1, sizeof(RRDCALC)); + rc->next_event_id = 1; + rc->id = rrdcalc_get_unique_id(host, chart, rt->name, &rc->next_event_id); + rc->name = strdupz(rt->name); + rc->hash = simple_hash(rc->name); + rc->chart = strdupz(chart); + rc->hash_chart = simple_hash(rc->chart); + + if(rt->dimensions) rc->dimensions = strdupz(rt->dimensions); + + rc->green = rt->green; + rc->red = rt->red; + rc->value = NAN; + rc->old_value = NAN; + + rc->delay_up_duration = rt->delay_up_duration; + rc->delay_down_duration = rt->delay_down_duration; + rc->delay_max_duration = rt->delay_max_duration; + rc->delay_multiplier = rt->delay_multiplier; + + rc->group = rt->group; + rc->after = rt->after; + rc->before = rt->before; + rc->update_every = rt->update_every; + rc->options = rt->options; + + if(rt->exec) rc->exec = strdupz(rt->exec); + if(rt->recipient) rc->recipient = strdupz(rt->recipient); + if(rt->source) rc->source = strdupz(rt->source); + if(rt->units) rc->units = strdupz(rt->units); + if(rt->info) rc->info = strdupz(rt->info); + + if(rt->calculation) { + rc->calculation = expression_parse(rt->calculation->source, NULL, NULL); + if(!rc->calculation) + error("Health alarm '%s.%s': failed to parse calculation expression '%s'", chart, rt->name, rt->calculation->source); + } + if(rt->warning) { + rc->warning = expression_parse(rt->warning->source, NULL, NULL); + if(!rc->warning) + error("Health alarm '%s.%s': failed to re-parse warning expression '%s'", chart, rt->name, rt->warning->source); + } + if(rt->critical) { + rc->critical = expression_parse(rt->critical->source, NULL, NULL); + if(!rc->critical) + error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", chart, rt->name, rt->critical->source); + } + + debug(D_HEALTH, "Health runtime added alarm '%s.%s': exec '%s', recipient '%s', green %Lf, red %Lf, lookup: group %d, after %d, before %d, options %u, dimensions '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f", + (rc->chart)?rc->chart:"NOCHART", + rc->name, + (rc->exec)?rc->exec:"DEFAULT", + (rc->recipient)?rc->recipient:"DEFAULT", + rc->green, + rc->red, + rc->group, + rc->after, + rc->before, + rc->options, + (rc->dimensions)?rc->dimensions:"NONE", + rc->update_every, + (rc->calculation)?rc->calculation->parsed_as:"NONE", + (rc->warning)?rc->warning->parsed_as:"NONE", + (rc->critical)?rc->critical->parsed_as:"NONE", + rc->source, + rc->delay_up_duration, + rc->delay_down_duration, + rc->delay_max_duration, + rc->delay_multiplier + ); + + rrdcalc_create_part2(host, rc); + return rc; +} + +void rrdcalc_free(RRDHOST *host, RRDCALC *rc) { + if(!rc) return; + + debug(D_HEALTH, "Health removing alarm '%s.%s' of host '%s'", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); + + // unlink it from RRDSET + if(rc->rrdset) rrdsetcalc_unlink(rc); + + // unlink it from RRDHOST + if(unlikely(rc == host->alarms)) + host->alarms = rc->next; + + else { + RRDCALC *t; + for(t = host->alarms; t && t->next != rc; t = t->next) ; + if(t) { + t->next = rc->next; + rc->next = NULL; + } + else + error("Cannot unlink alarm '%s.%s' from host '%s': not found", rc->chart?rc->chart:"NOCHART", rc->name, host->hostname); + } + + expression_free(rc->calculation); + expression_free(rc->warning); + expression_free(rc->critical); + + freez(rc->name); + freez(rc->chart); + freez(rc->family); + freez(rc->dimensions); + freez(rc->exec); + freez(rc->recipient); + freez(rc->source); + freez(rc->units); + freez(rc->info); + freez(rc); +} diff --git a/src/rrdcalctemplate.c b/src/rrdcalctemplate.c new file mode 100644 index 00000000..1deec43a --- /dev/null +++ b/src/rrdcalctemplate.c @@ -0,0 +1,60 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDCALCTEMPLATE management + +void rrdcalctemplate_link_matching(RRDSET *st) { + RRDCALCTEMPLATE *rt; + + for(rt = st->rrdhost->templates; rt ; rt = rt->next) { + if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) + && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) { + RRDCALC *rc = rrdcalc_create(st->rrdhost, rt, st->id); + if(unlikely(!rc)) + error("Health tried to create alarm from template '%s', but it failed", rt->name); + +#ifdef NETDATA_INTERNAL_CHECKS + else if(rc->rrdset != st) + error("Health alarm '%s.%s' should be linked to chart '%s', but it is not", rc->chart?rc->chart:"NOCHART", rc->name, st->id); +#endif + } + } +} + +inline void rrdcalctemplate_free(RRDHOST *host, RRDCALCTEMPLATE *rt) { + debug(D_HEALTH, "Health removing template '%s' of host '%s'", rt->name, host->hostname); + + if(host->templates == rt) { + host->templates = rt->next; + } + else { + RRDCALCTEMPLATE *t; + for (t = host->templates; t && t->next != rt; t = t->next ) ; + if(t) { + t->next = rt->next; + rt->next = NULL; + } + else + error("Cannot find RRDCALCTEMPLATE '%s' linked in host '%s'", rt->name, host->hostname); + } + + expression_free(rt->calculation); + expression_free(rt->warning); + expression_free(rt->critical); + + freez(rt->family_match); + simple_pattern_free(rt->family_pattern); + + freez(rt->name); + freez(rt->exec); + freez(rt->recipient); + freez(rt->context); + freez(rt->source); + freez(rt->units); + freez(rt->info); + freez(rt->dimensions); + freez(rt); +} + + diff --git a/src/rrddim.c b/src/rrddim.c new file mode 100644 index 00000000..54a17522 --- /dev/null +++ b/src/rrddim.c @@ -0,0 +1,313 @@ +#define NETDATA_RRD_INTERNALS 1 +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDDIM index + +int rrddim_compare(void* a, void* b) { + if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1; + else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1; + else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id); +} + +#define rrddim_index_add(st, rd) (RRDDIM *)avl_insert_lock(&((st)->dimensions_index), (avl *)(rd)) +#define rrddim_index_del(st,rd ) (RRDDIM *)avl_remove_lock(&((st)->dimensions_index), (avl *)(rd)) + +static inline RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) { + RRDDIM tmp = { + .id = id, + .hash = (hash)?hash:simple_hash(id) + }; + return (RRDDIM *)avl_search_lock(&(st->dimensions_index), (avl *) &tmp); +} + + +// ---------------------------------------------------------------------------- +// RRDDIM - find a dimension + +inline RRDDIM *rrddim_find(RRDSET *st, const char *id) { + debug(D_RRD_CALLS, "rrddim_find() for chart %s, dimension %s", st->name, id); + + return rrddim_index_find(st, id, 0); +} + + +// ---------------------------------------------------------------------------- +// RRDDIM rename a dimension + +inline void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name) { + if(unlikely(!strcmp(rd->name, name))) + return; + + debug(D_RRD_CALLS, "rrddim_set_name() from %s.%s to %s.%s", st->name, rd->name, st->name, name); + + char varname[CONFIG_MAX_NAME + 1]; + snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); + rd->name = config_set_default(st->config_section, varname, name); + rd->hash_name = simple_hash(rd->name); + + rrddimvar_rename_all(rd); +} + + +// ---------------------------------------------------------------------------- +// RRDDIM create a dimension + +RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divisor, RRD_ALGORITHM algorithm) { + RRDDIM *rd = rrddim_find(st, id); + if(unlikely(rd)) { + debug(D_RRD_CALLS, "Cannot create rrd dimension '%s/%s', it already exists.", st->id, name?name:""); + return rd; + } + + char filename[FILENAME_MAX + 1]; + char fullfilename[FILENAME_MAX + 1]; + + char varname[CONFIG_MAX_NAME + 1]; + unsigned long size = sizeof(RRDDIM) + (st->entries * sizeof(storage_number)); + + debug(D_RRD_CALLS, "Adding dimension '%s/%s'.", st->id, id); + + rrdset_strncpyz_name(filename, id, FILENAME_MAX); + snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename); + + if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) { + rd = (RRDDIM *)mymmap(fullfilename, size, ((st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 1); + if(likely(rd)) { + // we have a file mapped for rd + + memset(&rd->avl, 0, sizeof(avl)); + rd->id = NULL; + rd->name = NULL; + rd->cache_filename = NULL; + rd->variables = NULL; + rd->next = NULL; + rd->rrdset = NULL; + + struct timeval now; + now_realtime_timeval(&now); + + if(strcmp(rd->magic, RRDDIMENSION_MAGIC) != 0) { + errno = 0; + info("Initializing file %s.", fullfilename); + memset(rd, 0, size); + } + else if(rd->memsize != size) { + errno = 0; + error("File %s does not have the desired size. Clearing it.", fullfilename); + memset(rd, 0, size); + } + else if(rd->multiplier != multiplier) { + errno = 0; + error("File %s does not have the same multiplier. Clearing it.", fullfilename); + memset(rd, 0, size); + } + else if(rd->divisor != divisor) { + errno = 0; + error("File %s does not have the same divisor. Clearing it.", fullfilename); + memset(rd, 0, size); + } + else if(rd->update_every != st->update_every) { + errno = 0; + error("File %s does not have the same refresh frequency. Clearing it.", fullfilename); + memset(rd, 0, size); + } + else if(dt_usec(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * USEC_PER_SEC)) { + errno = 0; + error("File %s is too old. Clearing it.", fullfilename); + memset(rd, 0, size); + } + + if(rd->algorithm && rd->algorithm != algorithm) + error("File %s does not have the expected algorithm (expected %u '%s', found %u '%s'). Previous values may be wrong." + , fullfilename, algorithm, rrd_algorithm_name(algorithm), rd->algorithm, + rrd_algorithm_name(rd->algorithm)); + + // make sure we have the right memory mode + // even if we cleared the memory + rd->rrd_memory_mode = st->rrd_memory_mode; + } + } + + if(unlikely(!rd)) { + // if we didn't manage to get a mmap'd dimension, just create one + rd = callocz(1, size); + rd->rrd_memory_mode = (st->rrd_memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_RAM; + } + + rd->memsize = size; + + strcpy(rd->magic, RRDDIMENSION_MAGIC); + + rd->id = strdupz(id); + rd->hash = simple_hash(rd->id); + + rd->cache_filename = strdupz(fullfilename); + + snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id); + rd->name = config_get(st->config_section, varname, (name && *name)?name:rd->id); + rd->hash_name = simple_hash(rd->name); + + snprintfz(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id); + rd->algorithm = rrd_algorithm_id(config_get(st->config_section, varname, rrd_algorithm_name(algorithm))); + + snprintfz(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id); + rd->multiplier = config_get_number(st->config_section, varname, multiplier); + + snprintfz(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id); + rd->divisor = config_get_number(st->config_section, varname, divisor); + if(!rd->divisor) rd->divisor = 1; + + rd->entries = st->entries; + rd->update_every = st->update_every; + + // prevent incremental calculation spikes + rd->collections_counter = 0; + rd->updated = 0; + rd->flags = 0x00000000; + + rd->calculated_value = 0; + rd->last_calculated_value = 0; + rd->collected_value = 0; + rd->last_collected_value = 0; + rd->collected_volume = 0; + rd->stored_volume = 0; + rd->last_stored_value = 0; + rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); + rd->last_collected_time.tv_sec = 0; + rd->last_collected_time.tv_usec = 0; + rd->rrdset = st; + + // append this dimension + rrdset_wrlock(st); + if(!st->dimensions) + st->dimensions = rd; + else { + RRDDIM *td = st->dimensions; + for(; td->next; td = td->next) ; + td->next = rd; + } + + if(st->rrdhost->health_enabled) { + rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, 0); + rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, 0); + rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, 0); + } + + rrdset_unlock(st); + + if(unlikely(rrddim_index_add(st, rd) != rd)) + error("RRDDIM: INTERNAL ERROR: attempt to index duplicate dimension '%s' on chart '%s'", rd->id, st->id); + + return(rd); +} + + +// ---------------------------------------------------------------------------- +// RRDDIM remove / free a dimension + +void rrddim_free(RRDSET *st, RRDDIM *rd) +{ + debug(D_RRD_CALLS, "rrddim_free() %s.%s", st->name, rd->name); + + if(rd == st->dimensions) + st->dimensions = rd->next; + else { + RRDDIM *i; + for (i = st->dimensions; i && i->next != rd; i = i->next) ; + + if (i && i->next == rd) + i->next = rd->next; + else + error("Request to free dimension '%s.%s' but it is not linked.", st->id, rd->name); + } + rd->next = NULL; + + while(rd->variables) + rrddimvar_free(rd->variables); + + if(unlikely(rrddim_index_del(st, rd) != rd)) + error("RRDDIM: INTERNAL ERROR: attempt to remove from index dimension '%s' on chart '%s', removed a different dimension.", rd->id, st->id); + + // free(rd->annotations); + + switch(rd->rrd_memory_mode) { + case RRD_MEMORY_MODE_SAVE: + debug(D_RRD_CALLS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename); + savememory(rd->cache_filename, rd, rd->memsize); + // continue to map mode - no break; + + case RRD_MEMORY_MODE_MAP: + debug(D_RRD_CALLS, "Unmapping dimension '%s'.", rd->name); + freez((void *)rd->id); + freez(rd->cache_filename); + munmap(rd, rd->memsize); + break; + + case RRD_MEMORY_MODE_NONE: + case RRD_MEMORY_MODE_RAM: + debug(D_RRD_CALLS, "Removing dimension '%s'.", rd->name); + freez((void *)rd->id); + freez(rd->cache_filename); + freez(rd); + break; + } +} + + +// ---------------------------------------------------------------------------- +// RRDDIM - set dimension options + +int rrddim_hide(RRDSET *st, const char *id) { + debug(D_RRD_CALLS, "rrddim_hide() for chart %s, dimension %s", st->name, id); + + RRDDIM *rd = rrddim_find(st, id); + if(unlikely(!rd)) { + error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id); + return 1; + } + + rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN); + return 0; +} + +int rrddim_unhide(RRDSET *st, const char *id) { + debug(D_RRD_CALLS, "rrddim_unhide() for chart %s, dimension %s", st->name, id); + + RRDDIM *rd = rrddim_find(st, id); + if(unlikely(!rd)) { + error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id); + return 1; + } + + rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN); + return 0; +} + + +// ---------------------------------------------------------------------------- +// RRDDIM - collect values for a dimension + +inline collected_number rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, collected_number value) { + debug(D_RRD_CALLS, "rrddim_set_by_pointer() for chart %s, dimension %s, value " COLLECTED_NUMBER_FORMAT, st->name, rd->name, value); + + now_realtime_timeval(&rd->last_collected_time); + rd->collected_value = value; + rd->updated = 1; + + rd->collections_counter++; + + // fprintf(stderr, "%s.%s %llu " COLLECTED_NUMBER_FORMAT " dt %0.6f" " rate " CALCULATED_NUMBER_FORMAT "\n", st->name, rd->name, st->usec_since_last_update, value, (float)((double)st->usec_since_last_update / (double)1000000), (calculated_number)((value - rd->last_collected_value) * (calculated_number)rd->multiplier / (calculated_number)rd->divisor * 1000000.0 / (calculated_number)st->usec_since_last_update)); + + return rd->last_collected_value; +} + +collected_number rrddim_set(RRDSET *st, const char *id, collected_number value) { + RRDDIM *rd = rrddim_find(st, id); + if(unlikely(!rd)) { + error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id); + return 0; + } + + return rrddim_set_by_pointer(st, rd, value); +} diff --git a/src/rrddimvar.c b/src/rrddimvar.c new file mode 100644 index 00000000..f6eb6d8e --- /dev/null +++ b/src/rrddimvar.c @@ -0,0 +1,210 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDDIMVAR management +// DIMENSION VARIABLES + +#define RRDDIMVAR_ID_MAX 1024 + +static inline void rrddimvar_free_variables(RRDDIMVAR *rs) { + RRDDIM *rd = rs->rrddim; + RRDSET *st = rd->rrdset; + + // CHART VARIABLES FOR THIS DIMENSION + + rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_id); + rs->var_local_id = NULL; + + rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local_name); + rs->var_local_name = NULL; + + // FAMILY VARIABLES FOR THIS DIMENSION + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_id); + rs->var_family_id = NULL; + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); + rs->var_family_name = NULL; + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextid); + rs->var_family_contextid = NULL; + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_contextname); + rs->var_family_contextname = NULL; + + // HOST VARIABLES FOR THIS DIMENSION + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidid); + rs->var_host_chartidid = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartidname); + rs->var_host_chartidname = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnameid); + rs->var_host_chartnameid = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_chartnamename); + rs->var_host_chartnamename = NULL; + + // KEYS + + freez(rs->key_id); + rs->key_id = NULL; + + freez(rs->key_name); + rs->key_name = NULL; + + freez(rs->key_fullidid); + rs->key_fullidid = NULL; + + freez(rs->key_fullidname); + rs->key_fullidname = NULL; + + freez(rs->key_contextid); + rs->key_contextid = NULL; + + freez(rs->key_contextname); + rs->key_contextname = NULL; + + freez(rs->key_fullnameid); + rs->key_fullnameid = NULL; + + freez(rs->key_fullnamename); + rs->key_fullnamename = NULL; +} + +static inline void rrddimvar_create_variables(RRDDIMVAR *rs) { + rrddimvar_free_variables(rs); + + RRDDIM *rd = rs->rrddim; + RRDSET *st = rd->rrdset; + + char buffer[RRDDIMVAR_ID_MAX + 1]; + + // KEYS + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->id, rs->suffix); + rs->key_id = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix); + rs->key_name = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_id); + rs->key_fullidid = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->id, rs->key_name); + rs->key_fullidname = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_id); + rs->key_contextid = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->context, rs->key_name); + rs->key_contextname = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_id); + rs->key_fullnameid = strdupz(buffer); + + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s", st->name, rs->key_name); + rs->key_fullnamename = strdupz(buffer); + + // CHART VARIABLES FOR THIS DIMENSION + // ----------------------------------- + // + // dimensions are available as: + // - $id + // - $name + + rs->var_local_id = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_id, rs->type, rs->value); + rs->var_local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->key_name, rs->type, rs->value); + + // FAMILY VARIABLES FOR THIS DIMENSION + // ----------------------------------- + // + // dimensions are available as: + // - $id (only the first, when multiple overlap) + // - $name (only the first, when multiple overlap) + // - $chart-context.id + // - $chart-context.name + + rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_id, rs->type, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_name, rs->type, rs->value); + rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextid, rs->type, rs->value); + rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_contextname, rs->type, rs->value); + + // HOST VARIABLES FOR THIS DIMENSION + // ----------------------------------- + // + // dimensions are available as: + // - $chart-id.id + // - $chart-id.name + // - $chart-name.id + // - $chart-name.name + + rs->var_host_chartidid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidid, rs->type, rs->value); + rs->var_host_chartidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullidname, rs->type, rs->value); + rs->var_host_chartnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnameid, rs->type, rs->value); + rs->var_host_chartnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullnamename, rs->type, rs->value); +} + +RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) { + RRDSET *st = rd->rrdset; + + debug(D_VARIABLES, "RRDDIMSET create for chart id '%s' name '%s', dimension id '%s', name '%s%s%s'", st->id, st->name, rd->id, (prefix)?prefix:"", rd->name, (suffix)?suffix:""); + + if(!prefix) prefix = ""; + if(!suffix) suffix = ""; + + RRDDIMVAR *rs = (RRDDIMVAR *)callocz(1, sizeof(RRDDIMVAR)); + + rs->prefix = strdupz(prefix); + rs->suffix = strdupz(suffix); + + rs->type = type; + rs->value = value; + rs->options = options; + rs->rrddim = rd; + + rs->next = rd->variables; + rd->variables = rs; + + rrddimvar_create_variables(rs); + + return rs; +} + +void rrddimvar_rename_all(RRDDIM *rd) { + RRDSET *st = rd->rrdset; + debug(D_VARIABLES, "RRDDIMSET rename for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); + + RRDDIMVAR *rs, *next = rd->variables; + while((rs = next)) { + next = rs->next; + rrddimvar_create_variables(rs); + } +} + +void rrddimvar_free(RRDDIMVAR *rs) { + RRDDIM *rd = rs->rrddim; + RRDSET *st = rd->rrdset; + debug(D_VARIABLES, "RRDDIMSET free for chart id '%s' name '%s', dimension id '%s', name '%s', prefix='%s', suffix='%s'", st->id, st->name, rd->id, rd->name, rs->prefix, rs->suffix); + + rrddimvar_free_variables(rs); + + if(rd->variables == rs) { + debug(D_VARIABLES, "RRDDIMSET removing first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); + rd->variables = rs->next; + } + else { + debug(D_VARIABLES, "RRDDIMSET removing non-first entry for chart id '%s' name '%s', dimension id '%s', name '%s'", st->id, st->name, rd->id, rd->name); + RRDDIMVAR *t; + for (t = rd->variables; t && t->next != rs; t = t->next) ; + if(!t) error("RRDDIMVAR '%s' not found in dimension '%s/%s' variables linked list", rs->key_name, st->id, rd->id); + else t->next = rs->next; + } + + freez(rs->prefix); + freez(rs->suffix); + freez(rs); +} + diff --git a/src/rrdfamily.c b/src/rrdfamily.c new file mode 100644 index 00000000..fc203e91 --- /dev/null +++ b/src/rrdfamily.c @@ -0,0 +1,58 @@ +#define NETDATA_RRD_INTERNALS 1 +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDFAMILY index + +int rrdfamily_compare(void *a, void *b) { + if(((RRDFAMILY *)a)->hash_family < ((RRDFAMILY *)b)->hash_family) return -1; + else if(((RRDFAMILY *)a)->hash_family > ((RRDFAMILY *)b)->hash_family) return 1; + else return strcmp(((RRDFAMILY *)a)->family, ((RRDFAMILY *)b)->family); +} + +#define rrdfamily_index_add(host, rc) (RRDFAMILY *)avl_insert_lock(&((host)->rrdfamily_root_index), (avl *)(rc)) +#define rrdfamily_index_del(host, rc) (RRDFAMILY *)avl_remove_lock(&((host)->rrdfamily_root_index), (avl *)(rc)) + +static RRDFAMILY *rrdfamily_index_find(RRDHOST *host, const char *id, uint32_t hash) { + RRDFAMILY tmp; + tmp.family = id; + tmp.hash_family = (hash)?hash:simple_hash(tmp.family); + + return (RRDFAMILY *)avl_search_lock(&(host->rrdfamily_root_index), (avl *) &tmp); +} + +RRDFAMILY *rrdfamily_create(RRDHOST *host, const char *id) { + RRDFAMILY *rc = rrdfamily_index_find(host, id, 0); + if(!rc) { + rc = callocz(1, sizeof(RRDFAMILY)); + + rc->family = strdupz(id); + rc->hash_family = simple_hash(rc->family); + + // initialize the variables index + avl_init_lock(&rc->variables_root_index, rrdvar_compare); + + RRDFAMILY *ret = rrdfamily_index_add(host, rc); + if(ret != rc) + fatal("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE"); + } + + rc->use_count++; + return rc; +} + +void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc) { + rc->use_count--; + if(!rc->use_count) { + RRDFAMILY *ret = rrdfamily_index_del(host, rc); + if(ret != rc) + fatal("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE"); + + if(rc->variables_root_index.avl_tree.root != NULL) + fatal("RRDFAMILY: INTERNAL ERROR: Variables index of RRDFAMILY '%s' that is freed, is not empty.", rc->family); + + freez((void *)rc->family); + freez(rc); + } +} + diff --git a/src/rrdhost.c b/src/rrdhost.c new file mode 100644 index 00000000..81c69545 --- /dev/null +++ b/src/rrdhost.c @@ -0,0 +1,490 @@ +#define NETDATA_RRD_INTERNALS 1 +#include "common.h" + +RRDHOST *localhost = NULL; + +pthread_rwlock_t rrd_rwlock = PTHREAD_RWLOCK_INITIALIZER; + +time_t rrdhost_free_orphan_time = 3600; + +// ---------------------------------------------------------------------------- +// RRDHOST index + +int rrdhost_compare(void* a, void* b) { + if(((RRDHOST *)a)->hash_machine_guid < ((RRDHOST *)b)->hash_machine_guid) return -1; + else if(((RRDHOST *)a)->hash_machine_guid > ((RRDHOST *)b)->hash_machine_guid) return 1; + else return strcmp(((RRDHOST *)a)->machine_guid, ((RRDHOST *)b)->machine_guid); +} + +avl_tree_lock rrdhost_root_index = { + .avl_tree = { NULL, rrdhost_compare }, + .rwlock = AVL_LOCK_INITIALIZER +}; + +RRDHOST *rrdhost_find_guid(const char *guid, uint32_t hash) { + debug(D_RRDHOST, "Searching in index for host with guid '%s'", guid); + + RRDHOST tmp; + strncpyz(tmp.machine_guid, guid, GUID_LEN); + tmp.hash_machine_guid = (hash)?hash:simple_hash(tmp.machine_guid); + + return (RRDHOST *)avl_search_lock(&(rrdhost_root_index), (avl *) &tmp); +} + +#define rrdhost_index_add(rrdhost) (RRDHOST *)avl_insert_lock(&(rrdhost_root_index), (avl *)(rrdhost)) +#define rrdhost_index_del(rrdhost) (RRDHOST *)avl_remove_lock(&(rrdhost_root_index), (avl *)(rrdhost)) + + +// ---------------------------------------------------------------------------- +// RRDHOST - internal helpers + +static inline void rrdhost_init_hostname(RRDHOST *host, const char *hostname) { + freez(host->hostname); + host->hostname = strdupz(hostname); + host->hash_hostname = simple_hash(host->hostname); +} + +static inline void rrdhost_init_os(RRDHOST *host, const char *os) { + freez(host->os); + host->os = strdupz(os?os:"unknown"); +} + +static inline void rrdhost_init_machine_guid(RRDHOST *host, const char *machine_guid) { + strncpy(host->machine_guid, machine_guid, GUID_LEN); + host->machine_guid[GUID_LEN] = '\0'; + host->hash_machine_guid = simple_hash(host->machine_guid); +} + + +// ---------------------------------------------------------------------------- +// RRDHOST - add a host + +RRDHOST *rrdhost_create(const char *hostname, + const char *guid, + const char *os, + int update_every, + int entries, + RRD_MEMORY_MODE memory_mode, + int health_enabled, + int rrdpush_enabled, + char *rrdpush_destination, + char *rrdpush_api_key, + int is_localhost +) { + + debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid); + + RRDHOST *host = callocz(1, sizeof(RRDHOST)); + + host->rrd_update_every = update_every; + host->rrd_history_entries = entries; + host->rrd_memory_mode = memory_mode; + host->health_enabled = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled; + host->rrdpush_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key); + host->rrdpush_destination = (host->rrdpush_enabled)?strdupz(rrdpush_destination):NULL; + host->rrdpush_api_key = (host->rrdpush_enabled)?strdupz(rrdpush_api_key):NULL; + + host->rrdpush_pipe[0] = -1; + host->rrdpush_pipe[1] = -1; + host->rrdpush_socket = -1; + + pthread_mutex_init(&host->rrdpush_mutex, NULL); + pthread_rwlock_init(&host->rrdhost_rwlock, NULL); + + rrdhost_init_hostname(host, hostname); + rrdhost_init_machine_guid(host, guid); + rrdhost_init_os(host, os); + + avl_init_lock(&(host->rrdset_root_index), rrdset_compare); + avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name); + avl_init_lock(&(host->rrdfamily_root_index), rrdfamily_compare); + avl_init_lock(&(host->variables_root_index), rrdvar_compare); + + // ------------------------------------------------------------------------ + // initialize health variables + + host->health_log.next_log_id = 1; + host->health_log.next_alarm_id = 1; + host->health_log.max = 1000; + host->health_log.next_log_id = + host->health_log.next_alarm_id = (uint32_t)now_realtime_sec(); + + long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max); + if(n < 10) { + error("Host '%s': health configuration has invalid max log entries %ld. Using default %u", host->hostname, n, host->health_log.max); + config_set_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", (long)host->health_log.max); + } + else + host->health_log.max = (unsigned int)n; + + pthread_rwlock_init(&(host->health_log.alarm_log_rwlock), NULL); + + char filename[FILENAME_MAX + 1]; + + if(is_localhost) { + + host->cache_dir = strdupz(netdata_configured_cache_dir); + host->varlib_dir = strdupz(netdata_configured_varlib_dir); + + } + else { + // this is not localhost - append our GUID to localhost path + + snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid); + host->cache_dir = strdupz(filename); + + if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { + int r = mkdir(host->cache_dir, 0775); + if(r != 0 && errno != EEXIST) + error("Host '%s': cannot create directory '%s'", host->hostname, host->cache_dir); + } + + snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid); + host->varlib_dir = strdupz(filename); + + if(host->health_enabled) { + int r = mkdir(host->varlib_dir, 0775); + if(r != 0 && errno != EEXIST) + error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir); + + snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir); + r = mkdir(filename, 0775); + if(r != 0 && errno != EEXIST) + error("Host '%s': cannot create directory '%s'", host->hostname, filename); + } + + } + + snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir); + host->health_log_filename = strdupz(filename); + + snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir); + host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename)); + host->health_default_recipient = strdup("root"); + + + // ------------------------------------------------------------------------ + // load health configuration + + if(host->health_enabled) { + health_alarm_log_load(host); + health_alarm_log_open(host); + + rrdhost_wrlock(host); + health_readdir(host, health_config_dir()); + rrdhost_unlock(host); + } + + + // ------------------------------------------------------------------------ + // link it and add it to the index + + rrd_wrlock(); + + if(is_localhost) { + host->next = localhost; + localhost = host; + } + else { + if(localhost) { + host->next = localhost->next; + localhost->next = host; + } + else localhost = host; + } + + RRDHOST *t = rrdhost_index_add(host); + + if(t != host) { + error("Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.", host->hostname, host->machine_guid, t->hostname, t->machine_guid); + rrdhost_free(host); + host = NULL; + } + else { + info("Host '%s' with guid '%s' initialized" + ", os %s" + ", update every %d" + ", memory mode %s" + ", history entries %d" + ", streaming %s" + " (to '%s' with api key '%s')" + ", health %s" + ", cache_dir '%s'" + ", varlib_dir '%s'" + ", health_log '%s'" + ", alarms default handler '%s'" + ", alarms default recipient '%s'" + , host->hostname + , host->machine_guid + , host->os + , host->rrd_update_every + , rrd_memory_mode_name(host->rrd_memory_mode) + , host->rrd_history_entries + , host->rrdpush_enabled?"enabled":"disabled" + , host->rrdpush_destination?host->rrdpush_destination:"" + , host->rrdpush_api_key?host->rrdpush_api_key:"" + , host->health_enabled?"enabled":"disabled" + , host->cache_dir + , host->varlib_dir + , host->health_log_filename + , host->health_default_exec + , host->health_default_recipient + ); + } + + rrd_unlock(); + + return host; +} + +RRDHOST *rrdhost_find_or_create( + const char *hostname + , const char *guid + , const char *os + , int update_every + , int history + , RRD_MEMORY_MODE mode + , int health_enabled + , int rrdpush_enabled + , char *rrdpush_destination + , char *rrdpush_api_key +) { + debug(D_RRDHOST, "Searching for host '%s' with guid '%s'", hostname, guid); + + RRDHOST *host = rrdhost_find_guid(guid, 0); + if(!host) { + host = rrdhost_create( + hostname + , guid + , os + , update_every + , history + , mode + , health_enabled + , rrdpush_enabled + , rrdpush_destination + , rrdpush_api_key + , 0 + ); + } + else { + host->health_enabled = health_enabled; + + if(strcmp(host->hostname, hostname)) { + char *t = host->hostname; + char *n = strdupz(hostname); + host->hostname = n; + freez(t); + } + + if(host->rrd_update_every != update_every) + error("Host '%s' has an update frequency of %d seconds, but the wanted one is %d seconds.", host->hostname, host->rrd_update_every, update_every); + + if(host->rrd_history_entries != history) + error("Host '%s' has history of %d entries, but the wanted one is %d entries.", host->hostname, host->rrd_history_entries, history); + + if(host->rrd_memory_mode != mode) + error("Host '%s' has memory mode '%s', but the wanted one is '%s'.", host->hostname, rrd_memory_mode_name(host->rrd_memory_mode), rrd_memory_mode_name(mode)); + } + + rrdhost_cleanup_remote_stale(host); + + return host; +} + +void rrdhost_cleanup_remote_stale(RRDHOST *protected) { + rrd_wrlock(); + + RRDHOST *h; + rrdhost_foreach_write(h) { + if(h != protected + && h != localhost + && !h->connected_senders + && h->senders_disconnected_time + rrdhost_free_orphan_time > now_realtime_sec()) { + info("Host '%s' with machine guid '%s' is obsolete - cleaning up.", h->hostname, h->machine_guid); + rrdhost_save(h); + rrdhost_free(h); + break; + } + } + + rrd_unlock(); +} + +// ---------------------------------------------------------------------------- +// RRDHOST global / startup initialization + +void rrd_init(char *hostname) { + health_init(); + registry_init(); + rrdpush_init(); + + debug(D_RRDHOST, "Initializing localhost with hostname '%s'", hostname); + localhost = rrdhost_create( + hostname + , registry_get_this_machine_guid() + , os_type + , default_rrd_update_every + , default_rrd_history_entries + , default_rrd_memory_mode + , default_health_enabled + , default_rrdpush_enabled + , default_rrdpush_destination + , default_rrdpush_api_key + , 1 + ); +} + +// ---------------------------------------------------------------------------- +// RRDHOST - lock validations +// there are only used when NETDATA_INTERNAL_CHECKS is set + +void rrdhost_check_rdlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) { + debug(D_RRDHOST, "Checking read lock on host '%s'", host->hostname); + + int ret = pthread_rwlock_trywrlock(&host->rrdhost_rwlock); + if(ret == 0) + fatal("RRDHOST '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file); +} + +void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) { + debug(D_RRDHOST, "Checking write lock on host '%s'", host->hostname); + + int ret = pthread_rwlock_tryrdlock(&host->rrdhost_rwlock); + if(ret == 0) + fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file); +} + +void rrd_check_rdlock_int(const char *file, const char *function, const unsigned long line) { + debug(D_RRDHOST, "Checking read lock on all RRDs"); + + int ret = pthread_rwlock_trywrlock(&rrd_rwlock); + if(ret == 0) + fatal("RRDs should be read-locked, but it are not, at function %s() at line %lu of file '%s'", function, line, file); +} + +void rrd_check_wrlock_int(const char *file, const char *function, const unsigned long line) { + debug(D_RRDHOST, "Checking write lock on all RRDs"); + + int ret = pthread_rwlock_tryrdlock(&rrd_rwlock); + if(ret == 0) + fatal("RRDs should be write-locked, but it are not, at function %s() at line %lu of file '%s'", function, line, file); +} + +// ---------------------------------------------------------------------------- +// RRDHOST - free + +void rrdhost_free(RRDHOST *host) { + if(!host) return; + + info("Freeing all memory for host '%s'...", host->hostname); + + rrd_check_wrlock(); // make sure the RRDs are write locked + rrdhost_wrlock(host); // lock this RRDHOST + + // ------------------------------------------------------------------------ + // release its children resources + + while(host->rrdset_root) rrdset_free(host->rrdset_root); + + while(host->alarms) rrdcalc_free(host, host->alarms); + while(host->templates) rrdcalctemplate_free(host, host->templates); + health_alarm_log_free(host); + + + // ------------------------------------------------------------------------ + // remove it from the indexes + + if(rrdhost_index_del(host) != host) + error("RRDHOST '%s' removed from index, deleted the wrong entry.", host->hostname); + + + // ------------------------------------------------------------------------ + // unlink it from the host + + if(host == localhost) { + localhost = host->next; + } + else { + // find the previous one + RRDHOST *h; + for(h = localhost; h && h->next != host ; h = h->next) ; + + // bypass it + if(h) h->next = host->next; + else error("Request to free RRDHOST '%s': cannot find it", host->hostname); + } + + // ------------------------------------------------------------------------ + // free it + + rrdpush_sender_thread_stop(host); + + freez(host->os); + freez(host->cache_dir); + freez(host->varlib_dir); + freez(host->rrdpush_api_key); + freez(host->rrdpush_destination); + freez(host->health_default_exec); + freez(host->health_default_recipient); + freez(host->health_log_filename); + freez(host->hostname); + rrdhost_unlock(host); + freez(host); + + info("Host memory cleanup completed..."); +} + +void rrdhost_free_all(void) { + rrd_wrlock(); + while(localhost) rrdhost_free(localhost); + rrd_unlock(); +} + +// ---------------------------------------------------------------------------- +// RRDHOST - save + +void rrdhost_save(RRDHOST *host) { + if(!host) return; + + info("Saving host '%s' database...", host->hostname); + + RRDSET *st; + RRDDIM *rd; + + // we get a write lock + // to ensure only one thread is saving the database + rrdhost_wrlock(host); + + rrdset_foreach_write(st, host) { + rrdset_rdlock(st); + + if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { + debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename); + savememory(st->cache_filename, st, st->memsize); + } + + rrddim_foreach_read(rd, st) { + if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE)) { + debug(D_RRD_STATS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename); + savememory(rd->cache_filename, rd, rd->memsize); + } + } + + rrdset_unlock(st); + } + + rrdhost_unlock(host); +} + +void rrdhost_save_all(void) { + info("Saving database..."); + + rrd_rdlock(); + + RRDHOST *host; + rrdhost_foreach_read(host) + rrdhost_save(host); + + rrd_unlock(); +} diff --git a/src/rrdpush.c b/src/rrdpush.c new file mode 100644 index 00000000..60923287 --- /dev/null +++ b/src/rrdpush.c @@ -0,0 +1,733 @@ +#include "common.h" + +/* + * rrdpush + * + * 3 threads are involved for all stream operations + * + * 1. a random data collection thread, calling rrdset_done_push() + * this is called for each chart. + * + * the output of this work is kept in a BUFFER in RRDHOST + * the sender thread is signalled via a pipe (also in RRDHOST) + * + * 2. a sender thread running at the sending netdata + * this is spawned automatically on the first chart to be pushed + * + * It tries to push the metrics to the remote netdata, as fast + * as possible (i.e. immediately after they are collected). + * + * 3. a receiver thread, running at the receiving netdata + * this is spawned automatically when the sender connects to + * the receiver. + * + */ + +#define START_STREAMING_PROMPT "Hit me baby, push them over..." + +int default_rrdpush_enabled = 0; +char *default_rrdpush_destination = NULL; +char *default_rrdpush_api_key = NULL; + +int rrdpush_init() { + default_rrdpush_enabled = appconfig_get_boolean(&stream_config, CONFIG_SECTION_STREAM, "enabled", default_rrdpush_enabled); + default_rrdpush_destination = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "destination", ""); + default_rrdpush_api_key = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "api key", ""); + rrdhost_free_orphan_time = appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "free orphan hosts after seconds", rrdhost_free_orphan_time); + + if(default_rrdpush_enabled && (!default_rrdpush_destination || !*default_rrdpush_destination || !default_rrdpush_api_key || !*default_rrdpush_api_key)) { + error("STREAM [send]: cannot enable sending thread - information is missing."); + default_rrdpush_enabled = 0; + } + + return default_rrdpush_enabled; +} + +#define CONNECTED_TO_SIZE 100 + +// data collection happens from multiple threads +// each of these threads calls rrdset_done() +// which in turn calls rrdset_done_push() +// which uses this pipe to notify the streaming thread +// that there are more data ready to be sent +#define PIPE_READ 0 +#define PIPE_WRITE 1 + +// to have the remote netdata re-sync the charts +// to its current clock, we send for this many +// iterations a BEGIN line without microseconds +// this is for the first iterations of each chart +static unsigned int remote_clock_resync_iterations = 60; + +#define rrdpush_lock(host) pthread_mutex_lock(&((host)->rrdpush_mutex)) +#define rrdpush_unlock(host) pthread_mutex_unlock(&((host)->rrdpush_mutex)) + +// checks if the current chart definition has been sent +static inline int need_to_send_chart_definition(RRDSET *st) { + RRDDIM *rd; + rrddim_foreach_read(rd, st) + if(!rd->exposed) + return 1; + + return 0; +} + +// sends the current chart definition +static inline void send_chart_definition(RRDSET *st) { + buffer_sprintf(st->rrdhost->rrdpush_buffer, "CHART '%s' '%s' '%s' '%s' '%s' '%s' '%s' %ld %d\n" + , st->id + , st->name + , st->title + , st->units + , st->family + , st->context + , rrdset_type_name(st->chart_type) + , st->priority + , st->update_every + ); + + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + buffer_sprintf(st->rrdhost->rrdpush_buffer, "DIMENSION '%s' '%s' '%s' " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " '%s %s'\n" + , rd->id + , rd->name + , rrd_algorithm_name(rd->algorithm) + , rd->multiplier + , rd->divisor + , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?"hidden":"" + , rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS)?"noreset":"" + ); + rd->exposed = 1; + } +} + +// sends the current chart dimensions +static inline void send_chart_metrics(RRDSET *st) { + buffer_sprintf(st->rrdhost->rrdpush_buffer, "BEGIN %s %llu\n", st->id, (st->counter_done > remote_clock_resync_iterations)?st->usec_since_last_update:0); + + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + if(rd->updated && rd->exposed) + buffer_sprintf(st->rrdhost->rrdpush_buffer, "SET %s = " COLLECTED_NUMBER_FORMAT "\n" + , rd->id + , rd->collected_value + ); + } + + buffer_strcat(st->rrdhost->rrdpush_buffer, "END\n"); +} + +void rrdpush_sender_thread_spawn(RRDHOST *host); + +void rrdset_done_push(RRDSET *st) { + RRDHOST *host = st->rrdhost; + + if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_ENABLED))) + return; + + rrdpush_lock(host); + + if(unlikely(host->rrdpush_enabled && !host->rrdpush_spawn)) + rrdpush_sender_thread_spawn(host); + + if(unlikely(!host->rrdpush_buffer || !host->rrdpush_connected)) { + if(unlikely(!host->rrdpush_error_shown)) + error("STREAM %s [send]: not ready - discarding collected metrics.", host->hostname); + + host->rrdpush_error_shown = 1; + + rrdpush_unlock(host); + return; + } + else if(unlikely(host->rrdpush_error_shown)) { + info("STREAM %s [send]: ready - sending metrics...", host->hostname); + host->rrdpush_error_shown = 0; + } + + if(need_to_send_chart_definition(st)) + send_chart_definition(st); + + send_chart_metrics(st); + + // signal the sender there are more data + if(write(host->rrdpush_pipe[PIPE_WRITE], " ", 1) == -1) + error("STREAM %s [send]: cannot write to internal pipe", host->hostname); + + rrdpush_unlock(host); +} + +// ---------------------------------------------------------------------------- +// rrdpush sender thread + +// resets all the chart, so that their definitions +// will be resent to the central netdata +static void rrdpush_sender_thread_reset_all_charts(RRDHOST *host) { + rrdhost_rdlock(host); + + RRDSET *st; + rrdset_foreach_read(st, host) { + + // make it re-align the current time + // on the remote host + st->counter_done = 0; + + rrdset_rdlock(st); + + RRDDIM *rd; + rrddim_foreach_read(rd, st) + rd->exposed = 0; + + rrdset_unlock(st); + } + + rrdhost_unlock(host); +} + +static inline void rrdpush_sender_thread_data_flush(RRDHOST *host) { + rrdpush_lock(host); + if(buffer_strlen(host->rrdpush_buffer)) + error("STREAM %s [send]: discarding %zu bytes of metrics already in the buffer.", host->hostname, buffer_strlen(host->rrdpush_buffer)); + + buffer_flush(host->rrdpush_buffer); + rrdpush_sender_thread_reset_all_charts(host); + rrdpush_unlock(host); +} + +static inline void rrdpush_sender_thread_lock(RRDHOST *host) { + if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel state to DISABLE.", host->hostname); + + rrdpush_lock(host); +} + +static inline void rrdpush_sender_thread_unlock(RRDHOST *host) { + if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel state to DISABLE.", host->hostname); + + rrdpush_unlock(host); +} + +static void rrdpush_sender_thread_cleanup(RRDHOST *host) { + rrdpush_lock(host); + + host->rrdpush_connected = 0; + + if(host->rrdpush_socket != -1) { + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + } + + // close the pipe + if(host->rrdpush_pipe[PIPE_READ] != -1) { + close(host->rrdpush_pipe[PIPE_READ]); + host->rrdpush_pipe[PIPE_READ] = -1; + } + + if(host->rrdpush_pipe[PIPE_WRITE] != -1) { + close(host->rrdpush_pipe[PIPE_WRITE]); + host->rrdpush_pipe[PIPE_WRITE] = -1; + } + + buffer_free(host->rrdpush_buffer); + host->rrdpush_buffer = NULL; + + host->rrdpush_spawn = 0; + + rrdpush_unlock(host); +} + +void rrdpush_sender_thread_stop(RRDHOST *host) { + rrdhost_check_wrlock(host); + + if(host->rrdpush_spawn) { + info("STREAM %s [send]: stopping sending thread...", host->hostname); + pthread_cancel(host->rrdpush_thread); + rrdpush_sender_thread_cleanup(host); + } +} + +void *rrdpush_sender_thread(void *ptr) { + RRDHOST *host = (RRDHOST *)ptr; + + info("STREAM %s [send]: thread created (task id %d)", host->hostname, gettid()); + + if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel type to DEFERRED.", host->hostname); + + if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) + error("STREAM %s [send]: cannot set pthread cancel state to ENABLE.", host->hostname); + + int timeout = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "timeout seconds", 60); + int default_port = (int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "default port", 19999); + size_t max_size = (size_t)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "buffer size bytes", 1024 * 1024); + unsigned int reconnect_delay = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "reconnect delay seconds", 5); + remote_clock_resync_iterations = (unsigned int)appconfig_get_number(&stream_config, CONFIG_SECTION_STREAM, "initial clock resync iterations", remote_clock_resync_iterations); + char connected_to[CONNECTED_TO_SIZE + 1] = ""; + + if(!host->rrdpush_enabled || !host->rrdpush_destination || !*host->rrdpush_destination || !host->rrdpush_api_key || !*host->rrdpush_api_key) + goto cleanup; + + // initialize rrdpush globals + host->rrdpush_buffer = buffer_create(1); + host->rrdpush_connected = 0; + if(pipe(host->rrdpush_pipe) == -1) fatal("STREAM %s [send]: cannot create required pipe.", host->hostname); + + // initialize local variables + size_t begin = 0; + size_t reconnects_counter = 0; + size_t sent_bytes = 0; + size_t sent_connection = 0; + + struct timeval tv = { + .tv_sec = timeout, + .tv_usec = 0 + }; + + struct pollfd fds[2], *ifd, *ofd; + nfds_t fdmax; + + ifd = &fds[0]; + ofd = &fds[1]; + + for(; host->rrdpush_enabled && !netdata_exit ;) { + + if(unlikely(host->rrdpush_socket == -1)) { + // stop appending data into rrdpush_buffer + // they will be lost, so there is no point to do it + host->rrdpush_connected = 0; + + info("STREAM %s [send to %s]: connecting...", host->hostname, host->rrdpush_destination); + host->rrdpush_socket = connect_to_one_of(host->rrdpush_destination, default_port, &tv, &reconnects_counter, connected_to, CONNECTED_TO_SIZE); + + if(unlikely(host->rrdpush_socket == -1)) { + error("STREAM %s [send to %s]: failed to connect", host->hostname, host->rrdpush_destination); + sleep(reconnect_delay); + continue; + } + + info("STREAM %s [send to %s]: initializing communication...", host->hostname, connected_to); + + char http[1000 + 1]; + snprintfz(http, 1000, + "STREAM key=%s&hostname=%s&machine_guid=%s&os=%s&update_every=%d HTTP/1.1\r\n" + "User-Agent: netdata-push-service/%s\r\n" + "Accept: */*\r\n\r\n" + , host->rrdpush_api_key + , host->hostname + , host->machine_guid + , host->os + , default_rrd_update_every + , program_version + ); + + if(send_timeout(host->rrdpush_socket, http, strlen(http), 0, timeout) == -1) { + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + error("STREAM %s [send to %s]: failed to send http header to netdata", host->hostname, connected_to); + sleep(reconnect_delay); + continue; + } + + info("STREAM %s [send to %s]: waiting response from remote netdata...", host->hostname, connected_to); + + if(recv_timeout(host->rrdpush_socket, http, 1000, 0, timeout) == -1) { + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + error("STREAM %s [send to %s]: failed to initialize communication", host->hostname, connected_to); + sleep(reconnect_delay); + continue; + } + + if(strncmp(http, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT))) { + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + error("STREAM %s [send to %s]: server is not replying properly.", host->hostname, connected_to); + sleep(reconnect_delay); + continue; + } + + info("STREAM %s [send to %s]: established communication - sending metrics...", host->hostname, connected_to); + + if(fcntl(host->rrdpush_socket, F_SETFL, O_NONBLOCK) < 0) + error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", host->hostname, connected_to); + + rrdpush_sender_thread_data_flush(host); + sent_connection = 0; + + // allow appending data into rrdpush_buffer + host->rrdpush_connected = 1; + } + + ifd->fd = host->rrdpush_pipe[PIPE_READ]; + ifd->events = POLLIN; + ifd->revents = 0; + + ofd->fd = host->rrdpush_socket; + ofd->revents = 0; + if(begin < buffer_strlen(host->rrdpush_buffer)) { + ofd->events = POLLOUT; + fdmax = 2; + } + else { + ofd->events = 0; + fdmax = 1; + } + + if(netdata_exit) break; + int retval = poll(fds, fdmax, timeout * 1000); + if(netdata_exit) break; + + if(unlikely(retval == -1)) { + if(errno == EAGAIN || errno == EINTR) + continue; + + error("STREAM %s [send to %s]: failed to poll().", host->hostname, connected_to); + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + break; + } + else if(unlikely(!retval)) { + // timeout + continue; + } + + if(ifd->revents & POLLIN) { + char buffer[1000 + 1]; + if(read(host->rrdpush_pipe[PIPE_READ], buffer, 1000) == -1) + error("STREAM %s [send to %s]: cannot read from internal pipe.", host->hostname, connected_to); + } + + if(ofd->revents & POLLOUT && begin < buffer_strlen(host->rrdpush_buffer)) { + rrdpush_sender_thread_lock(host); + ssize_t ret = send(host->rrdpush_socket, &host->rrdpush_buffer->buffer[begin], buffer_strlen(host->rrdpush_buffer) - begin, MSG_DONTWAIT); + if(ret == -1) { + if(errno != EAGAIN && errno != EINTR) { + error("STREAM %s [send to %s]: failed to send metrics - closing connection - we have sent %zu bytes on this connection.", host->hostname, connected_to, sent_connection); + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + } + } + else { + sent_connection += ret; + sent_bytes += ret; + begin += ret; + if(begin == buffer_strlen(host->rrdpush_buffer)) { + buffer_flush(host->rrdpush_buffer); + begin = 0; + } + } + rrdpush_sender_thread_unlock(host); + } + + // protection from overflow + if(host->rrdpush_buffer->len > max_size) { + errno = 0; + error("STREAM %s [send to %s]: too many data pending - buffer is %zu bytes long, %zu unsent - we have sent %zu bytes in total, %zu on this connection. Closing connection to flush the data.", host->hostname, connected_to, host->rrdpush_buffer->len, host->rrdpush_buffer->len - begin, sent_bytes, sent_connection); + if(host->rrdpush_socket != -1) { + close(host->rrdpush_socket); + host->rrdpush_socket = -1; + } + } + } + +cleanup: + debug(D_WEB_CLIENT, "STREAM %s [send]: sending thread exits.", host->hostname); + + rrdpush_sender_thread_cleanup(host); + + pthread_exit(NULL); + return NULL; +} + + +// ---------------------------------------------------------------------------- +// rrdpush receiver thread + +int rrdpush_receive(int fd, const char *key, const char *hostname, const char *machine_guid, const char *os, int update_every, char *client_ip, char *client_port) { + RRDHOST *host; + int history = default_rrd_history_entries; + RRD_MEMORY_MODE mode = default_rrd_memory_mode; + int health_enabled = default_health_enabled; + int rrdpush_enabled = default_rrdpush_enabled; + char *rrdpush_destination = default_rrdpush_destination; + char *rrdpush_api_key = default_rrdpush_api_key; + time_t alarms_delay = 60; + + update_every = (int)appconfig_get_number(&stream_config, machine_guid, "update every", update_every); + if(update_every < 0) update_every = 1; + + history = (int)appconfig_get_number(&stream_config, key, "default history", history); + history = (int)appconfig_get_number(&stream_config, machine_guid, "history", history); + if(history < 5) history = 5; + + mode = rrd_memory_mode_id(appconfig_get(&stream_config, key, "default memory mode", rrd_memory_mode_name(mode))); + mode = rrd_memory_mode_id(appconfig_get(&stream_config, machine_guid, "memory mode", rrd_memory_mode_name(mode))); + + health_enabled = appconfig_get_boolean_ondemand(&stream_config, key, "health enabled by default", health_enabled); + health_enabled = appconfig_get_boolean_ondemand(&stream_config, machine_guid, "health enabled", health_enabled); + + alarms_delay = appconfig_get_number(&stream_config, key, "default postpone alarms on connect seconds", alarms_delay); + alarms_delay = appconfig_get_number(&stream_config, machine_guid, "postpone alarms on connect seconds", alarms_delay); + + rrdpush_enabled = appconfig_get_boolean(&stream_config, key, "default proxy enabled", rrdpush_enabled); + rrdpush_enabled = appconfig_get_boolean(&stream_config, machine_guid, "proxy enabled", rrdpush_enabled); + + rrdpush_destination = appconfig_get(&stream_config, key, "default proxy destination", rrdpush_destination); + rrdpush_destination = appconfig_get(&stream_config, machine_guid, "proxy destination", rrdpush_destination); + + rrdpush_api_key = appconfig_get(&stream_config, key, "default proxy api key", rrdpush_api_key); + rrdpush_api_key = appconfig_get(&stream_config, machine_guid, "proxy api key", rrdpush_api_key); + + if(!strcmp(machine_guid, "localhost")) + host = localhost; + else + host = rrdhost_find_or_create( + hostname + , machine_guid + , os + , update_every + , history + , mode + , (health_enabled != CONFIG_BOOLEAN_NO) + , (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key) + , rrdpush_destination + , rrdpush_api_key + ); + + if(!host) { + close(fd); + error("STREAM %s [receive from [%s]:%s]: failed to find/create host structure.", hostname, client_ip, client_port); + return 1; + } + +#ifdef NETDATA_INTERNAL_CHECKS + info("STREAM %s [receive from [%s]:%s]: client willing to stream metrics for host '%s' with machine_guid '%s': update every = %d, history = %d, memory mode = %s, health %s" + , hostname + , client_ip + , client_port + , host->hostname + , host->machine_guid + , host->rrd_update_every + , host->rrd_history_entries + , rrd_memory_mode_name(host->rrd_memory_mode) + , (health_enabled == CONFIG_BOOLEAN_NO)?"disabled":((health_enabled == CONFIG_BOOLEAN_YES)?"enabled":"auto") + ); +#endif // NETDATA_INTERNAL_CHECKS + + struct plugind cd = { + .enabled = 1, + .update_every = default_rrd_update_every, + .pid = 0, + .serial_failures = 0, + .successful_collections = 0, + .obsolete = 0, + .started_t = now_realtime_sec(), + .next = NULL, + }; + + // put the client IP and port into the buffers used by plugins.d + snprintfz(cd.id, CONFIG_MAX_NAME, "%s:%s", client_ip, client_port); + snprintfz(cd.filename, FILENAME_MAX, "%s:%s", client_ip, client_port); + snprintfz(cd.fullfilename, FILENAME_MAX, "%s:%s", client_ip, client_port); + snprintfz(cd.cmd, PLUGINSD_CMD_MAX, "%s:%s", client_ip, client_port); + + info("STREAM %s [receive from [%s]:%s]: initializing communication...", host->hostname, client_ip, client_port); + if(send_timeout(fd, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT), 0, 60) != strlen(START_STREAMING_PROMPT)) { + error("STREAM %s [receive from [%s]:%s]: cannot send ready command.", host->hostname, client_ip, client_port); + return 0; + } + + // remove the non-blocking flag from the socket + if(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK) == -1) + error("STREAM %s [receive from [%s]:%s]: cannot remove the non-blocking flag from socket %d", host->hostname, client_ip, client_port, fd); + + // convert the socket to a FILE * + FILE *fp = fdopen(fd, "r"); + if(!fp) { + error("STREAM %s [receive from [%s]:%s]: failed to get a FILE for FD %d.", host->hostname, client_ip, client_port, fd); + return 0; + } + + rrdhost_wrlock(host); + host->connected_senders++; + if(health_enabled != CONFIG_BOOLEAN_NO) + host->health_delay_up_to = now_realtime_sec() + alarms_delay; + rrdhost_unlock(host); + + // call the plugins.d processor to receive the metrics + info("STREAM %s [receive from [%s]:%s]: receiving metrics...", host->hostname, client_ip, client_port); + size_t count = pluginsd_process(host, &cd, fp, 1); + error("STREAM %s [receive from [%s]:%s]: disconnected (completed updates %zu).", host->hostname, client_ip, client_port, count); + + rrdhost_wrlock(host); + host->connected_senders--; + if(!host->connected_senders) { + if(health_enabled == CONFIG_BOOLEAN_AUTO) + host->health_enabled = 0; + + host->senders_disconnected_time = now_realtime_sec(); + + rrdpush_sender_thread_stop(host); + } + rrdhost_unlock(host); + + // cleanup + fclose(fp); + + return (int)count; +} + +struct rrdpush_thread { + int fd; + char *key; + char *hostname; + char *machine_guid; + char *os; + char *client_ip; + char *client_port; + int update_every; +}; + +void *rrdpush_receiver_thread(void *ptr) { + struct rrdpush_thread *rpt = (struct rrdpush_thread *)ptr; + + if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) + error("STREAM %s [receive]: cannot set pthread cancel type to DEFERRED.", rpt->hostname); + + if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) + error("STREAM %s [receive]: cannot set pthread cancel state to ENABLE.", rpt->hostname); + + + info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid()); + rrdpush_receive(rpt->fd, rpt->key, rpt->hostname, rpt->machine_guid, rpt->os, rpt->update_every, rpt->client_ip, rpt->client_port); + info("STREAM %s [receive from [%s]:%s]: receive thread ended (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid()); + + close(rpt->fd); + freez(rpt->key); + freez(rpt->hostname); + freez(rpt->machine_guid); + freez(rpt->os); + freez(rpt->client_ip); + freez(rpt->client_port); + freez(rpt); + + pthread_exit(NULL); + return NULL; +} + +void rrdpush_sender_thread_spawn(RRDHOST *host) { + if(pthread_create(&host->rrdpush_thread, NULL, rrdpush_sender_thread, (void *)host)) + error("STREAM %s [send]: failed to create new thread for client.", host->hostname); + + else if(pthread_detach(host->rrdpush_thread)) + error("STREAM %s [send]: cannot request detach newly created thread.", host->hostname); + + host->rrdpush_spawn = 1; +} + +int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url) { + (void)host; + + info("STREAM [receive from [%s]:%s]: new client connection.", w->client_ip, w->client_port); + + char *key = NULL, *hostname = NULL, *machine_guid = NULL, *os = NULL; + int update_every = default_rrd_update_every; + char buf[GUID_LEN + 1]; + + while(url) { + char *value = mystrsep(&url, "?&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + if(!strcmp(name, "key")) + key = value; + else if(!strcmp(name, "hostname")) + hostname = value; + else if(!strcmp(name, "machine_guid")) + machine_guid = value; + else if(!strcmp(name, "update_every")) + update_every = (int)strtoul(value, NULL, 0); + else if(!strcmp(name, "os")) + os = value; + } + + if(!key || !*key) { + error("STREAM [receive from [%s]:%s]: request without an API key. Forbidding access.", w->client_ip, w->client_port); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "You need an API key for this request."); + return 401; + } + + if(!hostname || !*hostname) { + error("STREAM [receive from [%s]:%s]: request without a hostname. Forbidding access.", w->client_ip, w->client_port); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "You need to send a hostname too."); + return 400; + } + + if(!machine_guid || !*machine_guid) { + error("STREAM [receive from [%s]:%s]: request without a machine GUID. Forbidding access.", w->client_ip, w->client_port); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "You need to send a machine GUID too."); + return 400; + } + + if(regenerate_guid(key, buf) == -1) { + error("STREAM [receive from [%s]:%s]: API key '%s' is not valid GUID. Forbidding access.", w->client_ip, w->client_port, key); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Your API key is invalid."); + return 401; + } + + if(regenerate_guid(machine_guid, buf) == -1) { + error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not GUID. Forbidding access.", w->client_ip, w->client_port, key); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Your machine GUID is invalid."); + return 404; + } + + if(!appconfig_get_boolean(&stream_config, key, "enabled", 1)) { + error("STREAM [receive from [%s]:%s]: API key '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, machine_guid); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Your API key is not permitted access."); + return 401; + } + + if(!appconfig_get_boolean(&stream_config, machine_guid, "enabled", 1)) { + error("STREAM [receive from [%s]:%s]: machine GUID '%s' is not allowed. Forbidding access.", w->client_ip, w->client_port, machine_guid); + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Your machine guide is not permitted access."); + return 404; + } + + struct rrdpush_thread *rpt = mallocz(sizeof(struct rrdpush_thread)); + rpt->fd = w->ifd; + rpt->key = strdupz(key); + rpt->hostname = strdupz(hostname); + rpt->machine_guid = strdupz(machine_guid); + rpt->os = strdupz(os); + rpt->client_ip = strdupz(w->client_ip); + rpt->client_port = strdupz(w->client_port); + rpt->update_every = update_every; + pthread_t thread; + + debug(D_SYSTEM, "STREAM [receive from [%s]:%s]: starting receiving thread.", w->client_ip, w->client_port); + + if(pthread_create(&thread, NULL, rrdpush_receiver_thread, (void *)rpt)) + error("STREAM [receive from [%s]:%s]: failed to create new thread for client.", w->client_ip, w->client_port); + + else if(pthread_detach(thread)) + error("STREAM [receive from [%s]:%s]: cannot request detach newly created thread.", w->client_ip, w->client_port); + + // prevent the caller from closing the streaming socket + if(w->ifd == w->ofd) + w->ifd = w->ofd = -1; + else + w->ifd = -1; + + buffer_flush(w->response.data); + return 200; +} diff --git a/src/rrdpush.h b/src/rrdpush.h new file mode 100644 index 00000000..dddbe758 --- /dev/null +++ b/src/rrdpush.h @@ -0,0 +1,15 @@ +#ifndef NETDATA_RRDPUSH_H +#define NETDATA_RRDPUSH_H + +extern int default_rrdpush_enabled; +extern char *default_rrdpush_destination; +extern char *default_rrdpush_api_key; + +extern int rrdpush_init(); +extern void rrdset_done_push(RRDSET *st); +extern void *rrdpush_sender_thread(void *ptr); + +extern int rrdpush_receiver_thread_spawn(RRDHOST *host, struct web_client *w, char *url); +extern void rrdpush_sender_thread_stop(RRDHOST *host); + +#endif //NETDATA_RRDPUSH_H diff --git a/src/rrdset.c b/src/rrdset.c new file mode 100644 index 00000000..13d6014e --- /dev/null +++ b/src/rrdset.c @@ -0,0 +1,1234 @@ +#define NETDATA_RRD_INTERNALS 1 +#include "common.h" + +#define RRD_DEFAULT_GAP_INTERPOLATIONS 1 + +void rrdset_check_rdlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line) { + debug(D_RRD_CALLS, "Checking read lock on chart '%s'", st->id); + + int ret = pthread_rwlock_trywrlock(&st->rrdset_rwlock); + if(ret == 0) + fatal("RRDSET '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", st->id, function, line, file); +} + +void rrdset_check_wrlock_int(RRDSET *st, const char *file, const char *function, const unsigned long line) { + debug(D_RRD_CALLS, "Checking write lock on chart '%s'", st->id); + + int ret = pthread_rwlock_tryrdlock(&st->rrdset_rwlock); + if(ret == 0) + fatal("RRDSET '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", st->id, function, line, file); +} + + +// ---------------------------------------------------------------------------- +// RRDSET index + +int rrdset_compare(void* a, void* b) { + if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1; + else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1; + else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id); +} + +static RRDSET *rrdset_index_find(RRDHOST *host, const char *id, uint32_t hash) { + RRDSET tmp; + strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX); + tmp.hash = (hash)?hash:simple_hash(tmp.id); + + return (RRDSET *)avl_search_lock(&(host->rrdset_root_index), (avl *) &tmp); +} + +// ---------------------------------------------------------------------------- +// RRDSET name index + +#define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname))) + +int rrdset_compare_name(void* a, void* b) { + RRDSET *A = rrdset_from_avlname(a); + RRDSET *B = rrdset_from_avlname(b); + + // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name); + + if(A->hash_name < B->hash_name) return -1; + else if(A->hash_name > B->hash_name) return 1; + else return strcmp(A->name, B->name); +} + +RRDSET *rrdset_index_add_name(RRDHOST *host, RRDSET *st) { + void *result; + // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name); + result = avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname)); + if(result) return rrdset_from_avlname(result); + return NULL; +} + +RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st) { + void *result; + // fprintf(stderr, "DELETING: %s (name: %s)\n", st->id, st->name); + result = (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index_name), (avl *)(&st->avlname)); + if(result) return rrdset_from_avlname(result); + return NULL; +} + + +// ---------------------------------------------------------------------------- +// RRDSET - find charts + +static inline RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t hash) { + void *result = NULL; + RRDSET tmp; + tmp.name = name; + tmp.hash_name = (hash)?hash:simple_hash(tmp.name); + + // fprintf(stderr, "SEARCHING: %s\n", name); + result = avl_search_lock(&host->rrdset_root_index_name, (avl *) (&(tmp.avlname))); + if(result) { + RRDSET *st = rrdset_from_avlname(result); + if(strcmp(st->magic, RRDSET_MAGIC)) + error("Search for RRDSET %s returned an invalid RRDSET %s (name %s)", name, st->id, st->name); + + // fprintf(stderr, "FOUND: %s\n", name); + return rrdset_from_avlname(result); + } + // fprintf(stderr, "NOT FOUND: %s\n", name); + return NULL; +} + +inline RRDSET *rrdset_find(RRDHOST *host, const char *id) { + debug(D_RRD_CALLS, "rrdset_find() for chart '%s' in host '%s'", id, host->hostname); + RRDSET *st = rrdset_index_find(host, id, 0); + return(st); +} + +inline RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id) { + debug(D_RRD_CALLS, "rrdset_find_bytype() for chart '%s.%s' in host '%s'", type, id, host->hostname); + + char buf[RRD_ID_LENGTH_MAX + 1]; + strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1); + strcat(buf, "."); + int len = (int) strlen(buf); + strncpyz(&buf[len], id, (size_t) (RRD_ID_LENGTH_MAX - len)); + + return(rrdset_find(host, buf)); +} + +inline RRDSET *rrdset_find_byname(RRDHOST *host, const char *name) { + debug(D_RRD_CALLS, "rrdset_find_byname() for chart '%s' in host '%s'", name, host->hostname); + RRDSET *st = rrdset_index_find_name(host, name, 0); + return(st); +} + +// ---------------------------------------------------------------------------- +// RRDSET - rename charts + +char *rrdset_strncpyz_name(char *to, const char *from, size_t length) { + char c, *p = to; + + while (length-- && (c = *from++)) { + if(c != '.' && !isalnum(c)) + c = '_'; + + *p++ = c; + } + + *p = '\0'; + + return to; +} + +void rrdset_set_name(RRDSET *st, const char *name) { + if(unlikely(st->name && !strcmp(st->name, name))) + return; + + debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name); + + char b[CONFIG_MAX_VALUE + 1]; + char n[RRD_ID_LENGTH_MAX + 1]; + + snprintfz(n, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); + rrdset_strncpyz_name(b, n, CONFIG_MAX_VALUE); + + if(st->name) { + rrdset_index_del_name(st->rrdhost, st); + st->name = config_set_default(st->config_section, "name", b); + st->hash_name = simple_hash(st->name); + rrdsetvar_rename_all(st); + } + else { + st->name = config_get(st->config_section, "name", b); + st->hash_name = simple_hash(st->name); + } + + rrdset_wrlock(st); + RRDDIM *rd; + rrddim_foreach_write(rd, st) + rrddimvar_rename_all(rd); + rrdset_unlock(st); + + if(unlikely(rrdset_index_add_name(st->rrdhost, st) != st)) + error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name); +} + + +// ---------------------------------------------------------------------------- +// RRDSET - reset a chart + +void rrdset_reset(RRDSET *st) { + debug(D_RRD_CALLS, "rrdset_reset() %s", st->name); + + st->last_collected_time.tv_sec = 0; + st->last_collected_time.tv_usec = 0; + st->last_updated.tv_sec = 0; + st->last_updated.tv_usec = 0; + st->current_entry = 0; + st->counter = 0; + st->counter_done = 0; + + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + rd->last_collected_time.tv_sec = 0; + rd->last_collected_time.tv_usec = 0; + rd->collections_counter = 0; + memset(rd->values, 0, rd->entries * sizeof(storage_number)); + } +} + +// ---------------------------------------------------------------------------- +// RRDSET - helpers for rrdset_create() + +inline long align_entries_to_pagesize(RRD_MEMORY_MODE mode, long entries) { + if(unlikely(entries < 5)) entries = 5; + if(unlikely(entries > RRD_HISTORY_ENTRIES_MAX)) entries = RRD_HISTORY_ENTRIES_MAX; + + if(unlikely(mode == RRD_MEMORY_MODE_NONE || mode == RRD_MEMORY_MODE_RAM)) + return entries; + + long page = (size_t)sysconf(_SC_PAGESIZE); + long size = sizeof(RRDDIM) + entries * sizeof(storage_number); + if(unlikely(size % page)) { + size -= (size % page); + size += page; + + long n = (size - sizeof(RRDDIM)) / sizeof(storage_number); + return n; + } + + return entries; +} + +static inline void last_collected_time_align(struct timeval *tv, int update_every) { + tv->tv_sec -= tv->tv_sec % update_every; + tv->tv_usec = 500000; +} + +static inline void last_updated_time_align(struct timeval *tv, int update_every) { + tv->tv_sec -= tv->tv_sec % update_every; + tv->tv_usec = 0; +} + +// ---------------------------------------------------------------------------- +// RRDSET - free a chart + +void rrdset_free(RRDSET *st) { + if(unlikely(!st)) return; + + rrdhost_check_wrlock(st->rrdhost); // make sure we have a write lock on the host + rrdset_wrlock(st); // lock this RRDSET + + // ------------------------------------------------------------------------ + // free its children structures + + while(st->variables) rrdsetvar_free(st->variables); + while(st->alarms) rrdsetcalc_unlink(st->alarms); + while(st->dimensions) rrddim_free(st, st->dimensions); + + rrdfamily_free(st->rrdhost, st->rrdfamily); + + // ------------------------------------------------------------------------ + // remove it from the indexes + + if(unlikely(rrdset_index_del(st->rrdhost, st) != st)) + error("RRDSET: INTERNAL ERROR: attempt to remove from index chart '%s', removed a different chart.", st->id); + + rrdset_index_del_name(st->rrdhost, st); + + // ------------------------------------------------------------------------ + // unlink it from the host + + if(st == st->rrdhost->rrdset_root) { + st->rrdhost->rrdset_root = st->next; + } + else { + // find the previous one + RRDSET *s; + for(s = st->rrdhost->rrdset_root; s && s->next != st ; s = s->next) ; + + // bypass it + if(s) s->next = st->next; + else error("Request to free RRDSET '%s': cannot find it under host '%s'", st->id, st->rrdhost->hostname); + } + + rrdset_unlock(st); + + // ------------------------------------------------------------------------ + // free it + + // free directly allocated members + freez(st->config_section); + + if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) { + debug(D_RRD_CALLS, "Unmapping stats '%s'.", st->name); + munmap(st, st->memsize); + } + else + freez(st); +} + +// ---------------------------------------------------------------------------- +// RRDSET - create a chart + +RRDSET *rrdset_create(RRDHOST *host, const char *type, const char *id, const char *name, const char *family + , const char *context, const char *title, const char *units, long priority + , int update_every, RRDSET_TYPE chart_type) { + + if(!type || !type[0]) { + fatal("Cannot create rrd stats without a type."); + return NULL; + } + + if(!id || !id[0]) { + fatal("Cannot create rrd stats without an id."); + return NULL; + } + + // ------------------------------------------------------------------------ + // check if it already exists + + char fullid[RRD_ID_LENGTH_MAX + 1]; + snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); + + RRDSET *st = rrdset_find(host, fullid); + if(st) { + debug(D_RRD_CALLS, "RRDSET '%s', already exists.", fullid); + return st; + } + + char fullfilename[FILENAME_MAX + 1]; + + // ------------------------------------------------------------------------ + // compose the config_section for this chart + + char config_section[RRD_ID_LENGTH_MAX + 1]; + if(host == localhost) + strcpy(config_section, fullid); + else + snprintfz(config_section, RRD_ID_LENGTH_MAX, "%s/%s", host->machine_guid, fullid); + + // ------------------------------------------------------------------------ + // get the options from the config, we need to create it + + long rentries = config_get_number(config_section, "history", host->rrd_history_entries); + long entries = align_entries_to_pagesize(host->rrd_memory_mode, rentries); + if(entries != rentries) entries = config_set_number(config_section, "history", entries); + + if(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE && entries != rentries) + entries = config_set_number(config_section, "history", 10); + + int enabled = config_get_boolean(config_section, "enabled", 1); + if(!enabled) entries = 5; + + unsigned long size = sizeof(RRDSET); + char *cache_dir = rrdset_cache_dir(host, fullid, config_section); + + time_t now = now_realtime_sec(); + + // ------------------------------------------------------------------------ + // load it or allocate it + + debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id); + + snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir); + if(host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || host->rrd_memory_mode == RRD_MEMORY_MODE_MAP) { + st = (RRDSET *) mymmap(fullfilename, size, ((host->rrd_memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 0); + if(st) { + memset(&st->avl, 0, sizeof(avl)); + memset(&st->avlname, 0, sizeof(avl)); + memset(&st->variables_root_index, 0, sizeof(avl_tree_lock)); + memset(&st->dimensions_index, 0, sizeof(avl_tree_lock)); + memset(&st->rrdset_rwlock, 0, sizeof(pthread_rwlock_t)); + + st->name = NULL; + st->type = NULL; + st->family = NULL; + st->context = NULL; + st->title = NULL; + st->units = NULL; + st->dimensions = NULL; + st->next = NULL; + st->variables = NULL; + st->alarms = NULL; + st->flags = 0x00000000; + + if(strcmp(st->magic, RRDSET_MAGIC) != 0) { + errno = 0; + info("Initializing file %s.", fullfilename); + memset(st, 0, size); + } + else if(strcmp(st->id, fullid) != 0) { + errno = 0; + error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid); + // munmap(st, size); + // st = NULL; + memset(st, 0, size); + } + else if(st->memsize != size || st->entries != entries) { + errno = 0; + error("File %s does not have the desired size. Clearing it.", fullfilename); + memset(st, 0, size); + } + else if(st->update_every != update_every) { + errno = 0; + error("File %s does not have the desired update frequency. Clearing it.", fullfilename); + memset(st, 0, size); + } + else if((now - st->last_updated.tv_sec) > update_every * entries) { + errno = 0; + error("File %s is too old. Clearing it.", fullfilename); + memset(st, 0, size); + } + else if(st->last_updated.tv_sec > now + update_every) { + errno = 0; + error("File %s refers to the future. Clearing it.", fullfilename); + memset(st, 0, size); + } + + // make sure the database is aligned + if(st->last_updated.tv_sec) + last_updated_time_align(&st->last_updated, update_every); + + + // make sure we have the right memory mode + // even if we cleared the memory + st->rrd_memory_mode = host->rrd_memory_mode; + } + } + + if(unlikely(!st)) { + st = callocz(1, size); + st->rrd_memory_mode = (host->rrd_memory_mode == RRD_MEMORY_MODE_NONE) ? RRD_MEMORY_MODE_NONE : RRD_MEMORY_MODE_RAM; + } + + st->config_section = strdup(config_section); + st->rrdhost = host; + st->memsize = size; + st->entries = entries; + st->update_every = update_every; + + if(st->current_entry >= st->entries) st->current_entry = 0; + + strcpy(st->cache_filename, fullfilename); + strcpy(st->magic, RRDSET_MAGIC); + + strcpy(st->id, fullid); + st->hash = simple_hash(st->id); + + st->cache_dir = cache_dir; + + st->chart_type = rrdset_type_id(config_get(st->config_section, "chart type", rrdset_type_name(chart_type))); + st->type = config_get(st->config_section, "type", type); + st->family = config_get(st->config_section, "family", family?family:st->type); + st->units = config_get(st->config_section, "units", units?units:""); + + st->context = config_get(st->config_section, "context", context?context:st->id); + st->hash_context = simple_hash(st->context); + + st->priority = config_get_number(st->config_section, "priority", priority); + if(enabled) + rrdset_flag_set(st, RRDSET_FLAG_ENABLED); + else + rrdset_flag_clear(st, RRDSET_FLAG_ENABLED); + + rrdset_flag_clear(st, RRDSET_FLAG_DETAIL); + rrdset_flag_clear(st, RRDSET_FLAG_DEBUG); + + // if(!strcmp(st->id, "disk_util.dm-0")) { + // st->debug = 1; + // error("enabled debugging for '%s'", st->id); + // } + // else error("not enabled debugging for '%s'", st->id); + + st->green = NAN; + st->red = NAN; + + st->last_collected_time.tv_sec = 0; + st->last_collected_time.tv_usec = 0; + st->counter_done = 0; + + st->gap_when_lost_iterations_above = (int) ( + config_get_number(st->config_section, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2); + + avl_init_lock(&st->dimensions_index, rrddim_compare); + avl_init_lock(&st->variables_root_index, rrdvar_compare); + + pthread_rwlock_init(&st->rrdset_rwlock, NULL); + rrdhost_wrlock(host); + + if(name && *name) rrdset_set_name(st, name); + else rrdset_set_name(st, id); + + { + char varvalue[CONFIG_MAX_VALUE + 1]; + char varvalue2[CONFIG_MAX_VALUE + 1]; + snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name); + json_escape_string(varvalue2, varvalue, sizeof(varvalue2)); + st->title = config_get(st->config_section, "title", varvalue2); + } + + st->rrdfamily = rrdfamily_create(host, st->family); + + st->next = host->rrdset_root; + host->rrdset_root = st; + + if(host->health_enabled) { + rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, 0); + rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, 0); + rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, 0); + rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, 0); + rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, 0); + } + + if(unlikely(rrdset_index_add(host, st) != st)) + error("RRDSET: INTERNAL ERROR: attempt to index duplicate chart '%s'", st->id); + + rrdsetcalc_link_matching(st); + rrdcalctemplate_link_matching(st); + + rrdhost_unlock(host); + + return(st); +} + + +// ---------------------------------------------------------------------------- +// RRDSET - data collection iteration control + +inline void rrdset_next_usec_unfiltered(RRDSET *st, usec_t microseconds) { + + if(unlikely(!st->last_collected_time.tv_sec)) { + // the first entry + microseconds = st->update_every * USEC_PER_SEC; + } + else if(unlikely(!microseconds)) { + // no dt given by the plugin + struct timeval now; + now_realtime_timeval(&now); + microseconds = dt_usec(&now, &st->last_collected_time); + } + + st->usec_since_last_update = microseconds; +} + +inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) { + struct timeval now; + now_realtime_timeval(&now); + + if(unlikely(!st->last_collected_time.tv_sec)) { + // the first entry + microseconds = st->update_every * USEC_PER_SEC; + } + else if(unlikely(!microseconds)) { + // no dt given by the plugin + microseconds = dt_usec(&now, &st->last_collected_time); + } + else { + // microseconds has the time since the last collection +//#ifdef NETDATA_INTERNAL_CHECKS +// usec_t now_usec = timeval_usec(&now); +// usec_t last_usec = timeval_usec(&st->last_collected_time); +//#endif + susec_t since_last_usec = dt_usec_signed(&now, &st->last_collected_time); + + if(unlikely(since_last_usec < 0)) { + // oops! the database is in the future + error("Database for chart '%s' on host '%s' is %lld microseconds in the future. Adjusting it to current time.", st->id, st->rrdhost->hostname, -since_last_usec); + + st->last_collected_time.tv_sec = now.tv_sec - st->update_every; + st->last_collected_time.tv_usec = now.tv_usec; + last_collected_time_align(&st->last_collected_time, st->update_every); + + st->last_updated.tv_sec = now.tv_sec - st->update_every; + st->last_updated.tv_usec = now.tv_usec; + last_updated_time_align(&st->last_updated, st->update_every); + + microseconds = st->update_every * USEC_PER_SEC; + since_last_usec = st->update_every * USEC_PER_SEC; + } + + // verify the microseconds given is good + if(unlikely(microseconds > (usec_t)since_last_usec)) { + debug(D_RRD_CALLS, "dt %llu usec given is too big - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, microseconds - (usec_t)since_last_usec, st->name, st->id); + +//#ifdef NETDATA_INTERNAL_CHECKS +// if(unlikely(last_usec + microseconds > now_usec + 1000)) +// error("dt %llu usec given is too big - it leads %llu usec to the future, for chart '%s' (%s).", microseconds, microseconds - (usec_t)since_last_usec, st->name, st->id); +//#endif + + microseconds = (usec_t)since_last_usec; + } + else if(unlikely(microseconds < (usec_t)since_last_usec * 0.8)) { + debug(D_RRD_CALLS, "dt %llu usec given is too small - expected %llu usec up to -20%%, for chart '%s' (%s).", microseconds, (usec_t)since_last_usec, st->name, st->id); + +//#ifdef NETDATA_INTERNAL_CHECKS +// error("dt %llu usec given is too small - expected %llu usec up to -20%%, for chart '%s' (%s).", microseconds, (usec_t)since_last_usec, st->name, st->id); +//#endif + microseconds = (usec_t)since_last_usec; + } + } + debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds); + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds); + + st->usec_since_last_update = microseconds; +} + + +// ---------------------------------------------------------------------------- +// RRDSET - process the collected values for all dimensions of a chart + +static inline void rrdset_init_last_collected_time(RRDSET *st) { + now_realtime_timeval(&st->last_collected_time); + last_collected_time_align(&st->last_collected_time, st->update_every); +} + +static inline usec_t rrdset_update_last_collected_time(RRDSET *st) { + usec_t last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec; + usec_t ut = last_collect_ut + st->usec_since_last_update; + st->last_collected_time.tv_sec = (time_t) (ut / USEC_PER_SEC); + st->last_collected_time.tv_usec = (suseconds_t) (ut % USEC_PER_SEC); + return last_collect_ut; +} + +static inline void rrdset_init_last_updated_time(RRDSET *st) { + // copy the last collected time to last updated time + st->last_updated.tv_sec = st->last_collected_time.tv_sec; + st->last_updated.tv_usec = st->last_collected_time.tv_usec; + last_updated_time_align(&st->last_updated, st->update_every); +} + +static inline void rrdset_done_push_exclusive(RRDSET *st) { + if(unlikely(!st->last_collected_time.tv_sec)) { + // it is the first entry + // set the last_collected_time to now + rrdset_init_last_collected_time(st); + } + else { + // it is not the first entry + // calculate the proper last_collected_time, using usec_since_last_update + rrdset_update_last_collected_time(st); + } + + st->counter_done++; + + rrdset_rdlock(st); + rrdset_done_push(st); + rrdset_unlock(st); +} + +void rrdset_done(RRDSET *st) { + if(unlikely(netdata_exit)) return; + + if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) { + if(unlikely(st->rrdhost->rrdpush_enabled)) + rrdset_done_push_exclusive(st); + + return; + } + + debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name); + + RRDDIM *rd; + + int + pthreadoldcancelstate; // store the old cancelable pthread state, to restore it at the end + + char + store_this_entry = 1, // boolean: 1 = store this entry, 0 = don't store this entry + first_entry = 0; // boolean: 1 = this is the first entry seen for this chart, 0 = all other entries + + unsigned int + stored_entries = 0; // the number of entries we have stored in the db, during this call to rrdset_done() + + usec_t + last_collect_ut, // the timestamp in microseconds, of the last collected value + now_collect_ut, // the timestamp in microseconds, of this collected value (this is NOW) + last_stored_ut, // the timestamp in microseconds, of the last stored entry in the db + next_store_ut, // the timestamp in microseconds, of the next entry to store in the db + update_every_ut = st->update_every * USEC_PER_SEC; // st->update_every in microseconds + + if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0)) + error("Cannot set pthread cancel state to DISABLE."); + + // a read lock is OK here + rrdset_rdlock(st); + +/* + // enable the chart, if it was disabled + if(unlikely(rrd_delete_unupdated_dimensions) && !st->enabled) + st->enabled = 1; +*/ + + // check if the chart has a long time to be updated + if(unlikely(st->usec_since_last_update > st->entries * update_every_ut)) { + info("%s: took too long to be updated (%0.3Lf secs). Resetting it.", st->name, (long double)(st->usec_since_last_update / 1000000.0)); + rrdset_reset(st); + st->usec_since_last_update = update_every_ut; + first_entry = 1; + } + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: microseconds since last update: %llu", st->name, st->usec_since_last_update); + + // set last_collected_time + if(unlikely(!st->last_collected_time.tv_sec)) { + // it is the first entry + // set the last_collected_time to now + rrdset_init_last_collected_time(st); + + last_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec - update_every_ut; + + // the first entry should not be stored + store_this_entry = 0; + first_entry = 1; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: has not set last_collected_time. Setting it now. Will not store the next entry.", st->name); + } + else { + // it is not the first entry + // calculate the proper last_collected_time, using usec_since_last_update + last_collect_ut = rrdset_update_last_collected_time(st); + } + + // if this set has not been updated in the past + // we fake the last_update time to be = now - usec_since_last_update + if(unlikely(!st->last_updated.tv_sec)) { + // it has never been updated before + // set a fake last_updated, in the past using usec_since_last_update + rrdset_init_last_updated_time(st); + + // the first entry should not be stored + store_this_entry = 0; + first_entry = 1; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: initializing last_updated to last_collected_time - %llu microseconds. Will not store the next entry.", st->name, st->usec_since_last_update); + } + + // check if we will re-write the entire data set + if(unlikely(dt_usec(&st->last_collected_time, &st->last_updated) > st->entries * update_every_ut)) { + info("%s: too old data (last updated at %ld.%ld, last collected at %ld.%ld). Resetting it. Will not store the next entry.", st->name, st->last_updated.tv_sec, st->last_updated.tv_usec, st->last_collected_time.tv_sec, st->last_collected_time.tv_usec); + rrdset_reset(st); + rrdset_init_last_updated_time(st); + + st->usec_since_last_update = update_every_ut; + + // the first entry should not be stored + store_this_entry = 0; + first_entry = 1; + } + + // these are the 3 variables that will help us in interpolation + // last_stored_ut = the last time we added a value to the storage + // now_collect_ut = the time the current value has been collected + // next_store_ut = the time of the next interpolation point + last_stored_ut = st->last_updated.tv_sec * USEC_PER_SEC + st->last_updated.tv_usec; + now_collect_ut = st->last_collected_time.tv_sec * USEC_PER_SEC + st->last_collected_time.tv_usec; + next_store_ut = (st->last_updated.tv_sec + st->update_every) * USEC_PER_SEC; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) { + debug(D_RRD_STATS, "%s: last_collect_ut = %0.3Lf (last collection time)", st->name, (long double)last_collect_ut/1000000.0); + debug(D_RRD_STATS, "%s: now_collect_ut = %0.3Lf (current collection time)", st->name, (long double)now_collect_ut/1000000.0); + debug(D_RRD_STATS, "%s: last_stored_ut = %0.3Lf (last updated time)", st->name, (long double)last_stored_ut/1000000.0); + debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0); + } + + if(unlikely(!st->counter_done)) { + store_this_entry = 0; + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: Will not store the next entry.", st->name); + } + st->counter_done++; + + if(unlikely(st->rrdhost->rrdpush_enabled)) + rrdset_done_push(st); + + // calculate totals and count the dimensions + int dimensions = 0; + st->collected_total = 0; + rrddim_foreach_read(rd, st) { + dimensions++; + if(likely(rd->updated)) + st->collected_total += rd->collected_value; + } + + uint32_t storage_flags = SN_EXISTS; + + // process all dimensions to calculate their values + // based on the collected figures only + // at this stage we do not interpolate anything + rrddim_foreach_read(rd, st) { + + if(unlikely(!rd->updated)) { + rd->calculated_value = 0; + continue; + } + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: START " + " last_collected_value = " COLLECTED_NUMBER_FORMAT + " collected_value = " COLLECTED_NUMBER_FORMAT + " last_calculated_value = " CALCULATED_NUMBER_FORMAT + " calculated_value = " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->last_collected_value + , rd->collected_value + , rd->last_calculated_value + , rd->calculated_value + ); + + switch(rd->algorithm) { + case RRD_ALGORITHM_ABSOLUTE: + rd->calculated_value = (calculated_number)rd->collected_value + * (calculated_number)rd->multiplier + / (calculated_number)rd->divisor; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN " + CALCULATED_NUMBER_FORMAT " = " + COLLECTED_NUMBER_FORMAT + " * " CALCULATED_NUMBER_FORMAT + " / " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->calculated_value + , rd->collected_value + , (calculated_number)rd->multiplier + , (calculated_number)rd->divisor + ); + break; + + case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL: + if(unlikely(!st->collected_total)) + rd->calculated_value = 0; + else + // the percentage of the current value + // over the total of all dimensions + rd->calculated_value = + (calculated_number)100 + * (calculated_number)rd->collected_value + / (calculated_number)st->collected_total; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC PCENT-ROW " + CALCULATED_NUMBER_FORMAT " = 100" + " * " COLLECTED_NUMBER_FORMAT + " / " COLLECTED_NUMBER_FORMAT + , st->id, rd->name + , rd->calculated_value + , rd->collected_value + , st->collected_total + ); + break; + + case RRD_ALGORITHM_INCREMENTAL: + if(unlikely(rd->collections_counter <= 1)) { + rd->calculated_value = 0; + continue; + } + + // if the new is smaller than the old (an overflow, or reset), set the old equal to the new + // to reset the calculation (it will give zero as the calculation for this second) + if(unlikely(rd->last_collected_value > rd->collected_value)) { + debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT + , st->name, rd->name + , rd->last_collected_value + , rd->collected_value); + + if(!(rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS))) + storage_flags = SN_EXISTS_RESET; + + rd->last_collected_value = rd->collected_value; + } + + rd->calculated_value += + (calculated_number)(rd->collected_value - rd->last_collected_value) + * (calculated_number)rd->multiplier + / (calculated_number)rd->divisor; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC INC PRE " + CALCULATED_NUMBER_FORMAT " = (" + COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT + ")" + " * " CALCULATED_NUMBER_FORMAT + " / " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->calculated_value + , rd->collected_value, rd->last_collected_value + , (calculated_number)rd->multiplier + , (calculated_number)rd->divisor + ); + break; + + case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL: + if(unlikely(rd->collections_counter <= 1)) { + rd->calculated_value = 0; + continue; + } + + // if the new is smaller than the old (an overflow, or reset), set the old equal to the new + // to reset the calculation (it will give zero as the calculation for this second) + if(unlikely(rd->last_collected_value > rd->collected_value)) { + debug(D_RRD_STATS, "%s.%s: RESET or OVERFLOW. Last collected value = " COLLECTED_NUMBER_FORMAT ", current = " COLLECTED_NUMBER_FORMAT + , st->name, rd->name + , rd->last_collected_value + , rd->collected_value); + + if(!(rrddim_flag_check(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS))) + storage_flags = SN_EXISTS_RESET; + + rd->last_collected_value = rd->collected_value; + } + + // the percentage of the current increment + // over the increment of all dimensions together + if(unlikely(st->collected_total == st->last_collected_total)) + rd->calculated_value = 0; + else + rd->calculated_value = + (calculated_number)100 + * (calculated_number)(rd->collected_value - rd->last_collected_value) + / (calculated_number)(st->collected_total - st->last_collected_total); + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF " + CALCULATED_NUMBER_FORMAT " = 100" + " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" + " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")" + , st->id, rd->name + , rd->calculated_value + , rd->collected_value, rd->last_collected_value + , st->collected_total, st->last_collected_total + ); + break; + + default: + // make the default zero, to make sure + // it gets noticed when we add new types + rd->calculated_value = 0; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC " + CALCULATED_NUMBER_FORMAT " = 0" + , st->id, rd->name + , rd->calculated_value + ); + break; + } + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: PHASE2 " + " last_collected_value = " COLLECTED_NUMBER_FORMAT + " collected_value = " COLLECTED_NUMBER_FORMAT + " last_calculated_value = " CALCULATED_NUMBER_FORMAT + " calculated_value = " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->last_collected_value + , rd->collected_value + , rd->last_calculated_value + , rd->calculated_value + ); + + } + + // at this point we have all the calculated values ready + // it is now time to interpolate values on a second boundary + + if(unlikely(now_collect_ut < next_store_ut)) { + // this is collected in the same interpolation point + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: THIS IS IN THE SAME INTERPOLATION POINT", st->name); + +//#ifdef NETDATA_INTERNAL_CHECKS +// info("%s is collected in the same interpolation point: short by %llu microseconds", st->name, next_store_ut - now_collect_ut); +//#endif + } + + usec_t first_ut = last_stored_ut; + long long iterations = (now_collect_ut - last_stored_ut) / (update_every_ut); + if((now_collect_ut % (update_every_ut)) == 0) iterations++; + + for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) { +//#ifdef NETDATA_INTERNAL_CHECKS +// if(iterations < 0) { error("%s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", st->name, first_ut, last_stored_ut, next_store_ut, now_collect_ut); } +//#endif + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) { + debug(D_RRD_STATS, "%s: last_stored_ut = %0.3Lf (last updated time)", st->name, (long double)last_stored_ut/1000000.0); + debug(D_RRD_STATS, "%s: next_store_ut = %0.3Lf (next interpolation point)", st->name, (long double)next_store_ut/1000000.0); + } + + st->last_updated.tv_sec = (time_t) (next_store_ut / USEC_PER_SEC); + st->last_updated.tv_usec = 0; + + rrddim_foreach_read(rd, st) { + calculated_number new_value; + + switch(rd->algorithm) { + case RRD_ALGORITHM_INCREMENTAL: + new_value = (calculated_number) + ( rd->calculated_value + * (calculated_number)(next_store_ut - last_collect_ut) + / (calculated_number)(now_collect_ut - last_collect_ut) + ); + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC2 INC " + CALCULATED_NUMBER_FORMAT " = " + CALCULATED_NUMBER_FORMAT + " * %llu" + " / %llu" + , st->id, rd->name + , new_value + , rd->calculated_value + , (next_store_ut - last_stored_ut) + , (now_collect_ut - last_stored_ut) + ); + + rd->calculated_value -= new_value; + new_value += rd->last_calculated_value; + rd->last_calculated_value = 0; + new_value /= (calculated_number)st->update_every; + + if(unlikely(next_store_ut - last_stored_ut < update_every_ut)) { + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: COLLECTION POINT IS SHORT " CALCULATED_NUMBER_FORMAT " - EXTRAPOLATING", + st->id, rd->name + , (calculated_number)(next_store_ut - last_stored_ut) + ); + new_value = new_value * (calculated_number)(st->update_every * 1000000) / (calculated_number)(next_store_ut - last_stored_ut); + } + break; + + case RRD_ALGORITHM_ABSOLUTE: + case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL: + case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL: + default: + if(iterations == 1) { + // this is the last iteration + // do not interpolate + // just show the calculated value + + new_value = rd->calculated_value; + } + else { + // we have missed an update + // interpolate in the middle values + + new_value = (calculated_number) + ( ( (rd->calculated_value - rd->last_calculated_value) + * (calculated_number)(next_store_ut - last_collect_ut) + / (calculated_number)(now_collect_ut - last_collect_ut) + ) + + rd->last_calculated_value + ); + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: CALC2 DEF " + CALCULATED_NUMBER_FORMAT " = (((" + "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")" + " * %llu" + " / %llu) + " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , new_value + , rd->calculated_value, rd->last_calculated_value + , (next_store_ut - first_ut) + , (now_collect_ut - first_ut), rd->last_calculated_value + ); + } + break; + } + + if(unlikely(!store_this_entry)) { + rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); + continue; + } + + if(likely(rd->updated && rd->collections_counter > 1 && iterations < st->gap_when_lost_iterations_above)) { + rd->values[st->current_entry] = pack_storage_number(new_value, storage_flags ); + rd->last_stored_value = new_value; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: STORE[%ld] " + CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , st->current_entry + , unpack_storage_number(rd->values[st->current_entry]), new_value + ); + } + else { + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: STORE[%ld] = NON EXISTING " + , st->id, rd->name + , st->current_entry + ); + rd->values[st->current_entry] = pack_storage_number(0, SN_NOT_EXISTS); + rd->last_stored_value = NAN; + } + + stored_entries++; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) { + calculated_number t1 = new_value * (calculated_number)rd->multiplier / (calculated_number)rd->divisor; + calculated_number t2 = unpack_storage_number(rd->values[st->current_entry]); + calculated_number accuracy = accuracy_loss(t1, t2); + debug(D_RRD_STATS, "%s/%s: UNPACK[%ld] = " CALCULATED_NUMBER_FORMAT " FLAGS=0x%08x (original = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s)" + , st->id, rd->name + , st->current_entry + , t2 + , get_storage_number_flags(rd->values[st->current_entry]) + , t1 + , accuracy + , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : "" + ); + + rd->collected_volume += t1; + rd->stored_volume += t2; + accuracy = accuracy_loss(rd->collected_volume, rd->stored_volume); + debug(D_RRD_STATS, "%s/%s: VOLUME[%ld] = " CALCULATED_NUMBER_FORMAT ", calculated = " CALCULATED_NUMBER_FORMAT ", accuracy loss = " CALCULATED_NUMBER_FORMAT "%%%s" + , st->id, rd->name + , st->current_entry + , rd->stored_volume + , rd->collected_volume + , accuracy + , (accuracy > ACCURACY_LOSS) ? " **TOO BIG** " : "" + ); + + } + } + // reset the storage flags for the next point, if any; + storage_flags = SN_EXISTS; + + st->counter++; + st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1; + last_stored_ut = next_store_ut; + } + + st->last_collected_total = st->collected_total; + + rrddim_foreach_read(rd, st) { + if(unlikely(!rd->updated)) + continue; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: setting last_collected_value (old: " COLLECTED_NUMBER_FORMAT ") to last_collected_value (new: " COLLECTED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_collected_value, rd->collected_value); + + rd->last_collected_value = rd->collected_value; + + switch(rd->algorithm) { + case RRD_ALGORITHM_INCREMENTAL: + if(unlikely(!first_entry)) { + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value + rd->calculated_value, rd->calculated_value); + rd->last_calculated_value += rd->calculated_value; + } + else { + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s: THIS IS THE FIRST POINT", st->name); + } + break; + + case RRD_ALGORITHM_ABSOLUTE: + case RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL: + case RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL: + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: setting last_calculated_value (old: " CALCULATED_NUMBER_FORMAT ") to last_calculated_value (new: " CALCULATED_NUMBER_FORMAT ")", st->id, rd->name, rd->last_calculated_value, rd->calculated_value); + rd->last_calculated_value = rd->calculated_value; + break; + } + + rd->calculated_value = 0; + rd->collected_value = 0; + rd->updated = 0; + + if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG))) + debug(D_RRD_STATS, "%s/%s: END " + " last_collected_value = " COLLECTED_NUMBER_FORMAT + " collected_value = " COLLECTED_NUMBER_FORMAT + " last_calculated_value = " CALCULATED_NUMBER_FORMAT + " calculated_value = " CALCULATED_NUMBER_FORMAT + , st->id, rd->name + , rd->last_collected_value + , rd->collected_value + , rd->last_calculated_value + , rd->calculated_value + ); + } + + // ALL DONE ABOUT THE DATA UPDATE + // -------------------------------------------------------------------- + +/* + // find if there are any obsolete dimensions (not updated recently) + if(unlikely(rrd_delete_unupdated_dimensions)) { + + for( rd = st->dimensions; likely(rd) ; rd = rd->next ) + if((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec) + break; + + if(unlikely(rd)) { + RRDDIM *last; + // there is dimension to free + // upgrade our read lock to a write lock + pthread_rwlock_unlock(&st->rrdset_rwlock); + pthread_rwlock_wrlock(&st->rrdset_rwlock); + + for( rd = st->dimensions, last = NULL ; likely(rd) ; ) { + // remove it only it is not updated in rrd_delete_unupdated_dimensions seconds + + if(unlikely((rd->last_collected_time.tv_sec + (rrd_delete_unupdated_dimensions * st->update_every)) < st->last_collected_time.tv_sec)) { + info("Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id); + + if(unlikely(!last)) { + st->dimensions = rd->next; + rd->next = NULL; + rrddim_free(st, rd); + rd = st->dimensions; + continue; + } + else { + last->next = rd->next; + rd->next = NULL; + rrddim_free(st, rd); + rd = last->next; + continue; + } + } + + last = rd; + rd = rd->next; + } + + if(unlikely(!st->dimensions)) { + info("Disabling chart %s (%s) since it does not have any dimensions", st->name, st->id); + st->enabled = 0; + } + } + } +*/ + + rrdset_unlock(st); + + if(unlikely(pthread_setcancelstate(pthreadoldcancelstate, NULL) != 0)) + error("Cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate); +} diff --git a/src/rrdsetvar.c b/src/rrdsetvar.c new file mode 100644 index 00000000..03d7aece --- /dev/null +++ b/src/rrdsetvar.c @@ -0,0 +1,120 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDSETVAR management +// CHART VARIABLES + +static inline void rrdsetvar_free_variables(RRDSETVAR *rs) { + RRDSET *st = rs->rrdset; + + // CHART + + rrdvar_free(st->rrdhost, &st->variables_root_index, rs->var_local); + rs->var_local = NULL; + + // FAMILY + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family); + rs->var_family = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host); + rs->var_host = NULL; + + // HOST + + rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->var_family_name); + rs->var_family_name = NULL; + + rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->var_host_name); + rs->var_host_name = NULL; + + // KEYS + + freez(rs->key_fullid); + rs->key_fullid = NULL; + + freez(rs->key_fullname); + rs->key_fullname = NULL; +} + +static inline void rrdsetvar_create_variables(RRDSETVAR *rs) { + rrdsetvar_free_variables(rs); + + RRDSET *st = rs->rrdset; + + // KEYS + + char buffer[RRDVAR_MAX_LENGTH + 1]; + snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rs->variable); + rs->key_fullid = strdupz(buffer); + + snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable); + rs->key_fullname = strdupz(buffer); + + // CHART + + rs->var_local = rrdvar_create_and_index("local", &st->variables_root_index, rs->variable, rs->type, rs->value); + + // FAMILY + + rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullid, rs->type, rs->value); + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->variables_root_index, rs->key_fullname, rs->type, rs->value); + + // HOST + + rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullid, rs->type, rs->value); + rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->key_fullname, rs->type, rs->value); + +} + +RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) { + debug(D_VARIABLES, "RRDVARSET create for chart id '%s' name '%s' with variable name '%s'", st->id, st->name, variable); + RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR)); + + rs->variable = strdupz(variable); + rs->type = type; + rs->value = value; + rs->options = options; + rs->rrdset = st; + + rs->next = st->variables; + st->variables = rs; + + rrdsetvar_create_variables(rs); + + return rs; +} + +void rrdsetvar_rename_all(RRDSET *st) { + debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name); + + RRDSETVAR *rs, *next = st->variables; + while((rs = next)) { + next = rs->next; + rrdsetvar_create_variables(rs); + } + + rrdsetcalc_link_matching(st); +} + +void rrdsetvar_free(RRDSETVAR *rs) { + RRDSET *st = rs->rrdset; + debug(D_VARIABLES, "RRDSETVAR free for chart id '%s' name '%s', variable '%s'", st->id, st->name, rs->variable); + + if(st->variables == rs) { + st->variables = rs->next; + } + else { + RRDSETVAR *t; + for (t = st->variables; t && t->next != rs; t = t->next); + if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->key_fullname, st->id); + else t->next = rs->next; + } + + rrdsetvar_free_variables(rs); + + freez(rs->variable); + freez(rs); +} + diff --git a/src/rrdvar.c b/src/rrdvar.c new file mode 100644 index 00000000..2223d7c9 --- /dev/null +++ b/src/rrdvar.c @@ -0,0 +1,265 @@ +#define NETDATA_HEALTH_INTERNALS +#include "common.h" + +// ---------------------------------------------------------------------------- +// RRDVAR management + +inline int rrdvar_fix_name(char *variable) { + int fixed = 0; + while(*variable) { + if (!isalnum(*variable) && *variable != '.' && *variable != '_') { + *variable++ = '_'; + fixed++; + } + else + variable++; + } + + return fixed; +} + +int rrdvar_compare(void* a, void* b) { + if(((RRDVAR *)a)->hash < ((RRDVAR *)b)->hash) return -1; + else if(((RRDVAR *)a)->hash > ((RRDVAR *)b)->hash) return 1; + else return strcmp(((RRDVAR *)a)->name, ((RRDVAR *)b)->name); +} + +static inline RRDVAR *rrdvar_index_add(avl_tree_lock *tree, RRDVAR *rv) { + RRDVAR *ret = (RRDVAR *)avl_insert_lock(tree, (avl *)(rv)); + if(ret != rv) + debug(D_VARIABLES, "Request to insert RRDVAR '%s' into index failed. Already exists.", rv->name); + + return ret; +} + +static inline RRDVAR *rrdvar_index_del(avl_tree_lock *tree, RRDVAR *rv) { + RRDVAR *ret = (RRDVAR *)avl_remove_lock(tree, (avl *)(rv)); + if(!ret) + error("Request to remove RRDVAR '%s' from index failed. Not Found.", rv->name); + + return ret; +} + +static inline RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) { + RRDVAR tmp; + tmp.name = (char *)name; + tmp.hash = (hash)?hash:simple_hash(tmp.name); + + return (RRDVAR *)avl_search_lock(tree, (avl *)&tmp); +} + +inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) { + (void)host; + + if(!rv) return; + + if(tree) { + debug(D_VARIABLES, "Deleting variable '%s'", rv->name); + if(unlikely(!rrdvar_index_del(tree, rv))) + error("Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname); + } + + freez(rv->name); + freez(rv); +} + +inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, int type, void *value) { + char *variable = strdupz(name); + rrdvar_fix_name(variable); + uint32_t hash = simple_hash(variable); + + RRDVAR *rv = rrdvar_index_find(tree, variable, hash); + if(unlikely(!rv)) { + debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", variable, scope); + + rv = callocz(1, sizeof(RRDVAR)); + rv->name = variable; + rv->hash = hash; + rv->type = type; + rv->value = value; + + RRDVAR *ret = rrdvar_index_add(tree, rv); + if(unlikely(ret != rv)) { + debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", variable, scope); + rrdvar_free(NULL, NULL, rv); + rv = NULL; + } + else + debug(D_VARIABLES, "Variable '%s' created in scope '%s'", variable, scope); + } + else { + debug(D_VARIABLES, "Variable '%s' is already found in scope '%s'.", variable, scope); + + // already exists + freez(variable); + + // this is important + // it must return NULL - not the existing variable - or double-free will happen + rv = NULL; + } + + return rv; +} + +// ---------------------------------------------------------------------------- +// CUSTOM VARIABLES + +RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) { + calculated_number *v = callocz(1, sizeof(calculated_number)); + *v = NAN; + RRDVAR *rv = rrdvar_create_and_index("host", &host->variables_root_index, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v); + if(unlikely(!rv)) { + free(v); + error("Requested variable '%s' already exists - possibly 2 plugins will be updating it at the same time", name); + + char *variable = strdupz(name); + rrdvar_fix_name(variable); + uint32_t hash = simple_hash(variable); + + rv = rrdvar_index_find(&host->variables_root_index, variable, hash); + } + + return rv; +} + +void rrdvar_custom_host_variable_destroy(RRDHOST *host, const char *name) { + char *variable = strdupz(name); + rrdvar_fix_name(variable); + uint32_t hash = simple_hash(variable); + + RRDVAR *rv = rrdvar_index_find(&host->variables_root_index, variable, hash); + freez(variable); + + if(!rv) { + error("Attempted to remove variable '%s' from host '%s', but it does not exist.", name, host->hostname); + return; + } + + if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) { + error("Attempted to remove variable '%s' from host '%s', but it does not a custom allocated variable.", name, host->hostname); + return; + } + + if(!rrdvar_index_del(&host->variables_root_index, rv)) { + error("Attempted to remove variable '%s' from host '%s', but it cannot be found.", name, host->hostname); + return; + } + + freez(rv->name); + freez(rv->value); + freez(rv); +} + +void rrdvar_custom_host_variable_set(RRDVAR *rv, calculated_number value) { + if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED) + error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value); + else { + calculated_number *v = rv->value; + *v = value; + } +} + +// ---------------------------------------------------------------------------- +// RRDVAR lookup + +static calculated_number rrdvar2number(RRDVAR *rv) { + switch(rv->type) { + case RRDVAR_TYPE_CALCULATED_ALLOCATED: + case RRDVAR_TYPE_CALCULATED: { + calculated_number *n = (calculated_number *)rv->value; + return *n; + } + + case RRDVAR_TYPE_TIME_T: { + time_t *n = (time_t *)rv->value; + return *n; + } + + case RRDVAR_TYPE_COLLECTED: { + collected_number *n = (collected_number *)rv->value; + return *n; + } + + case RRDVAR_TYPE_TOTAL: { + total_number *n = (total_number *)rv->value; + return *n; + } + + case RRDVAR_TYPE_INT: { + int *n = (int *)rv->value; + return *n; + } + + default: + error("I don't know how to convert RRDVAR type %d to calculated_number", rv->type); + return NAN; + } +} + +int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result) { + RRDSET *st = rc->rrdset; + RRDVAR *rv; + + if(!st) return 0; + + rv = rrdvar_index_find(&st->variables_root_index, variable, hash); + if(rv) { + *result = rrdvar2number(rv); + return 1; + } + + rv = rrdvar_index_find(&st->rrdfamily->variables_root_index, variable, hash); + if(rv) { + *result = rrdvar2number(rv); + return 1; + } + + rv = rrdvar_index_find(&st->rrdhost->variables_root_index, variable, hash); + if(rv) { + *result = rrdvar2number(rv); + return 1; + } + + return 0; +} + +// ---------------------------------------------------------------------------- +// RRDVAR to JSON + +struct variable2json_helper { + BUFFER *buf; + size_t counter; +}; + +static int single_variable2json(void *entry, void *data) { + struct variable2json_helper *helper = (struct variable2json_helper *)data; + RRDVAR *rv = (RRDVAR *)entry; + calculated_number value = rrdvar2number(rv); + + if(unlikely(isnan(value) || isinf(value))) + buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": null", helper->counter?",":"", rv->name); + else + buffer_sprintf(helper->buf, "%s\n\t\t\"%s\": %0.5Lf", helper->counter?",":"", rv->name, (long double)value); + + helper->counter++; + + return 0; +} + +void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf) { + struct variable2json_helper helper = { + .buf = buf, + .counter = 0 + }; + + buffer_sprintf(buf, "{\n\t\"chart\": \"%s\",\n\t\"chart_name\": \"%s\",\n\t\"chart_context\": \"%s\",\n\t\"chart_variables\": {", st->id, st->name, st->context); + avl_traverse_lock(&st->variables_root_index, single_variable2json, (void *)&helper); + buffer_sprintf(buf, "\n\t},\n\t\"family\": \"%s\",\n\t\"family_variables\": {", st->family); + helper.counter = 0; + avl_traverse_lock(&st->rrdfamily->variables_root_index, single_variable2json, (void *)&helper); + buffer_sprintf(buf, "\n\t},\n\t\"host\": \"%s\",\n\t\"host_variables\": {", st->rrdhost->hostname); + helper.counter = 0; + avl_traverse_lock(&st->rrdhost->variables_root_index, single_variable2json, (void *)&helper); + buffer_strcat(buf, "\n\t}\n}\n"); +} + diff --git a/src/simple_pattern.c b/src/simple_pattern.c index 7e442429..f72a42d0 100644 --- a/src/simple_pattern.c +++ b/src/simple_pattern.c @@ -169,7 +169,7 @@ static inline int match_pattern(struct simple_pattern *m, const char *str, size_ int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str) { struct simple_pattern *m, *root = (struct simple_pattern *)list; - if(unlikely(!root)) return 0; + if(unlikely(!root || !str || !*str)) return 0; size_t len = strlen(str); for(m = root; m ; m = m->next) @@ -184,8 +184,8 @@ int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str) { static inline void free_pattern(struct simple_pattern *m) { if(!m) return; - if(m->next) free_pattern(m->next); - if(m->child) free_pattern(m->child); + free_pattern(m->child); + free_pattern(m->next); freez((void *)m->match); freez(m); } @@ -193,5 +193,5 @@ static inline void free_pattern(struct simple_pattern *m) { void simple_pattern_free(SIMPLE_PATTERN *list) { if(!list) return; - free_pattern(((struct simple_pattern *)list)->next); + free_pattern(((struct simple_pattern *)list)); } diff --git a/src/socket.c b/src/socket.c index 643811e4..400c1ef4 100644 --- a/src/socket.c +++ b/src/socket.c @@ -160,8 +160,10 @@ int connect_to(const char *definition, int default_port, struct timeval *timeout fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if(fd != -1) { - if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)timeout, sizeof(struct timeval)) < 0) - error("Failed to set timeout on the socket to ip '%s' port '%s'", hostBfr, servBfr); + if(timeout) { + if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0) + error("Failed to set timeout on the socket to ip '%s' port '%s'", hostBfr, servBfr); + } if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) { error("Failed to connect to '%s', port '%s'", hostBfr, servBfr); @@ -177,3 +179,98 @@ int connect_to(const char *definition, int default_port, struct timeval *timeout return fd; } + +int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size) { + int sock = -1; + + const char *s = destination; + while(*s) { + const char *e = s; + + // skip separators, moving both s(tart) and e(nd) + while(isspace(*e) || *e == ',') s = ++e; + + // move e(nd) to the first separator + while(*e && !isspace(*e) && *e != ',') e++; + + // is there anything? + if(!*s || s == e) break; + + char buf[e - s + 1]; + strncpyz(buf, s, e - s); + if(reconnects_counter) *reconnects_counter += 1; + sock = connect_to(buf, default_port, timeout); + if(sock != -1) { + if(connected_to && connected_to_size) { + strncpy(connected_to, buf, connected_to_size); + connected_to[connected_to_size - 1] = '\0'; + } + break; + } + s = e; + } + + return sock; +} + +ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout) { + for(;;) { + struct pollfd fd = { + .fd = sockfd, + .events = POLLIN, + .revents = 0 + }; + + errno = 0; + int retval = poll(&fd, 1, timeout * 1000); + + if(retval == -1) { + // failed + + if(errno == EINTR || errno == EAGAIN) + continue; + + return -1; + } + + if(!retval) { + // timeout + return 0; + } + + if(fd.events & POLLIN) break; + } + + return recv(sockfd, buf, len, flags); +} + +ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout) { + for(;;) { + struct pollfd fd = { + .fd = sockfd, + .events = POLLOUT, + .revents = 0 + }; + + errno = 0; + int retval = poll(&fd, 1, timeout * 1000); + + if(retval == -1) { + // failed + + if(errno == EINTR || errno == EAGAIN) + continue; + + return -1; + } + + if(!retval) { + // timeout + return 0; + } + + if(fd.events & POLLOUT) break; + } + + return send(sockfd, buf, len, flags); +} diff --git a/src/socket.h b/src/socket.h index 791c0ce5..89c154a6 100644 --- a/src/socket.h +++ b/src/socket.h @@ -6,5 +6,9 @@ #define NETDATA_SOCKET_H extern int connect_to(const char *definition, int default_port, struct timeval *timeout); +extern int connect_to_one_of(const char *destination, int default_port, struct timeval *timeout, size_t *reconnects_counter, char *connected_to, size_t connected_to_size); + +extern ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout); +extern ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout); #endif //NETDATA_SOCKET_H diff --git a/src/sys_devices_system_edac_mc.c b/src/sys_devices_system_edac_mc.c index 260f5121..c41ad7fa 100644 --- a/src/sys_devices_system_edac_mc.c +++ b/src/sys_devices_system_edac_mc.c @@ -76,11 +76,11 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { struct mc *m; if(unlikely(do_ce == -1)) { - do_ce = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory correctable errors", CONFIG_ONDEMAND_ONDEMAND); - do_ue = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory uncorrectable errors", CONFIG_ONDEMAND_ONDEMAND); + do_ce = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory correctable errors", CONFIG_BOOLEAN_AUTO); + do_ue = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory uncorrectable errors", CONFIG_BOOLEAN_AUTO); } - if(do_ce != CONFIG_ONDEMAND_NO) { + if(do_ce != CONFIG_BOOLEAN_NO) { for(m = mc_root; m; m = m->next) { if(m->ce_count_filename) { m->ce_updated = 0; @@ -102,7 +102,7 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { } } - if(do_ue != CONFIG_ONDEMAND_NO) { + if(do_ue != CONFIG_BOOLEAN_NO) { for(m = mc_root; m; m = m->next) { if(m->ue_count_filename) { m->ue_updated = 0; @@ -126,20 +126,20 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ce == CONFIG_ONDEMAND_YES || (do_ce == CONFIG_ONDEMAND_ONDEMAND && ce_sum > 0)) { - do_ce = CONFIG_ONDEMAND_YES; + if(do_ce == CONFIG_BOOLEAN_YES || (do_ce == CONFIG_BOOLEAN_AUTO && ce_sum > 0)) { + do_ce = CONFIG_BOOLEAN_YES; static RRDSET *ce_st = NULL; if(unlikely(!ce_st)) { - ce_st = rrdset_find("mem.ecc_ce"); + ce_st = rrdset_find_localhost("mem.ecc_ce"); if(unlikely(!ce_st)) - ce_st = rrdset_create("mem", "ecc_ce", NULL, "ecc", NULL, "ECC Memory Correctable Errors", "errors", - 6600, update_every, RRDSET_TYPE_LINE); + ce_st = rrdset_create_localhost("mem", "ecc_ce", NULL, "ecc", NULL, "ECC Memory Correctable Errors" + , "errors", 6600, update_every, RRDSET_TYPE_LINE); for(m = mc_root; m; m = m->next) if(m->ce_count_filename) - m->ce_rd = rrddim_add(ce_st, m->name, NULL, 1, 1, RRDDIM_INCREMENTAL); + m->ce_rd = rrddim_add(ce_st, m->name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(ce_st); @@ -153,21 +153,21 @@ int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) { // -------------------------------------------------------------------- - if(do_ue == CONFIG_ONDEMAND_YES || (do_ue == CONFIG_ONDEMAND_ONDEMAND && ue_sum > 0)) { - do_ue = CONFIG_ONDEMAND_YES; + if(do_ue == CONFIG_BOOLEAN_YES || (do_ue == CONFIG_BOOLEAN_AUTO && ue_sum > 0)) { + do_ue = CONFIG_BOOLEAN_YES; static RRDSET *ue_st = NULL; if(unlikely(!ue_st)) { - ue_st = rrdset_find("mem.ecc_ue"); + ue_st = rrdset_find_localhost("mem.ecc_ue"); if(unlikely(!ue_st)) - ue_st = rrdset_create("mem", "ecc_ue", NULL, "ecc", NULL, "ECC Memory Uncorrectable Errors", "errors", - 6610, update_every, RRDSET_TYPE_LINE); + ue_st = rrdset_create_localhost("mem", "ecc_ue", NULL, "ecc", NULL, "ECC Memory Uncorrectable Errors" + , "errors", 6610, update_every, RRDSET_TYPE_LINE); for(m = mc_root; m; m = m->next) if(m->ue_count_filename) - m->ue_rd = rrddim_add(ue_st, m->name, NULL, 1, 1, RRDDIM_INCREMENTAL); + m->ue_rd = rrddim_add(ue_st, m->name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(ue_st); diff --git a/src/sys_devices_system_node.c b/src/sys_devices_system_node.c index eb031829..449bbf0d 100644 --- a/src/sys_devices_system_node.c +++ b/src/sys_devices_system_node.c @@ -72,10 +72,10 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) { struct node *m; if(unlikely(do_numastat == -1)) { - do_numastat = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_ONDEMAND_ONDEMAND); + do_numastat = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/node", "enable per-node numa metrics", CONFIG_BOOLEAN_AUTO); } - if(do_numastat == CONFIG_ONDEMAND_YES || (do_numastat == CONFIG_ONDEMAND_ONDEMAND && numa_node_count >= 2)) { + if(do_numastat == CONFIG_BOOLEAN_YES || (do_numastat == CONFIG_BOOLEAN_AUTO && numa_node_count >= 2)) { for(m = numa_root; m; m = m->next) { if(m->numastat_filename) { if(unlikely(!m->numastat_ff)) { @@ -92,13 +92,14 @@ int do_proc_sys_devices_system_node(int update_every, usec_t dt) { RRDSET *st = m->numastat_st; if(unlikely(!st)) { - st = rrdset_create("mem", m->name, NULL, "numa", NULL, "NUMA events", "events/s", 1000, update_every, RRDSET_TYPE_LINE); - st->isdetail = 1; - - rrddim_add(st, "local_node", "local", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "numa_foreign", "foreign", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "interleave_hit", "interleave", 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(st, "other_node", "other", 1, 1, RRDDIM_INCREMENTAL); + st = rrdset_create_localhost("mem", m->name, NULL, "numa", NULL, "NUMA events", "events/s", 1000 + , update_every, RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DETAIL); + + rrddim_add(st, "local_node", "local", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "numa_foreign", "foreign", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "interleave_hit", "interleave", 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(st, "other_node", "other", 1, 1, RRD_ALGORITHM_INCREMENTAL); m->numastat_st = st; } diff --git a/src/sys_fs_cgroup.c b/src/sys_fs_cgroup.c index 8b92646b..7981804a 100644 --- a/src/sys_fs_cgroup.c +++ b/src/sys_fs_cgroup.c @@ -8,22 +8,22 @@ static long system_page_size = 4096; // system will be queried via sysconf() in configuration() -static int cgroup_enable_cpuacct_stat = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_cpuacct_usage = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_memory = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_detailed_memory = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_memory_failcnt = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_swap = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_blkio_io = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_blkio_ops = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_blkio_throttle_io = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_blkio_throttle_ops = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_blkio_merged_ops = CONFIG_ONDEMAND_ONDEMAND; -static int cgroup_enable_blkio_queued_ops = CONFIG_ONDEMAND_ONDEMAND; - -static int cgroup_enable_systemd_services = CONFIG_ONDEMAND_YES; -static int cgroup_enable_systemd_services_detailed_memory = CONFIG_ONDEMAND_NO; -static int cgroup_used_memory_without_cache = CONFIG_ONDEMAND_YES; +static int cgroup_enable_cpuacct_stat = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_cpuacct_usage = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_memory = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_detailed_memory = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_memory_failcnt = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_swap = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_blkio_io = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_blkio_ops = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_blkio_throttle_io = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_blkio_throttle_ops = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_blkio_merged_ops = CONFIG_BOOLEAN_AUTO; +static int cgroup_enable_blkio_queued_ops = CONFIG_BOOLEAN_AUTO; + +static int cgroup_enable_systemd_services = CONFIG_BOOLEAN_YES; +static int cgroup_enable_systemd_services_detailed_memory = CONFIG_BOOLEAN_NO; +static int cgroup_used_memory_without_cache = CONFIG_BOOLEAN_YES; static int cgroup_search_in_devices = 1; @@ -64,9 +64,9 @@ void read_cgroup_plugin_configuration() { user_hash = simple_hash("user"); system_hash = simple_hash("system"); - cgroup_update_every = (int)config_get_number("plugin:cgroups", "update every", rrd_update_every); - if(cgroup_update_every < rrd_update_every) - cgroup_update_every = rrd_update_every; + cgroup_update_every = (int)config_get_number("plugin:cgroups", "update every", localhost->rrd_update_every); + if(cgroup_update_every < localhost->rrd_update_every) + cgroup_update_every = localhost->rrd_update_every; cgroup_check_for_new_every = (int)config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every * cgroup_update_every); if(cgroup_check_for_new_every < cgroup_update_every) @@ -211,7 +211,7 @@ void read_cgroup_plugin_configuration() { struct blkio { int updated; - int enabled; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND + int enabled; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO int delay_counter; char *filename; @@ -236,10 +236,10 @@ struct memory { int updated_msw_usage_in_bytes; int updated_failcnt; - int enabled_detailed; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND - int enabled_usage_in_bytes; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND - int enabled_msw_usage_in_bytes; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND - int enabled_failcnt; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND + int enabled_detailed; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO + int enabled_usage_in_bytes; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO + int enabled_msw_usage_in_bytes; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO + int enabled_failcnt; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO int delay_counter_detailed; int delay_counter_failcnt; @@ -298,7 +298,7 @@ struct memory { // https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt struct cpuacct_stat { int updated; - int enabled; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND + int enabled; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO char *filename; @@ -309,7 +309,7 @@ struct cpuacct_stat { // https://www.kernel.org/doc/Documentation/cgroup-v1/cpuacct.txt struct cpuacct_usage { int updated; - int enabled; // CONFIG_ONDEMAND_YES or CONFIG_ONDEMAND_ONDEMAND + int enabled; // CONFIG_BOOLEAN_YES or CONFIG_BOOLEAN_AUTO char *filename; @@ -437,8 +437,8 @@ static inline void cgroup_read_cpuacct_stat(struct cpuacct_stat *cp) { cp->updated = 1; - if(unlikely(cp->enabled == CONFIG_ONDEMAND_ONDEMAND && (cp->user || cp->system))) - cp->enabled = CONFIG_ONDEMAND_YES; + if(unlikely(cp->enabled == CONFIG_BOOLEAN_AUTO && (cp->user || cp->system))) + cp->enabled = CONFIG_BOOLEAN_YES; } } @@ -492,15 +492,15 @@ static inline void cgroup_read_cpuacct_usage(struct cpuacct_usage *ca) { ca->updated = 1; - if(unlikely(ca->enabled == CONFIG_ONDEMAND_ONDEMAND && total)) - ca->enabled = CONFIG_ONDEMAND_YES; + if(unlikely(ca->enabled == CONFIG_BOOLEAN_AUTO && total)) + ca->enabled = CONFIG_BOOLEAN_YES; } } static inline void cgroup_read_blkio(struct blkio *io) { static procfile *ff = NULL; - if(unlikely(io->enabled == CONFIG_ONDEMAND_ONDEMAND && io->delay_counter > 0)) { + if(unlikely(io->enabled == CONFIG_BOOLEAN_AUTO && io->delay_counter > 0)) { io->delay_counter--; return; } @@ -558,9 +558,9 @@ static inline void cgroup_read_blkio(struct blkio *io) { io->updated = 1; - if(unlikely(io->enabled == CONFIG_ONDEMAND_ONDEMAND)) { + if(unlikely(io->enabled == CONFIG_BOOLEAN_AUTO)) { if(unlikely(io->Read || io->Write)) - io->enabled = CONFIG_ONDEMAND_YES; + io->enabled = CONFIG_BOOLEAN_YES; else io->delay_counter = cgroup_recheck_zero_blkio_every_iterations; } @@ -572,7 +572,7 @@ static inline void cgroup_read_memory(struct memory *mem) { // read detailed ram usage if(likely(mem->filename_detailed)) { - if(unlikely(mem->enabled_detailed == CONFIG_ONDEMAND_ONDEMAND && mem->delay_counter_detailed > 0)) { + if(unlikely(mem->enabled_detailed == CONFIG_BOOLEAN_AUTO && mem->delay_counter_detailed > 0)) { mem->delay_counter_detailed--; goto memory_next; } @@ -631,9 +631,9 @@ static inline void cgroup_read_memory(struct memory *mem) { mem->updated_detailed = 1; - if(unlikely(mem->enabled_detailed == CONFIG_ONDEMAND_ONDEMAND)) { + if(unlikely(mem->enabled_detailed == CONFIG_BOOLEAN_AUTO)) { if(mem->cache || mem->dirty || mem->rss || mem->rss_huge || mem->mapped_file || mem->writeback || mem->swap || mem->pgpgin || mem->pgpgout || mem->pgfault || mem->pgmajfault) - mem->enabled_detailed = CONFIG_ONDEMAND_YES; + mem->enabled_detailed = CONFIG_BOOLEAN_YES; else mem->delay_counter_detailed = cgroup_recheck_zero_mem_detailed_every_iterations; } @@ -644,30 +644,30 @@ memory_next: // read usage_in_bytes if(likely(mem->filename_usage_in_bytes)) { mem->updated_usage_in_bytes = !read_single_number_file(mem->filename_usage_in_bytes, &mem->usage_in_bytes); - if(unlikely(mem->updated_usage_in_bytes && mem->enabled_usage_in_bytes == CONFIG_ONDEMAND_ONDEMAND && mem->usage_in_bytes)) - mem->enabled_usage_in_bytes = CONFIG_ONDEMAND_YES; + if(unlikely(mem->updated_usage_in_bytes && mem->enabled_usage_in_bytes == CONFIG_BOOLEAN_AUTO && mem->usage_in_bytes)) + mem->enabled_usage_in_bytes = CONFIG_BOOLEAN_YES; } // read msw_usage_in_bytes if(likely(mem->filename_msw_usage_in_bytes)) { mem->updated_msw_usage_in_bytes = !read_single_number_file(mem->filename_msw_usage_in_bytes, &mem->msw_usage_in_bytes); - if(unlikely(mem->updated_msw_usage_in_bytes && mem->enabled_msw_usage_in_bytes == CONFIG_ONDEMAND_ONDEMAND && mem->msw_usage_in_bytes)) - mem->enabled_msw_usage_in_bytes = CONFIG_ONDEMAND_YES; + if(unlikely(mem->updated_msw_usage_in_bytes && mem->enabled_msw_usage_in_bytes == CONFIG_BOOLEAN_AUTO && mem->msw_usage_in_bytes)) + mem->enabled_msw_usage_in_bytes = CONFIG_BOOLEAN_YES; } // read failcnt if(likely(mem->filename_failcnt)) { - if(unlikely(mem->enabled_failcnt == CONFIG_ONDEMAND_ONDEMAND && mem->delay_counter_failcnt > 0)) { + if(unlikely(mem->enabled_failcnt == CONFIG_BOOLEAN_AUTO && mem->delay_counter_failcnt > 0)) { mem->updated_failcnt = 0; mem->delay_counter_failcnt--; } else { mem->updated_failcnt = !read_single_number_file(mem->filename_failcnt, &mem->failcnt); - if(unlikely(mem->updated_failcnt && mem->enabled_failcnt == CONFIG_ONDEMAND_ONDEMAND)) { + if(unlikely(mem->updated_failcnt && mem->enabled_failcnt == CONFIG_BOOLEAN_AUTO)) { if(unlikely(!mem->failcnt)) mem->delay_counter_failcnt = cgroup_recheck_zero_mem_failcnt_every_iterations; else - mem->enabled_failcnt = CONFIG_ONDEMAND_YES; + mem->enabled_failcnt = CONFIG_BOOLEAN_YES; } } } @@ -1074,7 +1074,7 @@ static inline void find_all_cgroups() { if(cgroup_enable_cpuacct_stat || cgroup_enable_cpuacct_usage) { if(find_dir_in_subdirs(cgroup_cpuacct_base, NULL, found_subdir_in_dir) == -1) { cgroup_enable_cpuacct_stat = - cgroup_enable_cpuacct_usage = CONFIG_ONDEMAND_NO; + cgroup_enable_cpuacct_usage = CONFIG_BOOLEAN_NO; error("disabled CGROUP cpu statistics."); } } @@ -1086,7 +1086,7 @@ static inline void find_all_cgroups() { cgroup_enable_blkio_throttle_io = cgroup_enable_blkio_throttle_ops = cgroup_enable_blkio_merged_ops = - cgroup_enable_blkio_queued_ops = CONFIG_ONDEMAND_NO; + cgroup_enable_blkio_queued_ops = CONFIG_BOOLEAN_NO; error("disabled CGROUP blkio statistics."); } } @@ -1096,7 +1096,7 @@ static inline void find_all_cgroups() { cgroup_enable_memory = cgroup_enable_detailed_memory = cgroup_enable_swap = - cgroup_enable_memory_failcnt = CONFIG_ONDEMAND_NO; + cgroup_enable_memory_failcnt = CONFIG_BOOLEAN_NO; error("disabled CGROUP memory statistics."); } } @@ -1150,7 +1150,7 @@ static inline void find_all_cgroups() { snprintfz(filename, FILENAME_MAX, "%s%s/memory.stat", cgroup_memory_base, cg->id); if(likely(stat(filename, &buf) != -1)) { cg->memory.filename_detailed = strdupz(filename); - cg->memory.enabled_detailed = (cgroup_enable_detailed_memory == CONFIG_ONDEMAND_YES)?CONFIG_ONDEMAND_YES:CONFIG_ONDEMAND_ONDEMAND; + cg->memory.enabled_detailed = (cgroup_enable_detailed_memory == CONFIG_BOOLEAN_YES)?CONFIG_BOOLEAN_YES:CONFIG_BOOLEAN_AUTO; debug(D_CGROUP, "memory.stat filename for cgroup '%s': '%s'", cg->id, cg->memory.filename_detailed); } else @@ -1314,10 +1314,11 @@ void update_services_charts(int update_every, if(unlikely(!st_cpu)) { char title[CHART_TITLE_MAX + 1]; - st_cpu = rrdset_find_bytype("services", "cpu"); + st_cpu = rrdset_find_bytype_localhost("services", "cpu"); if(likely(!st_cpu)) { snprintfz(title, CHART_TITLE_MAX, "Systemd Services CPU utilization (%d%% = %d core%s)", (processors * 100), processors, (processors > 1) ? "s" : ""); - st_cpu = rrdset_create("services", "cpu", NULL, "cpu", "services.cpu", title, "%", CHART_PRIORITY_SYSTEMD_SERVICES, update_every, RRDSET_TYPE_STACKED); + st_cpu = rrdset_create_localhost("services", "cpu", NULL, "cpu", "services.cpu", title, "%" + , CHART_PRIORITY_SYSTEMD_SERVICES, update_every, RRDSET_TYPE_STACKED); } } else @@ -1326,9 +1327,13 @@ void update_services_charts(int update_every, if(likely(do_mem_usage)) { if(unlikely(!st_mem_usage)) { - st_mem_usage = rrdset_find_bytype("services", "mem_usage"); + st_mem_usage = rrdset_find_bytype_localhost("services", "mem_usage"); if(likely(!st_mem_usage)) - st_mem_usage = rrdset_create("services", "mem_usage", NULL, "mem", "services.mem_usage", (cgroup_used_memory_without_cache)?"Systemd Services Used Memory without Cache":"Systemd Services Used Memory", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 10, update_every, RRDSET_TYPE_STACKED); + st_mem_usage = rrdset_create_localhost("services", "mem_usage", NULL, "mem", "services.mem_usage" + , (cgroup_used_memory_without_cache) + ? "Systemd Services Used Memory without Cache" + : "Systemd Services Used Memory", "MB", + CHART_PRIORITY_SYSTEMD_SERVICES + 10, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_usage); @@ -1336,65 +1341,90 @@ void update_services_charts(int update_every, if(likely(do_mem_detailed)) { if(unlikely(!st_mem_detailed_rss)) { - st_mem_detailed_rss = rrdset_find_bytype("services", "mem_rss"); + st_mem_detailed_rss = rrdset_find_bytype_localhost("services", "mem_rss"); if(likely(!st_mem_detailed_rss)) - st_mem_detailed_rss = rrdset_create("services", "mem_rss", NULL, "mem", "services.mem_rss", "Systemd Services RSS Memory", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 20, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_rss = rrdset_create_localhost("services", "mem_rss", NULL, "mem", "services.mem_rss" + , "Systemd Services RSS Memory", "MB", + CHART_PRIORITY_SYSTEMD_SERVICES + 20, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_rss); if(unlikely(!st_mem_detailed_mapped)) { - st_mem_detailed_mapped = rrdset_find_bytype("services", "mem_mapped"); + st_mem_detailed_mapped = rrdset_find_bytype_localhost("services", "mem_mapped"); if(likely(!st_mem_detailed_mapped)) - st_mem_detailed_mapped = rrdset_create("services", "mem_mapped", NULL, "mem", "services.mem_mapped", "Systemd Services Mapped Memory", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 30, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_mapped = rrdset_create_localhost("services", "mem_mapped", NULL, "mem" + , "services.mem_mapped" + , "Systemd Services Mapped Memory", "MB", + CHART_PRIORITY_SYSTEMD_SERVICES + 30, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_mapped); if(unlikely(!st_mem_detailed_cache)) { - st_mem_detailed_cache = rrdset_find_bytype("services", "mem_cache"); + st_mem_detailed_cache = rrdset_find_bytype_localhost("services", "mem_cache"); if(likely(!st_mem_detailed_cache)) - st_mem_detailed_cache = rrdset_create("services", "mem_cache", NULL, "mem", "services.mem_cache", "Systemd Services Cache Memory", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 40, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_cache = rrdset_create_localhost("services", "mem_cache", NULL, "mem" + , "services.mem_cache", "Systemd Services Cache Memory" + , "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 40 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_cache); if(unlikely(!st_mem_detailed_writeback)) { - st_mem_detailed_writeback = rrdset_find_bytype("services", "mem_writeback"); + st_mem_detailed_writeback = rrdset_find_bytype_localhost("services", "mem_writeback"); if(likely(!st_mem_detailed_writeback)) - st_mem_detailed_writeback = rrdset_create("services", "mem_writeback", NULL, "mem", "services.mem_writeback", "Systemd Services Writeback Memory", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 50, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_writeback = rrdset_create_localhost("services", "mem_writeback", NULL, "mem" + , "services.mem_writeback" + , "Systemd Services Writeback Memory", "MB", + CHART_PRIORITY_SYSTEMD_SERVICES + 50, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_writeback); if(unlikely(!st_mem_detailed_pgfault)) { - st_mem_detailed_pgfault = rrdset_find_bytype("services", "mem_pgfault"); + st_mem_detailed_pgfault = rrdset_find_bytype_localhost("services", "mem_pgfault"); if(likely(!st_mem_detailed_pgfault)) - st_mem_detailed_pgfault = rrdset_create("services", "mem_pgfault", NULL, "mem", "services.mem_pgfault", "Systemd Services Memory Minor Page Faults", "MB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 60, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_pgfault = rrdset_create_localhost("services", "mem_pgfault", NULL, "mem" + , "services.mem_pgfault" + , "Systemd Services Memory Minor Page Faults", "MB/s", + CHART_PRIORITY_SYSTEMD_SERVICES + 60, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_pgfault); if(unlikely(!st_mem_detailed_pgmajfault)) { - st_mem_detailed_pgmajfault = rrdset_find_bytype("services", "mem_pgmajfault"); + st_mem_detailed_pgmajfault = rrdset_find_bytype_localhost("services", "mem_pgmajfault"); if(likely(!st_mem_detailed_pgmajfault)) - st_mem_detailed_pgmajfault = rrdset_create("services", "mem_pgmajfault", NULL, "mem", "services.mem_pgmajfault", "Systemd Services Memory Major Page Faults", "MB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 70, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_pgmajfault = rrdset_create_localhost("services", "mem_pgmajfault", NULL, "mem" + , "services.mem_pgmajfault" + , "Systemd Services Memory Major Page Faults" + , "MB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 70 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_pgmajfault); if(unlikely(!st_mem_detailed_pgpgin)) { - st_mem_detailed_pgpgin = rrdset_find_bytype("services", "mem_pgpgin"); + st_mem_detailed_pgpgin = rrdset_find_bytype_localhost("services", "mem_pgpgin"); if(likely(!st_mem_detailed_pgpgin)) - st_mem_detailed_pgpgin = rrdset_create("services", "mem_pgpgin", NULL, "mem", "services.mem_pgpgin", "Systemd Services Memory Charging Activity", "MB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 80, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_pgpgin = rrdset_create_localhost("services", "mem_pgpgin", NULL, "mem" + , "services.mem_pgpgin" + , "Systemd Services Memory Charging Activity", "MB/s", + CHART_PRIORITY_SYSTEMD_SERVICES + 80, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_pgpgin); if(unlikely(!st_mem_detailed_pgpgout)) { - st_mem_detailed_pgpgout = rrdset_find_bytype("services", "mem_pgpgout"); + st_mem_detailed_pgpgout = rrdset_find_bytype_localhost("services", "mem_pgpgout"); if(likely(!st_mem_detailed_pgpgout)) - st_mem_detailed_pgpgout = rrdset_create("services", "mem_pgpgout", NULL, "mem", "services.mem_pgpgout", "Systemd Services Memory Uncharging Activity", "MB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 90, update_every, RRDSET_TYPE_STACKED); + st_mem_detailed_pgpgout = rrdset_create_localhost("services", "mem_pgpgout", NULL, "mem" + , "services.mem_pgpgout" + , "Systemd Services Memory Uncharging Activity" + , "MB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 90 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_detailed_pgpgout); @@ -1402,9 +1432,11 @@ void update_services_charts(int update_every, if(likely(do_mem_failcnt)) { if(unlikely(!st_mem_failcnt)) { - st_mem_failcnt = rrdset_find_bytype("services", "mem_failcnt"); + st_mem_failcnt = rrdset_find_bytype_localhost("services", "mem_failcnt"); if(likely(!st_mem_failcnt)) - st_mem_failcnt = rrdset_create("services", "mem_failcnt", NULL, "mem", "services.mem_failcnt", "Systemd Services Memory Limit Failures", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 110, update_every, RRDSET_TYPE_STACKED); + st_mem_failcnt = rrdset_create_localhost("services", "mem_failcnt", NULL, "mem", "services.mem_failcnt" + , "Systemd Services Memory Limit Failures", "MB", + CHART_PRIORITY_SYSTEMD_SERVICES + 110, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_mem_failcnt); @@ -1412,9 +1444,11 @@ void update_services_charts(int update_every, if(likely(do_swap_usage)) { if(unlikely(!st_swap_usage)) { - st_swap_usage = rrdset_find_bytype("services", "swap_usage"); + st_swap_usage = rrdset_find_bytype_localhost("services", "swap_usage"); if(likely(!st_swap_usage)) - st_swap_usage = rrdset_create("services", "swap_usage", NULL, "swap", "services.swap_usage", "Systemd Services Swap Memory Used", "MB", CHART_PRIORITY_SYSTEMD_SERVICES + 100, update_every, RRDSET_TYPE_STACKED); + st_swap_usage = rrdset_create_localhost("services", "swap_usage", NULL, "swap", "services.swap_usage" + , "Systemd Services Swap Memory Used", "MB", + CHART_PRIORITY_SYSTEMD_SERVICES + 100, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_swap_usage); @@ -1422,17 +1456,21 @@ void update_services_charts(int update_every, if(likely(do_io)) { if(unlikely(!st_io_read)) { - st_io_read = rrdset_find_bytype("services", "io_read"); + st_io_read = rrdset_find_bytype_localhost("services", "io_read"); if(likely(!st_io_read)) - st_io_read = rrdset_create("services", "io_read", NULL, "disk", "services.io_read", "Systemd Services Disk Read Bandwidth", "KB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 120, update_every, RRDSET_TYPE_STACKED); + st_io_read = rrdset_create_localhost("services", "io_read", NULL, "disk", "services.io_read" + , "Systemd Services Disk Read Bandwidth", "KB/s", + CHART_PRIORITY_SYSTEMD_SERVICES + 120, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_io_read); if(unlikely(!st_io_write)) { - st_io_write = rrdset_find_bytype("services", "io_write"); + st_io_write = rrdset_find_bytype_localhost("services", "io_write"); if(likely(!st_io_write)) - st_io_write = rrdset_create("services", "io_write", NULL, "disk", "services.io_write", "Systemd Services Disk Write Bandwidth", "KB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 130, update_every, RRDSET_TYPE_STACKED); + st_io_write = rrdset_create_localhost("services", "io_write", NULL, "disk", "services.io_write" + , "Systemd Services Disk Write Bandwidth", "KB/s", + CHART_PRIORITY_SYSTEMD_SERVICES + 130, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_io_write); @@ -1440,17 +1478,24 @@ void update_services_charts(int update_every, if(likely(do_io_ops)) { if(unlikely(!st_io_serviced_read)) { - st_io_serviced_read = rrdset_find_bytype("services", "io_ops_read"); + st_io_serviced_read = rrdset_find_bytype_localhost("services", "io_ops_read"); if(likely(!st_io_serviced_read)) - st_io_serviced_read = rrdset_create("services", "io_ops_read", NULL, "disk", "services.io_ops_read", "Systemd Services Disk Read Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 140, update_every, RRDSET_TYPE_STACKED); + st_io_serviced_read = rrdset_create_localhost("services", "io_ops_read", NULL, "disk" + , "services.io_ops_read" + , "Systemd Services Disk Read Operations", "operations/s", + CHART_PRIORITY_SYSTEMD_SERVICES + 140, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_io_serviced_read); if(unlikely(!st_io_serviced_write)) { - st_io_serviced_write = rrdset_find_bytype("services", "io_ops_write"); + st_io_serviced_write = rrdset_find_bytype_localhost("services", "io_ops_write"); if(likely(!st_io_serviced_write)) - st_io_serviced_write = rrdset_create("services", "io_ops_write", NULL, "disk", "services.io_ops_write", "Systemd Services Disk Write Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 150, update_every, RRDSET_TYPE_STACKED); + st_io_serviced_write = rrdset_create_localhost("services", "io_ops_write", NULL, "disk" + , "services.io_ops_write" + , "Systemd Services Disk Write Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 150 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_io_serviced_write); @@ -1458,17 +1503,24 @@ void update_services_charts(int update_every, if(likely(do_throttle_io)) { if(unlikely(!st_throttle_io_read)) { - st_throttle_io_read = rrdset_find_bytype("services", "throttle_io_read"); + st_throttle_io_read = rrdset_find_bytype_localhost("services", "throttle_io_read"); if(likely(!st_throttle_io_read)) - st_throttle_io_read = rrdset_create("services", "throttle_io_read", NULL, "disk", "services.throttle_io_read", "Systemd Services Throttle Disk Read Bandwidth", "KB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 160, update_every, RRDSET_TYPE_STACKED); + st_throttle_io_read = rrdset_create_localhost("services", "throttle_io_read", NULL, "disk" + , "services.throttle_io_read" + , "Systemd Services Throttle Disk Read Bandwidth", "KB/s", + CHART_PRIORITY_SYSTEMD_SERVICES + 160, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_throttle_io_read); if(unlikely(!st_throttle_io_write)) { - st_throttle_io_write = rrdset_find_bytype("services", "throttle_io_write"); + st_throttle_io_write = rrdset_find_bytype_localhost("services", "throttle_io_write"); if(likely(!st_throttle_io_write)) - st_throttle_io_write = rrdset_create("services", "throttle_io_write", NULL, "disk", "services.throttle_io_write", "Systemd Services Throttle Disk Write Bandwidth", "KB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 170, update_every, RRDSET_TYPE_STACKED); + st_throttle_io_write = rrdset_create_localhost("services", "throttle_io_write", NULL, "disk" + , "services.throttle_io_write" + , "Systemd Services Throttle Disk Write Bandwidth" + , "KB/s", CHART_PRIORITY_SYSTEMD_SERVICES + 170 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_throttle_io_write); @@ -1476,17 +1528,25 @@ void update_services_charts(int update_every, if(likely(do_throttle_ops)) { if(unlikely(!st_throttle_ops_read)) { - st_throttle_ops_read = rrdset_find_bytype("services", "throttle_io_ops_read"); + st_throttle_ops_read = rrdset_find_bytype_localhost("services", "throttle_io_ops_read"); if(likely(!st_throttle_ops_read)) - st_throttle_ops_read = rrdset_create("services", "throttle_io_ops_read", NULL, "disk", "services.throttle_io_ops_read", "Systemd Services Throttle Disk Read Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 180, update_every, RRDSET_TYPE_STACKED); + st_throttle_ops_read = rrdset_create_localhost("services", "throttle_io_ops_read", NULL, "disk" + , "services.throttle_io_ops_read" + , "Systemd Services Throttle Disk Read Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 180 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_throttle_ops_read); if(unlikely(!st_throttle_ops_write)) { - st_throttle_ops_write = rrdset_find_bytype("services", "throttle_io_ops_write"); + st_throttle_ops_write = rrdset_find_bytype_localhost("services", "throttle_io_ops_write"); if(likely(!st_throttle_ops_write)) - st_throttle_ops_write = rrdset_create("services", "throttle_io_ops_write", NULL, "disk", "services.throttle_io_ops_write", "Systemd Services Throttle Disk Write Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 190, update_every, RRDSET_TYPE_STACKED); + st_throttle_ops_write = rrdset_create_localhost("services", "throttle_io_ops_write", NULL, "disk" + , "services.throttle_io_ops_write" + , "Systemd Services Throttle Disk Write Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 190 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_throttle_ops_write); @@ -1494,17 +1554,25 @@ void update_services_charts(int update_every, if(likely(do_queued_ops)) { if(unlikely(!st_queued_ops_read)) { - st_queued_ops_read = rrdset_find_bytype("services", "queued_io_ops_read"); + st_queued_ops_read = rrdset_find_bytype_localhost("services", "queued_io_ops_read"); if(likely(!st_queued_ops_read)) - st_queued_ops_read = rrdset_create("services", "queued_io_ops_read", NULL, "disk", "services.queued_io_ops_read", "Systemd Services Queued Disk Read Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 200, update_every, RRDSET_TYPE_STACKED); + st_queued_ops_read = rrdset_create_localhost("services", "queued_io_ops_read", NULL, "disk" + , "services.queued_io_ops_read" + , "Systemd Services Queued Disk Read Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 200 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_queued_ops_read); if(unlikely(!st_queued_ops_write)) { - st_queued_ops_write = rrdset_find_bytype("services", "queued_io_ops_write"); + st_queued_ops_write = rrdset_find_bytype_localhost("services", "queued_io_ops_write"); if(likely(!st_queued_ops_write)) - st_queued_ops_write = rrdset_create("services", "queued_io_ops_write", NULL, "disk", "services.queued_io_ops_write", "Systemd Services Queued Disk Write Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 210, update_every, RRDSET_TYPE_STACKED); + st_queued_ops_write = rrdset_create_localhost("services", "queued_io_ops_write", NULL, "disk" + , "services.queued_io_ops_write" + , "Systemd Services Queued Disk Write Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 210 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_queued_ops_write); @@ -1512,17 +1580,25 @@ void update_services_charts(int update_every, if(likely(do_merged_ops)) { if(unlikely(!st_merged_ops_read)) { - st_merged_ops_read = rrdset_find_bytype("services", "merged_io_ops_read"); + st_merged_ops_read = rrdset_find_bytype_localhost("services", "merged_io_ops_read"); if(likely(!st_merged_ops_read)) - st_merged_ops_read = rrdset_create("services", "merged_io_ops_read", NULL, "disk", "services.merged_io_ops_read", "Systemd Services Merged Disk Read Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 220, update_every, RRDSET_TYPE_STACKED); + st_merged_ops_read = rrdset_create_localhost("services", "merged_io_ops_read", NULL, "disk" + , "services.merged_io_ops_read" + , "Systemd Services Merged Disk Read Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 220 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_merged_ops_read); if(unlikely(!st_merged_ops_write)) { - st_merged_ops_write = rrdset_find_bytype("services", "merged_io_ops_write"); + st_merged_ops_write = rrdset_find_bytype_localhost("services", "merged_io_ops_write"); if(likely(!st_merged_ops_write)) - st_merged_ops_write = rrdset_create("services", "merged_io_ops_write", NULL, "disk", "services.merged_io_ops_write", "Systemd Services Merged Disk Write Operations", "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 230, update_every, RRDSET_TYPE_STACKED); + st_merged_ops_write = rrdset_create_localhost("services", "merged_io_ops_write", NULL, "disk" + , "services.merged_io_ops_write" + , "Systemd Services Merged Disk Write Operations" + , "operations/s", CHART_PRIORITY_SYSTEMD_SERVICES + 230 + , update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st_merged_ops_write); @@ -1536,134 +1612,134 @@ void update_services_charts(int update_every, if(likely(do_cpu && cg->cpuacct_stat.updated)) { if(unlikely(!cg->rd_cpu)) - cg->rd_cpu = rrddim_add(st_cpu, cg->chart_id, cg->chart_title, 100, hz, RRDDIM_INCREMENTAL); + cg->rd_cpu = rrddim_add(st_cpu, cg->chart_id, cg->chart_title, 100, hz, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_cpu, cg->rd_cpu, cg->cpuacct_stat.user + cg->cpuacct_stat.system); } if(likely(do_mem_usage && cg->memory.updated_usage_in_bytes)) { if(unlikely(!cg->rd_mem_usage)) - cg->rd_mem_usage = rrddim_add(st_mem_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + cg->rd_mem_usage = rrddim_add(st_mem_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(st_mem_usage, cg->rd_mem_usage, cg->memory.usage_in_bytes - ((cgroup_used_memory_without_cache)?cg->memory.cache:0)); } if(likely(do_mem_detailed && cg->memory.updated_detailed)) { if(unlikely(!cg->rd_mem_detailed_rss)) - cg->rd_mem_detailed_rss = rrddim_add(st_mem_detailed_rss, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + cg->rd_mem_detailed_rss = rrddim_add(st_mem_detailed_rss, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(st_mem_detailed_rss, cg->rd_mem_detailed_rss, cg->memory.rss + cg->memory.rss_huge); if(unlikely(!cg->rd_mem_detailed_mapped)) - cg->rd_mem_detailed_mapped = rrddim_add(st_mem_detailed_mapped, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + cg->rd_mem_detailed_mapped = rrddim_add(st_mem_detailed_mapped, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(st_mem_detailed_mapped, cg->rd_mem_detailed_mapped, cg->memory.mapped_file); if(unlikely(!cg->rd_mem_detailed_cache)) - cg->rd_mem_detailed_cache = rrddim_add(st_mem_detailed_cache, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + cg->rd_mem_detailed_cache = rrddim_add(st_mem_detailed_cache, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(st_mem_detailed_cache, cg->rd_mem_detailed_cache, cg->memory.cache); if(unlikely(!cg->rd_mem_detailed_writeback)) - cg->rd_mem_detailed_writeback = rrddim_add(st_mem_detailed_writeback, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + cg->rd_mem_detailed_writeback = rrddim_add(st_mem_detailed_writeback, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(st_mem_detailed_writeback, cg->rd_mem_detailed_writeback, cg->memory.writeback); if(unlikely(!cg->rd_mem_detailed_pgfault)) - cg->rd_mem_detailed_pgfault = rrddim_add(st_mem_detailed_pgfault, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); + cg->rd_mem_detailed_pgfault = rrddim_add(st_mem_detailed_pgfault, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_mem_detailed_pgfault, cg->rd_mem_detailed_pgfault, cg->memory.pgfault); if(unlikely(!cg->rd_mem_detailed_pgmajfault)) - cg->rd_mem_detailed_pgmajfault = rrddim_add(st_mem_detailed_pgmajfault, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); + cg->rd_mem_detailed_pgmajfault = rrddim_add(st_mem_detailed_pgmajfault, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_mem_detailed_pgmajfault, cg->rd_mem_detailed_pgmajfault, cg->memory.pgmajfault); if(unlikely(!cg->rd_mem_detailed_pgpgin)) - cg->rd_mem_detailed_pgpgin = rrddim_add(st_mem_detailed_pgpgin, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); + cg->rd_mem_detailed_pgpgin = rrddim_add(st_mem_detailed_pgpgin, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_mem_detailed_pgpgin, cg->rd_mem_detailed_pgpgin, cg->memory.pgpgin); if(unlikely(!cg->rd_mem_detailed_pgpgout)) - cg->rd_mem_detailed_pgpgout = rrddim_add(st_mem_detailed_pgpgout, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); + cg->rd_mem_detailed_pgpgout = rrddim_add(st_mem_detailed_pgpgout, cg->chart_id, cg->chart_title, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_mem_detailed_pgpgout, cg->rd_mem_detailed_pgpgout, cg->memory.pgpgout); } if(likely(do_mem_failcnt && cg->memory.updated_failcnt)) { if(unlikely(!cg->rd_mem_failcnt)) - cg->rd_mem_failcnt = rrddim_add(st_mem_failcnt, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_mem_failcnt = rrddim_add(st_mem_failcnt, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_mem_failcnt, cg->rd_mem_failcnt, cg->memory.failcnt); } if(likely(do_swap_usage && cg->memory.updated_msw_usage_in_bytes)) { if(unlikely(!cg->rd_swap_usage)) - cg->rd_swap_usage = rrddim_add(st_swap_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + cg->rd_swap_usage = rrddim_add(st_swap_usage, cg->chart_id, cg->chart_title, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(st_swap_usage, cg->rd_swap_usage, cg->memory.msw_usage_in_bytes); } if(likely(do_io && cg->io_service_bytes.updated)) { if(unlikely(!cg->rd_io_service_bytes_read)) - cg->rd_io_service_bytes_read = rrddim_add(st_io_read, cg->chart_id, cg->chart_title, 1, 1024, RRDDIM_INCREMENTAL); + cg->rd_io_service_bytes_read = rrddim_add(st_io_read, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_io_read, cg->rd_io_service_bytes_read, cg->io_service_bytes.Read); if(unlikely(!cg->rd_io_service_bytes_write)) - cg->rd_io_service_bytes_write = rrddim_add(st_io_write, cg->chart_id, cg->chart_title, 1, 1024, RRDDIM_INCREMENTAL); + cg->rd_io_service_bytes_write = rrddim_add(st_io_write, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_io_write, cg->rd_io_service_bytes_write, cg->io_service_bytes.Write); } if(likely(do_io_ops && cg->io_serviced.updated)) { if(unlikely(!cg->rd_io_serviced_read)) - cg->rd_io_serviced_read = rrddim_add(st_io_serviced_read, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_io_serviced_read = rrddim_add(st_io_serviced_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_io_serviced_read, cg->rd_io_serviced_read, cg->io_serviced.Read); if(unlikely(!cg->rd_io_serviced_write)) - cg->rd_io_serviced_write = rrddim_add(st_io_serviced_write, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_io_serviced_write = rrddim_add(st_io_serviced_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_io_serviced_write, cg->rd_io_serviced_write, cg->io_serviced.Write); } if(likely(do_throttle_io && cg->throttle_io_service_bytes.updated)) { if(unlikely(!cg->rd_throttle_io_read)) - cg->rd_throttle_io_read = rrddim_add(st_throttle_io_read, cg->chart_id, cg->chart_title, 1, 1024, RRDDIM_INCREMENTAL); + cg->rd_throttle_io_read = rrddim_add(st_throttle_io_read, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_throttle_io_read, cg->rd_throttle_io_read, cg->throttle_io_service_bytes.Read); if(unlikely(!cg->rd_throttle_io_write)) - cg->rd_throttle_io_write = rrddim_add(st_throttle_io_write, cg->chart_id, cg->chart_title, 1, 1024, RRDDIM_INCREMENTAL); + cg->rd_throttle_io_write = rrddim_add(st_throttle_io_write, cg->chart_id, cg->chart_title, 1, 1024, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_throttle_io_write, cg->rd_throttle_io_write, cg->throttle_io_service_bytes.Write); } if(likely(do_throttle_ops && cg->throttle_io_serviced.updated)) { if(unlikely(!cg->rd_throttle_io_serviced_read)) - cg->rd_throttle_io_serviced_read = rrddim_add(st_throttle_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_throttle_io_serviced_read = rrddim_add(st_throttle_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_throttle_ops_read, cg->rd_throttle_io_serviced_read, cg->throttle_io_serviced.Read); if(unlikely(!cg->rd_throttle_io_serviced_write)) - cg->rd_throttle_io_serviced_write = rrddim_add(st_throttle_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_throttle_io_serviced_write = rrddim_add(st_throttle_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_throttle_ops_write, cg->rd_throttle_io_serviced_write, cg->throttle_io_serviced.Write); } if(likely(do_queued_ops && cg->io_queued.updated)) { if(unlikely(!cg->rd_io_queued_read)) - cg->rd_io_queued_read = rrddim_add(st_queued_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_io_queued_read = rrddim_add(st_queued_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_queued_ops_read, cg->rd_io_queued_read, cg->io_queued.Read); if(unlikely(!cg->rd_io_queued_write)) - cg->rd_io_queued_write = rrddim_add(st_queued_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_io_queued_write = rrddim_add(st_queued_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_queued_ops_write, cg->rd_io_queued_write, cg->io_queued.Write); } if(likely(do_merged_ops && cg->io_merged.updated)) { if(unlikely(!cg->rd_io_merged_read)) - cg->rd_io_merged_read = rrddim_add(st_merged_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_io_merged_read = rrddim_add(st_merged_ops_read, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_merged_ops_read, cg->rd_io_merged_read, cg->io_merged.Read); if(unlikely(!cg->rd_io_merged_write)) - cg->rd_io_merged_write = rrddim_add(st_merged_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRDDIM_INCREMENTAL); + cg->rd_io_merged_write = rrddim_add(st_merged_ops_write, cg->chart_id, cg->chart_title, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st_merged_ops_write, cg->rd_io_merged_write, cg->io_merged.Write); } @@ -1760,33 +1836,35 @@ void update_cgroup_charts(int update_every) { continue; if(likely(cgroup_enable_systemd_services && cg->options & CGROUP_OPTIONS_SYSTEM_SLICE_SERVICE)) { - if(cg->cpuacct_stat.updated && cg->cpuacct_stat.enabled == CONFIG_ONDEMAND_YES) services_do_cpu++; + if(cg->cpuacct_stat.updated && cg->cpuacct_stat.enabled == CONFIG_BOOLEAN_YES) services_do_cpu++; if(cgroup_enable_systemd_services_detailed_memory && cg->memory.updated_detailed && cg->memory.enabled_detailed) services_do_mem_detailed++; - if(cg->memory.updated_usage_in_bytes && cg->memory.enabled_usage_in_bytes == CONFIG_ONDEMAND_YES) services_do_mem_usage++; - if(cg->memory.updated_failcnt && cg->memory.enabled_failcnt == CONFIG_ONDEMAND_YES) services_do_mem_failcnt++; - if(cg->memory.updated_msw_usage_in_bytes && cg->memory.enabled_msw_usage_in_bytes == CONFIG_ONDEMAND_YES) services_do_swap_usage++; - - if(cg->io_service_bytes.updated && cg->io_service_bytes.enabled == CONFIG_ONDEMAND_YES) services_do_io++; - if(cg->io_serviced.updated && cg->io_serviced.enabled == CONFIG_ONDEMAND_YES) services_do_io_ops++; - if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.enabled == CONFIG_ONDEMAND_YES) services_do_throttle_io++; - if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.enabled == CONFIG_ONDEMAND_YES) services_do_throttle_ops++; - if(cg->io_queued.updated && cg->io_queued.enabled == CONFIG_ONDEMAND_YES) services_do_queued_ops++; - if(cg->io_merged.updated && cg->io_merged.enabled == CONFIG_ONDEMAND_YES) services_do_merged_ops++; + if(cg->memory.updated_usage_in_bytes && cg->memory.enabled_usage_in_bytes == CONFIG_BOOLEAN_YES) services_do_mem_usage++; + if(cg->memory.updated_failcnt && cg->memory.enabled_failcnt == CONFIG_BOOLEAN_YES) services_do_mem_failcnt++; + if(cg->memory.updated_msw_usage_in_bytes && cg->memory.enabled_msw_usage_in_bytes == CONFIG_BOOLEAN_YES) services_do_swap_usage++; + + if(cg->io_service_bytes.updated && cg->io_service_bytes.enabled == CONFIG_BOOLEAN_YES) services_do_io++; + if(cg->io_serviced.updated && cg->io_serviced.enabled == CONFIG_BOOLEAN_YES) services_do_io_ops++; + if(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.enabled == CONFIG_BOOLEAN_YES) services_do_throttle_io++; + if(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.enabled == CONFIG_BOOLEAN_YES) services_do_throttle_ops++; + if(cg->io_queued.updated && cg->io_queued.enabled == CONFIG_BOOLEAN_YES) services_do_queued_ops++; + if(cg->io_merged.updated && cg->io_merged.enabled == CONFIG_BOOLEAN_YES) services_do_merged_ops++; continue; } type[0] = '\0'; - if(likely(cg->cpuacct_stat.updated && cg->cpuacct_stat.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->cpuacct_stat.updated && cg->cpuacct_stat.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_cpu)) { - cg->st_cpu = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "cpu"); + cg->st_cpu = rrdset_find_bytype_localhost(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX) + , "cpu"); if(likely(!cg->st_cpu)) { snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) for cgroup %s", (processors * 100), processors, (processors > 1) ? "s" : "", cg->chart_title); - cg->st_cpu = rrdset_create(type, "cpu", NULL, "cpu", "cgroup.cpu", title, "%", CHART_PRIORITY_CONTAINERS, update_every, RRDSET_TYPE_STACKED); + cg->st_cpu = rrdset_create_localhost(type, "cpu", NULL, "cpu", "cgroup.cpu", title, "%" + , CHART_PRIORITY_CONTAINERS, update_every, RRDSET_TYPE_STACKED); } - rrddim_add(cg->st_cpu, "user", NULL, 100, hz, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_cpu, "system", NULL, 100, hz, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_cpu, "user", NULL, 100, hz, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_cpu, "system", NULL, 100, hz, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_cpu); @@ -1796,19 +1874,22 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_cpu); } - if(likely(cg->cpuacct_usage.updated && cg->cpuacct_usage.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->cpuacct_usage.updated && cg->cpuacct_usage.enabled == CONFIG_BOOLEAN_YES)) { char id[RRD_ID_LENGTH_MAX + 1]; unsigned int i; if(unlikely(!cg->st_cpu_per_core)) { - cg->st_cpu_per_core = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "cpu_per_core"); + cg->st_cpu_per_core = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "cpu_per_core"); if(likely(!cg->st_cpu_per_core)) { snprintfz(title, CHART_TITLE_MAX, "CPU Usage (%d%% = %d core%s) Per Core for cgroup %s", (processors * 100), processors, (processors > 1) ? "s" : "", cg->chart_title); - cg->st_cpu_per_core = rrdset_create(type, "cpu_per_core", NULL, "cpu", "cgroup.cpu_per_core", title, "%", CHART_PRIORITY_CONTAINERS + 100, update_every, RRDSET_TYPE_STACKED); + cg->st_cpu_per_core = rrdset_create_localhost(type, "cpu_per_core", NULL, "cpu" + , "cgroup.cpu_per_core", title, "%", + CHART_PRIORITY_CONTAINERS + 100, update_every, RRDSET_TYPE_STACKED); } for(i = 0; i < cg->cpuacct_usage.cpus; i++) { snprintfz(id, CHART_TITLE_MAX, "cpu%u", i); - rrddim_add(cg->st_cpu_per_core, id, NULL, 100, 1000000000, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_cpu_per_core, id, NULL, 100, 1000000000, RRD_ALGORITHM_INCREMENTAL); } } else @@ -1821,20 +1902,22 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_cpu_per_core); } - if(likely(cg->memory.updated_detailed && cg->memory.enabled_detailed == CONFIG_ONDEMAND_YES)) { + if(likely(cg->memory.updated_detailed && cg->memory.enabled_detailed == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_mem)) { - cg->st_mem = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem"); + cg->st_mem = rrdset_find_bytype_localhost(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX) + , "mem"); if(likely(!cg->st_mem)) { snprintfz(title, CHART_TITLE_MAX, "Memory Usage for cgroup %s", cg->chart_title); - cg->st_mem = rrdset_create(type, "mem", NULL, "mem", "cgroup.mem", title, "MB", CHART_PRIORITY_CONTAINERS + 210, update_every, RRDSET_TYPE_STACKED); + cg->st_mem = rrdset_create_localhost(type, "mem", NULL, "mem", "cgroup.mem", title, "MB", + CHART_PRIORITY_CONTAINERS + 210, update_every, RRDSET_TYPE_STACKED); } - rrddim_add(cg->st_mem, "cache", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(cg->st_mem, "rss", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + rrddim_add(cg->st_mem, "cache", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(cg->st_mem, "rss", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); if(cg->memory.detailed_has_swap) - rrddim_add(cg->st_mem, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(cg->st_mem, "rss_huge", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(cg->st_mem, "mapped_file", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + rrddim_add(cg->st_mem, "swap", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(cg->st_mem, "rss_huge", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(cg->st_mem, "mapped_file", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(cg->st_mem); @@ -1848,15 +1931,18 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_mem); if(unlikely(!cg->st_writeback)) { - cg->st_writeback = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "writeback"); + cg->st_writeback = rrdset_find_bytype_localhost(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX) + , "writeback"); if(likely(!cg->st_writeback)) { snprintfz(title, CHART_TITLE_MAX, "Writeback Memory for cgroup %s", cg->chart_title); - cg->st_writeback = rrdset_create(type, "writeback", NULL, "mem", "cgroup.writeback", title, "MB", CHART_PRIORITY_CONTAINERS + 300, update_every, RRDSET_TYPE_AREA); + cg->st_writeback = rrdset_create_localhost(type, "writeback", NULL, "mem", "cgroup.writeback", title + , "MB", CHART_PRIORITY_CONTAINERS + 300, update_every + , RRDSET_TYPE_AREA); } if(cg->memory.detailed_has_dirty) - rrddim_add(cg->st_writeback, "dirty", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(cg->st_writeback, "writeback", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + rrddim_add(cg->st_writeback, "dirty", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(cg->st_writeback, "writeback", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(cg->st_writeback); @@ -1867,13 +1953,16 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_writeback); if(unlikely(!cg->st_mem_activity)) { - cg->st_mem_activity = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_activity"); + cg->st_mem_activity = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_activity"); if(likely(!cg->st_mem_activity)) { snprintfz(title, CHART_TITLE_MAX, "Memory Activity for cgroup %s", cg->chart_title); - cg->st_mem_activity = rrdset_create(type, "mem_activity", NULL, "mem", "cgroup.mem_activity", title, "MB/s", CHART_PRIORITY_CONTAINERS + 400, update_every, RRDSET_TYPE_LINE); + cg->st_mem_activity = rrdset_create_localhost(type, "mem_activity", NULL, "mem" + , "cgroup.mem_activity", title, "MB/s", + CHART_PRIORITY_CONTAINERS + 400, update_every, RRDSET_TYPE_LINE); } - rrddim_add(cg->st_mem_activity, "pgpgin", "in", system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_mem_activity, "pgpgout", "out", -system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_mem_activity, "pgpgin", "in", system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_mem_activity, "pgpgout", "out", -system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_mem_activity); @@ -1883,13 +1972,16 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_mem_activity); if(unlikely(!cg->st_pgfaults)) { - cg->st_pgfaults = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "pgfaults"); + cg->st_pgfaults = rrdset_find_bytype_localhost(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX) + , "pgfaults"); if(likely(!cg->st_pgfaults)) { snprintfz(title, CHART_TITLE_MAX, "Memory Page Faults for cgroup %s", cg->chart_title); - cg->st_pgfaults = rrdset_create(type, "pgfaults", NULL, "mem", "cgroup.pgfaults", title, "MB/s", CHART_PRIORITY_CONTAINERS + 500, update_every, RRDSET_TYPE_LINE); + cg->st_pgfaults = rrdset_create_localhost(type, "pgfaults", NULL, "mem", "cgroup.pgfaults", title + , "MB/s", CHART_PRIORITY_CONTAINERS + 500, update_every + , RRDSET_TYPE_LINE); } - rrddim_add(cg->st_pgfaults, "pgfault", NULL, system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_pgfaults, "pgmajfault", "swap", -system_page_size, 1024 * 1024, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_pgfaults, "pgfault", NULL, system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_pgfaults, "pgmajfault", "swap", -system_page_size, 1024 * 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_pgfaults); @@ -1899,15 +1991,18 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_pgfaults); } - if(likely(cg->memory.updated_usage_in_bytes && cg->memory.enabled_usage_in_bytes == CONFIG_ONDEMAND_YES)) { + if(likely(cg->memory.updated_usage_in_bytes && cg->memory.enabled_usage_in_bytes == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_mem_usage)) { - cg->st_mem_usage = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_usage"); + cg->st_mem_usage = rrdset_find_bytype_localhost(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX) + , "mem_usage"); if(likely(!cg->st_mem_usage)) { snprintfz(title, CHART_TITLE_MAX, "Used Memory %sfor cgroup %s", (cgroup_used_memory_without_cache && cg->memory.updated_detailed)?"without Cache ":"", cg->chart_title); - cg->st_mem_usage = rrdset_create(type, "mem_usage", NULL, "mem", "cgroup.mem_usage", title, "MB", CHART_PRIORITY_CONTAINERS + 200, update_every, RRDSET_TYPE_STACKED); + cg->st_mem_usage = rrdset_create_localhost(type, "mem_usage", NULL, "mem", "cgroup.mem_usage", title + , "MB", CHART_PRIORITY_CONTAINERS + 200, update_every + , RRDSET_TYPE_STACKED); } - rrddim_add(cg->st_mem_usage, "ram", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(cg->st_mem_usage, "swap", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + rrddim_add(cg->st_mem_usage, "ram", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(cg->st_mem_usage, "swap", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(cg->st_mem_usage); @@ -1917,14 +2012,17 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_mem_usage); } - if(likely(cg->memory.updated_failcnt && cg->memory.enabled_failcnt == CONFIG_ONDEMAND_YES)) { + if(likely(cg->memory.updated_failcnt && cg->memory.enabled_failcnt == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_mem_failcnt)) { - cg->st_mem_failcnt = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_failcnt"); + cg->st_mem_failcnt = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "mem_failcnt"); if(likely(!cg->st_mem_failcnt)) { snprintfz(title, CHART_TITLE_MAX, "Memory Limit Failures for cgroup %s", cg->chart_title); - cg->st_mem_failcnt = rrdset_create(type, "mem_failcnt", NULL, "mem", "cgroup.mem_failcnt", title, "count", CHART_PRIORITY_CONTAINERS + 250, update_every, RRDSET_TYPE_LINE); + cg->st_mem_failcnt = rrdset_create_localhost(type, "mem_failcnt", NULL, "mem", "cgroup.mem_failcnt" + , title, "count", CHART_PRIORITY_CONTAINERS + 250 + , update_every, RRDSET_TYPE_LINE); } - rrddim_add(cg->st_mem_failcnt, "failures", NULL, 1, 1, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_mem_failcnt, "failures", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_mem_failcnt); @@ -1933,15 +2031,16 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_mem_failcnt); } - if(likely(cg->io_service_bytes.updated && cg->io_service_bytes.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->io_service_bytes.updated && cg->io_service_bytes.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_io)) { - cg->st_io = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "io"); + cg->st_io = rrdset_find_bytype_localhost(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "io"); if(likely(!cg->st_io)) { snprintfz(title, CHART_TITLE_MAX, "I/O Bandwidth (all disks) for cgroup %s", cg->chart_title); - cg->st_io = rrdset_create(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", CHART_PRIORITY_CONTAINERS + 1200, update_every, RRDSET_TYPE_AREA); + cg->st_io = rrdset_create_localhost(type, "io", NULL, "disk", "cgroup.io", title, "KB/s", + CHART_PRIORITY_CONTAINERS + 1200, update_every, RRDSET_TYPE_AREA); } - rrddim_add(cg->st_io, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_io, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_io, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_io, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_io); @@ -1951,15 +2050,18 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_io); } - if(likely(cg->io_serviced.updated && cg->io_serviced.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->io_serviced.updated && cg->io_serviced.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_serviced_ops)) { - cg->st_serviced_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "serviced_ops"); + cg->st_serviced_ops = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "serviced_ops"); if(likely(!cg->st_serviced_ops)) { snprintfz(title, CHART_TITLE_MAX, "Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title); - cg->st_serviced_ops = rrdset_create(type, "serviced_ops", NULL, "disk", "cgroup.serviced_ops", title, "operations/s", CHART_PRIORITY_CONTAINERS + 1200, update_every, RRDSET_TYPE_LINE); + cg->st_serviced_ops = rrdset_create_localhost(type, "serviced_ops", NULL, "disk" + , "cgroup.serviced_ops", title, "operations/s", + CHART_PRIORITY_CONTAINERS + 1200, update_every, RRDSET_TYPE_LINE); } - rrddim_add(cg->st_serviced_ops, "read", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_serviced_ops, "write", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_serviced_ops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_serviced_ops, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_serviced_ops); @@ -1969,15 +2071,18 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_serviced_ops); } - if(likely(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->throttle_io_service_bytes.updated && cg->throttle_io_service_bytes.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_throttle_io)) { - cg->st_throttle_io = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "throttle_io"); + cg->st_throttle_io = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "throttle_io"); if(likely(!cg->st_throttle_io)) { snprintfz(title, CHART_TITLE_MAX, "Throttle I/O Bandwidth (all disks) for cgroup %s", cg->chart_title); - cg->st_throttle_io = rrdset_create(type, "throttle_io", NULL, "disk", "cgroup.throttle_io", title, "KB/s", CHART_PRIORITY_CONTAINERS + 1200, update_every, RRDSET_TYPE_AREA); + cg->st_throttle_io = rrdset_create_localhost(type, "throttle_io", NULL, "disk", "cgroup.throttle_io" + , title, "KB/s", CHART_PRIORITY_CONTAINERS + 1200 + , update_every, RRDSET_TYPE_AREA); } - rrddim_add(cg->st_throttle_io, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_throttle_io, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_throttle_io, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_throttle_io, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_throttle_io); @@ -1987,15 +2092,20 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_throttle_io); } - if(likely(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->throttle_io_serviced.updated && cg->throttle_io_serviced.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_throttle_serviced_ops)) { - cg->st_throttle_serviced_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "throttle_serviced_ops"); + cg->st_throttle_serviced_ops = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "throttle_serviced_ops"); if(likely(!cg->st_throttle_serviced_ops)) { snprintfz(title, CHART_TITLE_MAX, "Throttle Serviced I/O Operations (all disks) for cgroup %s", cg->chart_title); - cg->st_throttle_serviced_ops = rrdset_create(type, "throttle_serviced_ops", NULL, "disk", "cgroup.throttle_serviced_ops", title, "operations/s", CHART_PRIORITY_CONTAINERS + 1200, update_every, RRDSET_TYPE_LINE); + cg->st_throttle_serviced_ops = rrdset_create_localhost(type, "throttle_serviced_ops", NULL, "disk" + , "cgroup.throttle_serviced_ops", title + , "operations/s", CHART_PRIORITY_CONTAINERS + + 1200, update_every + , RRDSET_TYPE_LINE); } - rrddim_add(cg->st_throttle_serviced_ops, "read", NULL, 1, 1, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_throttle_serviced_ops, "write", NULL, -1, 1, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_throttle_serviced_ops, "read", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_throttle_serviced_ops, "write", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_throttle_serviced_ops); @@ -2005,15 +2115,18 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_throttle_serviced_ops); } - if(likely(cg->io_queued.updated && cg->io_queued.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->io_queued.updated && cg->io_queued.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_queued_ops)) { - cg->st_queued_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "queued_ops"); + cg->st_queued_ops = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "queued_ops"); if(likely(!cg->st_queued_ops)) { snprintfz(title, CHART_TITLE_MAX, "Queued I/O Operations (all disks) for cgroup %s", cg->chart_title); - cg->st_queued_ops = rrdset_create(type, "queued_ops", NULL, "disk", "cgroup.queued_ops", title, "operations", CHART_PRIORITY_CONTAINERS + 2000, update_every, RRDSET_TYPE_LINE); + cg->st_queued_ops = rrdset_create_localhost(type, "queued_ops", NULL, "disk", "cgroup.queued_ops" + , title, "operations", CHART_PRIORITY_CONTAINERS + 2000 + , update_every, RRDSET_TYPE_LINE); } - rrddim_add(cg->st_queued_ops, "read", NULL, 1, 1, RRDDIM_ABSOLUTE); - rrddim_add(cg->st_queued_ops, "write", NULL, -1, 1, RRDDIM_ABSOLUTE); + rrddim_add(cg->st_queued_ops, "read", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(cg->st_queued_ops, "write", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(cg->st_queued_ops); @@ -2023,15 +2136,19 @@ void update_cgroup_charts(int update_every) { rrdset_done(cg->st_queued_ops); } - if(likely(cg->io_merged.updated && cg->io_merged.enabled == CONFIG_ONDEMAND_YES)) { + if(likely(cg->io_merged.updated && cg->io_merged.enabled == CONFIG_BOOLEAN_YES)) { if(unlikely(!cg->st_merged_ops)) { - cg->st_merged_ops = rrdset_find_bytype(cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "merged_ops"); + cg->st_merged_ops = rrdset_find_bytype_localhost( + cgroup_chart_type(type, cg->chart_id, RRD_ID_LENGTH_MAX), "merged_ops"); if(likely(!cg->st_merged_ops)) { snprintfz(title, CHART_TITLE_MAX, "Merged I/O Operations (all disks) for cgroup %s", cg->chart_title); - cg->st_merged_ops = rrdset_create(type, "merged_ops", NULL, "disk", "cgroup.merged_ops", title, "operations/s", CHART_PRIORITY_CONTAINERS + 2100, update_every, RRDSET_TYPE_LINE); + cg->st_merged_ops = rrdset_create_localhost(type, "merged_ops", NULL, "disk", "cgroup.merged_ops" + , title, "operations/s", CHART_PRIORITY_CONTAINERS + + 2100, update_every + , RRDSET_TYPE_LINE); } - rrddim_add(cg->st_merged_ops, "read", NULL, 1, 1024, RRDDIM_INCREMENTAL); - rrddim_add(cg->st_merged_ops, "write", NULL, -1, 1024, RRDDIM_INCREMENTAL); + rrddim_add(cg->st_merged_ops, "read", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(cg->st_merged_ops, "write", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(cg->st_merged_ops); @@ -2110,12 +2227,14 @@ void *cgroups_main(void *ptr) { getrusage(RUSAGE_THREAD, &thread); if(unlikely(!stcpu_thread)) { - stcpu_thread = rrdset_find("netdata.plugin_cgroups_cpu"); + stcpu_thread = rrdset_find_localhost("netdata.plugin_cgroups_cpu"); if(unlikely(!stcpu_thread)) - stcpu_thread = rrdset_create("netdata", "plugin_cgroups_cpu", NULL, "cgroups", NULL, "NetData CGroups Plugin CPU usage", "milliseconds/s", 132000, cgroup_update_every, RRDSET_TYPE_STACKED); + stcpu_thread = rrdset_create_localhost("netdata", "plugin_cgroups_cpu", NULL, "cgroups", NULL + , "NetData CGroups Plugin CPU usage", "milliseconds/s" + , 132000, cgroup_update_every, RRDSET_TYPE_STACKED); - rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL); - rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL); + rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); diff --git a/src/sys_kernel_mm_ksm.c b/src/sys_kernel_mm_ksm.c index 4998b010..76d80853 100644 --- a/src/sys_kernel_mm_ksm.c +++ b/src/sys_kernel_mm_ksm.c @@ -90,15 +90,16 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { // -------------------------------------------------------------------- - st = rrdset_find("mem.ksm"); + st = rrdset_find_localhost("mem.ksm"); if(!st) { - st = rrdset_create("mem", "ksm", NULL, "ksm", NULL, "Kernel Same Page Merging", "MB", 5000, update_every, RRDSET_TYPE_AREA); - - rrddim_add(st, "shared", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "unshared", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "sharing", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "volatile", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "to_scan", "to scan", -1, 1024 * 1024, RRDDIM_ABSOLUTE); + st = rrdset_create_localhost("mem", "ksm", NULL, "ksm", NULL, "Kernel Same Page Merging", "MB", 5000 + , update_every, RRDSET_TYPE_AREA); + + rrddim_add(st, "shared", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "unshared", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "sharing", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "volatile", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "to_scan", "to scan", -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -109,12 +110,13 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { rrddim_set(st, "to_scan", pages_to_scan * page_size); rrdset_done(st); - st = rrdset_find("mem.ksm_savings"); + st = rrdset_find_localhost("mem.ksm_savings"); if(!st) { - st = rrdset_create("mem", "ksm_savings", NULL, "ksm", NULL, "Kernel Same Page Merging Savings", "MB", 5001, update_every, RRDSET_TYPE_AREA); + st = rrdset_create_localhost("mem", "ksm_savings", NULL, "ksm", NULL, "Kernel Same Page Merging Savings", "MB" + , 5001, update_every, RRDSET_TYPE_AREA); - rrddim_add(st, "savings", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE); - rrddim_add(st, "offered", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE); + rrddim_add(st, "savings", NULL, -1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); + rrddim_add(st, "offered", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); @@ -122,11 +124,12 @@ int do_sys_kernel_mm_ksm(int update_every, usec_t dt) { rrddim_set(st, "offered", offered * page_size); rrdset_done(st); - st = rrdset_find("mem.ksm_ratios"); + st = rrdset_find_localhost("mem.ksm_ratios"); if(!st) { - st = rrdset_create("mem", "ksm_ratios", NULL, "ksm", NULL, "Kernel Same Page Merging Effectiveness", "percentage", 5002, update_every, RRDSET_TYPE_LINE); + st = rrdset_create_localhost("mem", "ksm_ratios", NULL, "ksm", NULL, "Kernel Same Page Merging Effectiveness" + , "percentage", 5002, update_every, RRDSET_TYPE_LINE); - rrddim_add(st, "savings", NULL, 1, 10000, RRDDIM_ABSOLUTE); + rrddim_add(st, "savings", NULL, 1, 10000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); diff --git a/src/unit_test.c b/src/unit_test.c index 4e2f10c0..0866d215 100644 --- a/src/unit_test.c +++ b/src/unit_test.c @@ -282,7 +282,7 @@ struct test test1 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_ABSOLUTE, // algorithm + RRD_ALGORITHM_ABSOLUTE, // algorithm 10, // feed entries 9, // result entries test1_feed, // feed @@ -318,7 +318,7 @@ struct test test2 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_ABSOLUTE, // algorithm + RRD_ALGORITHM_ABSOLUTE, // algorithm 10, // feed entries 9, // result entries test2_feed, // feed @@ -353,7 +353,7 @@ struct test test3 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 9, // result entries test3_feed, // feed @@ -388,7 +388,7 @@ struct test test4 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 9, // result entries test4_feed, // feed @@ -423,7 +423,7 @@ struct test test5 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 9, // result entries test5_feed, // feed @@ -464,7 +464,7 @@ struct test test6 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 16, // feed entries 4, // result entries test6_feed, // feed @@ -499,7 +499,7 @@ struct test test7 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 18, // result entries test7_feed, // feed @@ -530,7 +530,7 @@ struct test test8 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_ABSOLUTE, // algorithm + RRD_ALGORITHM_ABSOLUTE, // algorithm 6, // feed entries 10, // result entries test8_feed, // feed @@ -571,7 +571,7 @@ struct test test9 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_ABSOLUTE, // algorithm + RRD_ALGORITHM_ABSOLUTE, // algorithm 16, // feed entries 4, // result entries test9_feed, // feed @@ -606,7 +606,7 @@ struct test test10 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 7, // result entries test10_feed, // feed @@ -649,7 +649,7 @@ struct test test11 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm + RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm 10, // feed entries 9, // result entries test11_feed, // feed @@ -692,7 +692,7 @@ struct test test12 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm + RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm 10, // feed entries 9, // result entries test12_feed, // feed @@ -727,7 +727,7 @@ struct test test13 = { 1, // update_every 1, // multiplier 1, // divisor - RRDDIM_PCENT_OVER_DIFF_TOTAL, // algorithm + RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL, // algorithm 10, // feed entries 7, // result entries test13_feed, // feed @@ -762,7 +762,7 @@ struct test test14 = { 30, // update_every 8, // multiplier 1000000000, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 8, // result entries test14_feed, // feed @@ -794,7 +794,7 @@ struct test test14b = { 30, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 8, // result entries test14b_feed, // feed @@ -826,7 +826,7 @@ struct test test14c = { 30, // update_every 1, // multiplier 1, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 9, // result entries test14c_feed, // feed @@ -869,7 +869,7 @@ struct test test15 = { 1, // update_every 8, // multiplier 1024, // divisor - RRDDIM_INCREMENTAL, // algorithm + RRD_ALGORITHM_INCREMENTAL, // algorithm 10, // feed entries 9, // result entries test15_feed, // feed @@ -884,21 +884,22 @@ int run_test(struct test *test) { fprintf(stderr, "\nRunning test '%s':\n%s\n", test->name, test->description); - rrd_memory_mode = RRD_MEMORY_MODE_RAM; - rrd_update_every = test->update_every; + default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; + default_rrd_update_every = test->update_every; char name[101]; snprintfz(name, 100, "unittest-%s", test->name); // create the chart - RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, test->update_every, RRDSET_TYPE_LINE); + RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1 + , test->update_every, RRDSET_TYPE_LINE); RRDDIM *rd = rrddim_add(st, "dim1", NULL, test->multiplier, test->divisor, test->algorithm); RRDDIM *rd2 = NULL; if(test->feed2) rd2 = rrddim_add(st, "dim2", NULL, test->multiplier, test->divisor, test->algorithm); - st->debug = 1; + rrdset_flag_set(st, RRDSET_FLAG_DEBUG); // feed it with the test data time_t time_now = 0, time_start = now_realtime_sec(); @@ -977,15 +978,16 @@ int run_test(struct test *test) static int test_variable_renames(void) { fprintf(stderr, "Creating chart\n"); - RRDSET *st = rrdset_create("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE); + RRDSET *st = rrdset_create_localhost("chart", "ID", NULL, "family", "context", "Unit Testing", "a value", 1, 1 + , RRDSET_TYPE_LINE); fprintf(stderr, "Created chart with id '%s', name '%s'\n", st->id, st->name); fprintf(stderr, "Creating dimension DIM1\n"); - RRDDIM *rd1 = rrddim_add(st, "DIM1", NULL, 1, 1, RRDDIM_INCREMENTAL); + RRDDIM *rd1 = rrddim_add(st, "DIM1", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd1->id, rd1->name); fprintf(stderr, "Creating dimension DIM2\n"); - RRDDIM *rd2 = rrddim_add(st, "DIM2", NULL, 1, 1, RRDDIM_INCREMENTAL); + RRDDIM *rd2 = rrddim_add(st, "DIM2", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); fprintf(stderr, "Created dimension with id '%s', name '%s'\n", rd2->id, rd2->name); fprintf(stderr, "Renaming chart to CHARTNAME1\n"); @@ -1089,26 +1091,27 @@ int unit_test(long delay, long shift) snprintfz(name, 100, "unittest-%d-%ld-%ld", repeat, delay, shift); //debug_flags = 0xffffffff; - rrd_memory_mode = RRD_MEMORY_MODE_RAM; - rrd_update_every = 1; + default_rrd_memory_mode = RRD_MEMORY_MODE_RAM; + default_rrd_update_every = 1; int do_abs = 1; int do_inc = 1; int do_abst = 0; int do_absi = 0; - RRDSET *st = rrdset_create("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1, RRDSET_TYPE_LINE); - st->debug = 1; + RRDSET *st = rrdset_create_localhost("netdata", name, name, "netdata", NULL, "Unit Testing", "a value", 1, 1 + , RRDSET_TYPE_LINE); + rrdset_flag_set(st, RRDSET_FLAG_DEBUG); RRDDIM *rdabs = NULL; RRDDIM *rdinc = NULL; RRDDIM *rdabst = NULL; RRDDIM *rdabsi = NULL; - if(do_abs) rdabs = rrddim_add(st, "absolute", "absolute", 1, 1, RRDDIM_ABSOLUTE); - if(do_inc) rdinc = rrddim_add(st, "incremental", "incremental", 1, 1, RRDDIM_INCREMENTAL); - if(do_abst) rdabst = rrddim_add(st, "percentage-of-absolute-row", "percentage-of-absolute-row", 1, 1, RRDDIM_PCENT_OVER_ROW_TOTAL); - if(do_absi) rdabsi = rrddim_add(st, "percentage-of-incremental-row", "percentage-of-incremental-row", 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); + if(do_abs) rdabs = rrddim_add(st, "absolute", "absolute", 1, 1, RRD_ALGORITHM_ABSOLUTE); + if(do_inc) rdinc = rrddim_add(st, "incremental", "incremental", 1, 1, RRD_ALGORITHM_INCREMENTAL); + if(do_abst) rdabst = rrddim_add(st, "percentage-of-absolute-row", "percentage-of-absolute-row", 1, 1, RRD_ALGORITHM_PCENT_OVER_ROW_TOTAL); + if(do_absi) rdabsi = rrddim_add(st, "percentage-of-incremental-row", "percentage-of-incremental-row", 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL); long increment = 1000; collected_number i = 0; diff --git a/src/web_api_old.c b/src/web_api_old.c new file mode 100644 index 00000000..127536ec --- /dev/null +++ b/src/web_api_old.c @@ -0,0 +1,231 @@ +#include "common.h" + +int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type) { + if(!url || !*url) { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Incomplete request."); + return 400; + } + + RRDSET *st = NULL; + + char *args = strchr(url, '?'); + if(args) { + *args='\0'; + args = &args[1]; + } + + // get the name of the data to show + char *tok = mystrsep(&url, "/"); + if(!tok) tok = ""; + + // do we have such a data set? + if(*tok) { + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); + st = rrdset_find_byname(host, tok); + if(!st) st = rrdset_find(host, tok); + } + + if(!st) { + // we don't have it + // try to send a file with that name + buffer_flush(w->response.data); + return(mysendfile(w, tok)); + } + + // we have it + debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok); + + // how many entries does the client want? + int lines = (int)st->entries; + int group_count = 1; + time_t after = 0, before = 0; + int group_method = GROUP_AVERAGE; + int nonzero = 0; + + if(url) { + // parse the lines required + tok = mystrsep(&url, "/"); + if(tok) lines = str2i(tok); + if(lines < 1) lines = 1; + } + if(url) { + // parse the group count required + tok = mystrsep(&url, "/"); + if(tok && *tok) group_count = str2i(tok); + if(group_count < 1) group_count = 1; + //if(group_count > save_history / 20) group_count = save_history / 20; + } + if(url) { + // parse the grouping method required + tok = mystrsep(&url, "/"); + if(tok && *tok) { + if(strcmp(tok, "max") == 0) group_method = GROUP_MAX; + else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE; + else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM; + else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok); + } + } + if(url) { + // parse after time + tok = mystrsep(&url, "/"); + if(tok && *tok) after = str2ul(tok); + if(after < 0) after = 0; + } + if(url) { + // parse before time + tok = mystrsep(&url, "/"); + if(tok && *tok) before = str2ul(tok); + if(before < 0) before = 0; + } + if(url) { + // parse nonzero + tok = mystrsep(&url, "/"); + if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1; + } + + w->response.data->contenttype = CT_APPLICATION_JSON; + buffer_flush(w->response.data); + + char *google_version = "0.6"; + char *google_reqId = "0"; + char *google_sig = "0"; + char *google_out = "json"; + char *google_responseHandler = "google.visualization.Query.setResponse"; + char *google_outFileName = NULL; + time_t last_timestamp_in_data = 0; + if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) { + + w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT; + + while(args) { + tok = mystrsep(&args, "&"); + if(tok && *tok) { + char *name = mystrsep(&tok, "="); + if(name && *name && strcmp(name, "tqx") == 0) { + char *key = mystrsep(&tok, ":"); + char *value = mystrsep(&tok, ";"); + if(key && value && *key && *value) { + if(strcmp(key, "version") == 0) + google_version = value; + + else if(strcmp(key, "reqId") == 0) + google_reqId = value; + + else if(strcmp(key, "sig") == 0) + google_sig = value; + + else if(strcmp(key, "out") == 0) + google_out = value; + + else if(strcmp(key, "responseHandler") == 0) + google_responseHandler = value; + + else if(strcmp(key, "outFileName") == 0) + google_outFileName = value; + } + } + } + } + + debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'", + w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName + ); + + if(datasource_type == DATASOURCE_DATATABLE_JSONP) { + last_timestamp_in_data = strtoul(google_sig, NULL, 0); + + // check the client wants json + if(strcmp(google_out, "json") != 0) { + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});", + google_responseHandler, google_version, google_reqId, google_out); + return 200; + } + } + } + + if(datasource_type == DATASOURCE_DATATABLE_JSONP) { + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:", + google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec); + } + + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).", + w->id, st->name, st->id, lines, group_count, group_method, after, before); + + time_t timestamp_in_data = rrd_stats_json(datasource_type, st, w->response.data, lines, group_count, group_method, (unsigned long)after, (unsigned long)before, nonzero); + + if(datasource_type == DATASOURCE_DATATABLE_JSONP) { + if(timestamp_in_data > last_timestamp_in_data) + buffer_strcat(w->response.data, "});"); + + else { + // the client already has the latest data + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});", + google_responseHandler, google_version, google_reqId); + } + } + + return 200; +} + +inline int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url) { + return web_client_api_old_data_request(host, w, url, DATASOURCE_JSON); +} + +inline int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url) { + return web_client_api_old_data_request(host, w, url, DATASOURCE_DATATABLE_JSONP); +} + +inline int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url) { + // get the name of the data to show + char *tok = mystrsep(&url, "/?&"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); + + // do we have such a data set? + RRDSET *st = rrdset_find_byname(host, tok); + if(!st) st = rrdset_find(host, tok); + if(!st) { + // we don't have it + // try to send a file with that name + buffer_flush(w->response.data); + return mysendfile(w, tok); + } + + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name); + w->response.data->contenttype = CT_APPLICATION_JSON; + buffer_flush(w->response.data); + rrd_stats_graph_json(st, url, w->response.data); + return 200; + } + + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Graph name?\r\n"); + return 400; +} + +inline int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url) { + (void)url; + + buffer_flush(w->response.data); + RRDSET *st; + + rrdhost_rdlock(host); + rrdset_foreach_read(st, host) buffer_sprintf(w->response.data, "%s\n", st->name); + rrdhost_unlock(host); + + return 200; +} + +inline int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url) { + (void)url; + + w->response.data->contenttype = CT_APPLICATION_JSON; + buffer_flush(w->response.data); + rrd_stats_all_json(host, w->response.data); + return 200; +} diff --git a/src/web_api_old.h b/src/web_api_old.h new file mode 100644 index 00000000..dff48c2f --- /dev/null +++ b/src/web_api_old.h @@ -0,0 +1,13 @@ +#ifndef NETDATA_WEB_API_OLD_H +#define NETDATA_WEB_API_OLD_H + +#include "common.h" + +extern int web_client_api_old_data_request(RRDHOST *host, struct web_client *w, char *url, int datasource_type); +extern int web_client_api_old_data_request_json(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_old_data_request_jsonp(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_old_graph_request(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_old_list_request(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_old_all_json(RRDHOST *host, struct web_client *w, char *url); + +#endif //NETDATA_WEB_API_OLD_H diff --git a/src/web_api_v1.c b/src/web_api_v1.c new file mode 100644 index 00000000..c180cf39 --- /dev/null +++ b/src/web_api_v1.c @@ -0,0 +1,902 @@ +#include "common.h" + +inline int web_client_api_request_v1_data_group(char *name, int def) { + if(!strcmp(name, "average")) + return GROUP_AVERAGE; + + else if(!strcmp(name, "min")) + return GROUP_MIN; + + else if(!strcmp(name, "max")) + return GROUP_MAX; + + else if(!strcmp(name, "sum")) + return GROUP_SUM; + + else if(!strcmp(name, "incremental-sum")) + return GROUP_INCREMENTAL_SUM; + + return def; +} + +inline uint32_t web_client_api_request_v1_data_options(char *o) { + uint32_t ret = 0x00000000; + char *tok; + + while(o && *o && (tok = mystrsep(&o, ", |"))) { + if(!*tok) continue; + + if(!strcmp(tok, "nonzero")) + ret |= RRDR_OPTION_NONZERO; + else if(!strcmp(tok, "flip") || !strcmp(tok, "reversed") || !strcmp(tok, "reverse")) + ret |= RRDR_OPTION_REVERSED; + else if(!strcmp(tok, "jsonwrap")) + ret |= RRDR_OPTION_JSON_WRAP; + else if(!strcmp(tok, "min2max")) + ret |= RRDR_OPTION_MIN2MAX; + else if(!strcmp(tok, "ms") || !strcmp(tok, "milliseconds")) + ret |= RRDR_OPTION_MILLISECONDS; + else if(!strcmp(tok, "abs") || !strcmp(tok, "absolute") || !strcmp(tok, "absolute_sum") || !strcmp(tok, "absolute-sum")) + ret |= RRDR_OPTION_ABSOLUTE; + else if(!strcmp(tok, "seconds")) + ret |= RRDR_OPTION_SECONDS; + else if(!strcmp(tok, "null2zero")) + ret |= RRDR_OPTION_NULL2ZERO; + else if(!strcmp(tok, "objectrows")) + ret |= RRDR_OPTION_OBJECTSROWS; + else if(!strcmp(tok, "google_json")) + ret |= RRDR_OPTION_GOOGLE_JSON; + else if(!strcmp(tok, "percentage")) + ret |= RRDR_OPTION_PERCENTAGE; + else if(!strcmp(tok, "unaligned")) + ret |= RRDR_OPTION_NOT_ALIGNED; + } + + return ret; +} + +inline uint32_t web_client_api_request_v1_data_format(char *name) { + if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSON)) // datatable + return DATASOURCE_DATATABLE_JSON; + + else if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSONP)) // datasource + return DATASOURCE_DATATABLE_JSONP; + + else if(!strcmp(name, DATASOURCE_FORMAT_JSON)) // json + return DATASOURCE_JSON; + + else if(!strcmp(name, DATASOURCE_FORMAT_JSONP)) // jsonp + return DATASOURCE_JSONP; + + else if(!strcmp(name, DATASOURCE_FORMAT_SSV)) // ssv + return DATASOURCE_SSV; + + else if(!strcmp(name, DATASOURCE_FORMAT_CSV)) // csv + return DATASOURCE_CSV; + + else if(!strcmp(name, DATASOURCE_FORMAT_TSV) || !strcmp(name, "tsv-excel")) // tsv + return DATASOURCE_TSV; + + else if(!strcmp(name, DATASOURCE_FORMAT_HTML)) // html + return DATASOURCE_HTML; + + else if(!strcmp(name, DATASOURCE_FORMAT_JS_ARRAY)) // array + return DATASOURCE_JS_ARRAY; + + else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma + return DATASOURCE_SSV_COMMA; + + else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray + return DATASOURCE_CSV_JSON_ARRAY; + + return DATASOURCE_JSON; +} + +inline uint32_t web_client_api_request_v1_data_google_format(char *name) { + if(!strcmp(name, "json")) + return DATASOURCE_DATATABLE_JSONP; + + else if(!strcmp(name, "html")) + return DATASOURCE_HTML; + + else if(!strcmp(name, "csv")) + return DATASOURCE_CSV; + + else if(!strcmp(name, "tsv-excel")) + return DATASOURCE_TSV; + + return DATASOURCE_JSON; +} + + +inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) { + int all = 0; + + while(url) { + char *value = mystrsep(&url, "?&"); + if (!value || !*value) continue; + + if(!strcmp(value, "all")) all = 1; + else if(!strcmp(value, "active")) all = 0; + } + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + health_alarms2json(host, w->response.data, all); + return 200; +} + +inline int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url) { + uint32_t after = 0; + + while(url) { + char *value = mystrsep(&url, "?&"); + if (!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + if(!strcmp(name, "after")) after = (uint32_t)strtoul(value, NULL, 0); + } + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + health_alarm_log2json(host, w->response.data, after); + return 200; +} + +inline int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) { + int ret = 400; + char *chart = NULL; + + buffer_flush(w->response.data); + + while(url) { + char *value = mystrsep(&url, "?&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + //else { + /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name); + // goto cleanup; + //} + } + + if(!chart || !*chart) { + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, chart); + ret = 404; + goto cleanup; + } + + w->response.data->contenttype = CT_APPLICATION_JSON; + callback(st, w->response.data); + return 200; + + cleanup: + return ret; +} + +inline int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url) { + return web_client_api_request_single_chart(host, w, url, health_api_v1_chart_variables2json); +} + +inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url) { + (void)url; + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + rrd_stats_api_v1_charts(host, w->response.data); + return 200; +} + +inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) { + int format = ALLMETRICS_SHELL; + + while(url) { + char *value = mystrsep(&url, "?&"); + if (!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + if(!strcmp(name, "format")) { + if(!strcmp(value, ALLMETRICS_FORMAT_SHELL)) + format = ALLMETRICS_SHELL; + else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS)) + format = ALLMETRICS_PROMETHEUS; + else + format = 0; + } + } + + buffer_flush(w->response.data); + buffer_no_cacheable(w->response.data); + + switch(format) { + case ALLMETRICS_SHELL: + w->response.data->contenttype = CT_TEXT_PLAIN; + rrd_stats_api_v1_charts_allmetrics_shell(host, w->response.data); + return 200; + + case ALLMETRICS_PROMETHEUS: + w->response.data->contenttype = CT_PROMETHEUS; + rrd_stats_api_v1_charts_allmetrics_prometheus(host, w->response.data); + return 200; + + default: + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_strcat(w->response.data, "Which format? Only '" ALLMETRICS_FORMAT_SHELL "' and '" ALLMETRICS_FORMAT_PROMETHEUS "' is currently supported."); + return 400; + } +} + +inline int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url) { + return web_client_api_request_single_chart(host, w, url, rrd_stats_api_v1_chart); +} + +int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) { + int ret = 400; + buffer_flush(w->response.data); + + BUFFER *dimensions = NULL; + + const char *chart = NULL + , *before_str = NULL + , *after_str = NULL + , *points_str = NULL + , *multiply_str = NULL + , *divide_str = NULL + , *label = NULL + , *units = NULL + , *label_color = NULL + , *value_color = NULL + , *refresh_str = NULL + , *precision_str = NULL + , *alarm = NULL; + + int group = GROUP_AVERAGE; + uint32_t options = 0x00000000; + + while(url) { + char *value = mystrsep(&url, "/?&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value); + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { + if(!dimensions) + dimensions = buffer_create(100); + + buffer_strcat(dimensions, "|"); + buffer_strcat(dimensions, value); + } + else if(!strcmp(name, "after")) after_str = value; + else if(!strcmp(name, "before")) before_str = value; + else if(!strcmp(name, "points")) points_str = value; + else if(!strcmp(name, "group")) { + group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE); + } + else if(!strcmp(name, "options")) { + options |= web_client_api_request_v1_data_options(value); + } + else if(!strcmp(name, "label")) label = value; + else if(!strcmp(name, "units")) units = value; + else if(!strcmp(name, "label_color")) label_color = value; + else if(!strcmp(name, "value_color")) value_color = value; + else if(!strcmp(name, "multiply")) multiply_str = value; + else if(!strcmp(name, "divide")) divide_str = value; + else if(!strcmp(name, "refresh")) refresh_str = value; + else if(!strcmp(name, "precision")) precision_str = value; + else if(!strcmp(name, "alarm")) alarm = value; + } + + if(!chart || !*chart) { + buffer_no_cacheable(w->response.data); + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_no_cacheable(w->response.data); + buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1); + ret = 200; + goto cleanup; + } + + RRDCALC *rc = NULL; + if(alarm) { + rc = rrdcalc_find(st, alarm); + if (!rc) { + buffer_no_cacheable(w->response.data); + buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1); + ret = 200; + goto cleanup; + } + } + + long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1; + long long divide = (divide_str && *divide_str )?str2l(divide_str):1; + long long before = (before_str && *before_str )?str2l(before_str):0; + long long after = (after_str && *after_str )?str2l(after_str):-st->update_every; + int points = (points_str && *points_str )?str2i(points_str):1; + int precision = (precision_str && *precision_str)?str2i(precision_str):-1; + + if(!multiply) multiply = 1; + if(!divide) divide = 1; + + int refresh = 0; + if(refresh_str && *refresh_str) { + if(!strcmp(refresh_str, "auto")) { + if(rc) refresh = rc->update_every; + else if(options & RRDR_OPTION_NOT_ALIGNED) + refresh = st->update_every; + else { + refresh = (int)(before - after); + if(refresh < 0) refresh = -refresh; + } + } + else { + refresh = str2i(refresh_str); + if(refresh < 0) refresh = -refresh; + } + } + + if(!label) { + if(alarm) { + char *s = (char *)alarm; + while(*s) { + if(*s == '_') *s = ' '; + s++; + } + label = alarm; + } + else if(dimensions) { + const char *dim = buffer_tostring(dimensions); + if(*dim == '|') dim++; + label = dim; + } + else + label = st->name; + } + if(!units) { + if(alarm) { + if(rc->units) + units = rc->units; + else + units = ""; + } + else if(options & RRDR_OPTION_PERCENTAGE) + units = "%"; + else + units = st->units; + } + + debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" + , w->id + , chart + , alarm?alarm:"" + , (dimensions)?buffer_tostring(dimensions):"" + , after + , before + , points + , group + , options + ); + + if(rc) { + if (refresh > 0) { + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + w->response.data->expires = now_realtime_sec() + refresh; + } + else buffer_no_cacheable(w->response.data); + + if(!value_color) { + switch(rc->status) { + case RRDCALC_STATUS_CRITICAL: + value_color = "red"; + break; + + case RRDCALC_STATUS_WARNING: + value_color = "orange"; + break; + + case RRDCALC_STATUS_CLEAR: + value_color = "brightgreen"; + break; + + case RRDCALC_STATUS_UNDEFINED: + value_color = "lightgrey"; + break; + + case RRDCALC_STATUS_UNINITIALIZED: + value_color = "#000"; + break; + + default: + value_color = "grey"; + break; + } + } + + buffer_svg(w->response.data, + label, + (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide, + units, + label_color, + value_color, + precision); + ret = 200; + } + else { + time_t latest_timestamp = 0; + int value_is_null = 1; + calculated_number n = NAN; + ret = 500; + + // if the collected value is too old, don't calculate its value + if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above))) + ret = rrd2value(st, + w->response.data, + &n, + (dimensions) ? buffer_tostring(dimensions) : NULL, + points, + after, + before, + group, + options, + NULL, + &latest_timestamp, + &value_is_null); + + // if the value cannot be calculated, show empty badge + if (ret != 200) { + buffer_no_cacheable(w->response.data); + value_is_null = 1; + n = 0; + ret = 200; + } + else if (refresh > 0) { + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + w->response.data->expires = now_realtime_sec() + refresh; + } + else buffer_no_cacheable(w->response.data); + + // render the badge + buffer_svg(w->response.data, + label, + (value_is_null)?NAN:(n * multiply / divide), + units, + label_color, + value_color, + precision); + } + + cleanup: + buffer_free(dimensions); + return ret; +} + +// returns the HTTP code +inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) { + debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url); + + int ret = 400; + BUFFER *dimensions = NULL; + + buffer_flush(w->response.data); + + char *google_version = "0.6", + *google_reqId = "0", + *google_sig = "0", + *google_out = "json", + *responseHandler = NULL, + *outFileName = NULL; + + time_t last_timestamp_in_data = 0, google_timestamp = 0; + + char *chart = NULL + , *before_str = NULL + , *after_str = NULL + , *points_str = NULL; + + int group = GROUP_AVERAGE; + uint32_t format = DATASOURCE_JSON; + uint32_t options = 0x00000000; + + while(url) { + char *value = mystrsep(&url, "?&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value); + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { + if(!dimensions) dimensions = buffer_create(100); + buffer_strcat(dimensions, "|"); + buffer_strcat(dimensions, value); + } + else if(!strcmp(name, "after")) after_str = value; + else if(!strcmp(name, "before")) before_str = value; + else if(!strcmp(name, "points")) points_str = value; + else if(!strcmp(name, "group")) { + group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE); + } + else if(!strcmp(name, "format")) { + format = web_client_api_request_v1_data_format(value); + } + else if(!strcmp(name, "options")) { + options |= web_client_api_request_v1_data_options(value); + } + else if(!strcmp(name, "callback")) { + responseHandler = value; + } + else if(!strcmp(name, "filename")) { + outFileName = value; + } + else if(!strcmp(name, "tqx")) { + // parse Google Visualization API options + // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source + char *tqx_name, *tqx_value; + + while(value) { + tqx_value = mystrsep(&value, ";"); + if(!tqx_value || !*tqx_value) continue; + + tqx_name = mystrsep(&tqx_value, ":"); + if(!tqx_name || !*tqx_name) continue; + if(!tqx_value || !*tqx_value) continue; + + if(!strcmp(tqx_name, "version")) + google_version = tqx_value; + else if(!strcmp(tqx_name, "reqId")) + google_reqId = tqx_value; + else if(!strcmp(tqx_name, "sig")) { + google_sig = tqx_value; + google_timestamp = strtoul(google_sig, NULL, 0); + } + else if(!strcmp(tqx_name, "out")) { + google_out = tqx_value; + format = web_client_api_request_v1_data_google_format(google_out); + } + else if(!strcmp(tqx_name, "responseHandler")) + responseHandler = tqx_value; + else if(!strcmp(tqx_name, "outFileName")) + outFileName = tqx_value; + } + } + } + + if(!chart || !*chart) { + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, chart); + ret = 404; + goto cleanup; + } + + long long before = (before_str && *before_str)?str2l(before_str):0; + long long after = (after_str && *after_str) ?str2l(after_str):0; + int points = (points_str && *points_str)?str2i(points_str):0; + + debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'" + , w->id + , chart + , (dimensions)?buffer_tostring(dimensions):"" + , after + , before + , points + , group + , format + , options + ); + + if(outFileName && *outFileName) { + buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName); + debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName); + } + + if(format == DATASOURCE_DATATABLE_JSONP) { + if(responseHandler == NULL) + responseHandler = "google.visualization.Query.setResponse"; + + debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'", + w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName + ); + + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:", + responseHandler, google_version, google_reqId, st->last_updated.tv_sec); + } + else if(format == DATASOURCE_JSONP) { + if(responseHandler == NULL) + responseHandler = "callback"; + + buffer_strcat(w->response.data, responseHandler); + buffer_strcat(w->response.data, "("); + } + + ret = rrd2format(st, w->response.data, dimensions, format, points, after, before, group, options, &last_timestamp_in_data); + + if(format == DATASOURCE_DATATABLE_JSONP) { + if(google_timestamp < last_timestamp_in_data) + buffer_strcat(w->response.data, "});"); + + else { + // the client already has the latest data + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});", + responseHandler, google_version, google_reqId); + } + } + else if(format == DATASOURCE_JSONP) + buffer_strcat(w->response.data, ");"); + + cleanup: + buffer_free(dimensions); + return ret; +} + +inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url) { + static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0, + hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0, + hash_to = 0 /*, hash_redirects = 0 */; + + if(unlikely(!hash_action)) { + hash_action = simple_hash("action"); + hash_access = simple_hash("access"); + hash_hello = simple_hash("hello"); + hash_delete = simple_hash("delete"); + hash_search = simple_hash("search"); + hash_switch = simple_hash("switch"); + hash_machine = simple_hash("machine"); + hash_url = simple_hash("url"); + hash_name = simple_hash("name"); + hash_delete_url = simple_hash("delete_url"); + hash_for = simple_hash("for"); + hash_to = simple_hash("to"); +/* + hash_redirects = simple_hash("redirects"); +*/ + } + + char person_guid[GUID_LEN + 1] = ""; + + debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url); + + // FIXME + // The browser may send multiple cookies with our id + + char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "="); + if(cookie) + strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36); + + char action = '\0'; + char *machine_guid = NULL, + *machine_url = NULL, + *url_name = NULL, + *search_machine_guid = NULL, + *delete_url = NULL, + *to_person_guid = NULL; +/* + int redirects = 0; +*/ + + while(url) { + char *value = mystrsep(&url, "?&"); + if (!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if (!name || !*name) continue; + if (!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value); + + uint32_t hash = simple_hash(name); + + if(hash == hash_action && !strcmp(name, "action")) { + uint32_t vhash = simple_hash(value); + + if(vhash == hash_access && !strcmp(value, "access")) action = 'A'; + else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H'; + else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D'; + else if(vhash == hash_search && !strcmp(value, "search")) action = 'S'; + else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W'; +#ifdef NETDATA_INTERNAL_CHECKS + else error("unknown registry action '%s'", value); +#endif /* NETDATA_INTERNAL_CHECKS */ + } +/* + else if(hash == hash_redirects && !strcmp(name, "redirects")) + redirects = atoi(value); +*/ + else if(hash == hash_machine && !strcmp(name, "machine")) + machine_guid = value; + + else if(hash == hash_url && !strcmp(name, "url")) + machine_url = value; + + else if(action == 'A') { + if(hash == hash_name && !strcmp(name, "name")) + url_name = value; + } + else if(action == 'D') { + if(hash == hash_delete_url && !strcmp(name, "delete_url")) + delete_url = value; + } + else if(action == 'S') { + if(hash == hash_for && !strcmp(name, "for")) + search_machine_guid = value; + } + else if(action == 'W') { + if(hash == hash_to && !strcmp(name, "to")) + to_person_guid = value; + } +#ifdef NETDATA_INTERNAL_CHECKS + else error("unused registry URL parameter '%s' with value '%s'", name, value); +#endif /* NETDATA_INTERNAL_CHECKS */ + } + + if(respect_web_browser_do_not_track_policy && w->donottrack) { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work."); + return 400; + } + + if(action == 'A' && (!machine_guid || !machine_url || !url_name)) { + error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", + machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Access request."); + return 400; + } + else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) { + error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", + machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Delete request."); + return 400; + } + else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) { + error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", + machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Search request."); + return 400; + } + else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) { + error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", + machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Switch request."); + return 400; + } + + switch(action) { + case 'A': + w->tracking_required = 1; + return registry_request_access_json(host, w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec()); + + case 'D': + w->tracking_required = 1; + return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec()); + + case 'S': + w->tracking_required = 1; + return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec()); + + case 'W': + w->tracking_required = 1; + return registry_request_switch_json(host, w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec()); + + case 'H': + return registry_request_hello_json(host, w); + + default: + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search"); + return 400; + } +} + +inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url) { + static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0, hash_alarm_variables = 0, hash_raw = 0; + + if(unlikely(hash_data == 0)) { + hash_data = simple_hash("data"); + hash_chart = simple_hash("chart"); + hash_charts = simple_hash("charts"); + hash_registry = simple_hash("registry"); + hash_badge = simple_hash("badge.svg"); + hash_alarms = simple_hash("alarms"); + hash_alarm_log = simple_hash("alarm_log"); + hash_alarm_variables = simple_hash("alarm_variables"); + hash_raw = simple_hash("allmetrics"); + } + + // get the command + char *tok = mystrsep(&url, "/?&"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok); + uint32_t hash = simple_hash(tok); + + if(hash == hash_data && !strcmp(tok, "data")) + return web_client_api_request_v1_data(host, w, url); + + else if(hash == hash_chart && !strcmp(tok, "chart")) + return web_client_api_request_v1_chart(host, w, url); + + else if(hash == hash_charts && !strcmp(tok, "charts")) + return web_client_api_request_v1_charts(host, w, url); + + else if(hash == hash_registry && !strcmp(tok, "registry")) + return web_client_api_request_v1_registry(host, w, url); + + else if(hash == hash_badge && !strcmp(tok, "badge.svg")) + return web_client_api_request_v1_badge(host, w, url); + + else if(hash == hash_alarms && !strcmp(tok, "alarms")) + return web_client_api_request_v1_alarms(host, w, url); + + else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log")) + return web_client_api_request_v1_alarm_log(host, w, url); + + else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables")) + return web_client_api_request_v1_alarm_variables(host, w, url); + + else if(hash == hash_raw && !strcmp(tok, "allmetrics")) + return web_client_api_request_v1_allmetrics(host, w, url); + + else { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Unsupported v1 API command: "); + buffer_strcat_htmlescape(w->response.data, tok); + return 404; + } + } + else { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Which API v1 command?"); + return 400; + } +} diff --git a/src/web_api_v1.h b/src/web_api_v1.h new file mode 100644 index 00000000..e980edb1 --- /dev/null +++ b/src/web_api_v1.h @@ -0,0 +1,21 @@ +#ifndef NETDATA_WEB_API_V1_H +#define NETDATA_WEB_API_V1_H + +extern int web_client_api_request_v1_data_group(char *name, int def); +extern uint32_t web_client_api_request_v1_data_options(char *o); +extern uint32_t web_client_api_request_v1_data_format(char *name); +extern uint32_t web_client_api_request_v1_data_google_format(char *name); + +extern int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)); +extern int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url); + +#endif //NETDATA_WEB_API_V1_H diff --git a/src/web_buffer.c b/src/web_buffer.c index 6203db0f..9f9ceda6 100644 --- a/src/web_buffer.c +++ b/src/web_buffer.c @@ -359,8 +359,9 @@ BUFFER *buffer_create(size_t size) return(b); } -void buffer_free(BUFFER *b) -{ +void buffer_free(BUFFER *b) { + if(unlikely(!b)) return; + buffer_overflow_check(b); debug(D_WEB_BUFFER, "Freeing web buffer of size %zu.", b->size); diff --git a/src/web_client.c b/src/web_client.c index 9a9e2376..908e72a3 100644 --- a/src/web_client.c +++ b/src/web_client.c @@ -45,8 +45,7 @@ static inline int web_client_uncrock_socket(struct web_client *w) { return 0; } -struct web_client *web_client_create(int listener) -{ +struct web_client *web_client_create(int listener) { struct web_client *w; w = callocz(1, sizeof(struct web_client)); @@ -223,9 +222,9 @@ struct web_client *web_client_free(struct web_client *w) { if(w->prev) w->prev->next = w->next; if(w->next) w->next->prev = w->prev; - if(w->response.header_output) buffer_free(w->response.header_output); - if(w->response.header) buffer_free(w->response.header); - if(w->response.data) buffer_free(w->response.data); + buffer_free(w->response.header_output); + buffer_free(w->response.header); + buffer_free(w->response.data); if(w->ifd != -1) close(w->ifd); if(w->ofd != -1 && w->ofd != w->ifd) close(w->ofd); freez(w); @@ -240,7 +239,7 @@ uid_t web_files_uid(void) { static uid_t owner_uid = 0; if(unlikely(!web_owner)) { - web_owner = config_get("global", "web files owner", config_get("global", "run as user", "")); + web_owner = config_get(CONFIG_SECTION_WEB, "web files owner", config_get(CONFIG_SECTION_GLOBAL, "run as user", "")); if(!web_owner || !*web_owner) owner_uid = geteuid(); else { @@ -267,7 +266,7 @@ gid_t web_files_gid(void) { static gid_t owner_gid = 0; if(unlikely(!web_group)) { - web_group = config_get("global", "web files group", config_get("global", "web files owner", "")); + web_group = config_get(CONFIG_SECTION_WEB, "web files group", config_get(CONFIG_SECTION_WEB, "web files owner", "")); if(!web_group || !*web_group) owner_gid = getegid(); else { @@ -289,8 +288,7 @@ gid_t web_files_gid(void) { return(owner_gid); } -int mysendfile(struct web_client *w, char *filename) -{ +int mysendfile(struct web_client *w, char *filename) { debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, netdata_configured_web_dir, filename); // skip leading slashes @@ -304,6 +302,7 @@ int mysendfile(struct web_client *w, char *filename) for(s = filename; *s ;s++) { if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') { debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename); + w->response.data->contenttype = CT_TEXT_HTML; buffer_sprintf(w->response.data, "Filename contains invalid characters: "); buffer_strcat_htmlescape(w->response.data, filename); return 400; @@ -313,6 +312,7 @@ int mysendfile(struct web_client *w, char *filename) // if the filename contains a .. refuse to serve it if(strstr(filename, "..") != 0) { debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "Relative filenames are not supported: "); buffer_strcat_htmlescape(w->response.data, filename); return 400; @@ -326,6 +326,7 @@ int mysendfile(struct web_client *w, char *filename) struct stat stat; if(lstat(webfilename, &stat) != 0) { debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "File does not exist, or is not accessible: "); buffer_strcat_htmlescape(w->response.data, webfilename); return 404; @@ -334,6 +335,7 @@ int mysendfile(struct web_client *w, char *filename) // check if the file is owned by expected user if(stat.st_uid != web_files_uid()) { error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, stat.st_uid, web_files_uid()); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "Access to file is not permitted: "); buffer_strcat_htmlescape(w->response.data, webfilename); return 403; @@ -342,6 +344,7 @@ int mysendfile(struct web_client *w, char *filename) // check if the file is owned by expected group if(stat.st_gid != web_files_gid()) { error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, stat.st_gid, web_files_gid()); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "Access to file is not permitted: "); buffer_strcat_htmlescape(w->response.data, webfilename); return 403; @@ -354,6 +357,7 @@ int mysendfile(struct web_client *w, char *filename) if((stat.st_mode & S_IFMT) != S_IFREG) { error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "Access to file is not permitted: "); buffer_strcat_htmlescape(w->response.data, webfilename); return 403; @@ -366,6 +370,7 @@ int mysendfile(struct web_client *w, char *filename) if(errno == EBUSY || errno == EAGAIN) { error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; buffer_sprintf(w->response.header, "Location: /" WEB_PATH_FILE "/%s\r\n", filename); buffer_strcat(w->response.data, "File is currently busy, please try again later: "); buffer_strcat_htmlescape(w->response.data, webfilename); @@ -373,6 +378,7 @@ int mysendfile(struct web_client *w, char *filename) } else { error("%llu: Cannot open file '%s'.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "Cannot open file: "); buffer_strcat_htmlescape(w->response.data, webfilename); return 404; @@ -532,98 +538,6 @@ void buffer_data_options2string(BUFFER *wb, uint32_t options) { } } -uint32_t web_client_api_request_v1_data_options(char *o) -{ - uint32_t ret = 0x00000000; - char *tok; - - while(o && *o && (tok = mystrsep(&o, ", |"))) { - if(!*tok) continue; - - if(!strcmp(tok, "nonzero")) - ret |= RRDR_OPTION_NONZERO; - else if(!strcmp(tok, "flip") || !strcmp(tok, "reversed") || !strcmp(tok, "reverse")) - ret |= RRDR_OPTION_REVERSED; - else if(!strcmp(tok, "jsonwrap")) - ret |= RRDR_OPTION_JSON_WRAP; - else if(!strcmp(tok, "min2max")) - ret |= RRDR_OPTION_MIN2MAX; - else if(!strcmp(tok, "ms") || !strcmp(tok, "milliseconds")) - ret |= RRDR_OPTION_MILLISECONDS; - else if(!strcmp(tok, "abs") || !strcmp(tok, "absolute") || !strcmp(tok, "absolute_sum") || !strcmp(tok, "absolute-sum")) - ret |= RRDR_OPTION_ABSOLUTE; - else if(!strcmp(tok, "seconds")) - ret |= RRDR_OPTION_SECONDS; - else if(!strcmp(tok, "null2zero")) - ret |= RRDR_OPTION_NULL2ZERO; - else if(!strcmp(tok, "objectrows")) - ret |= RRDR_OPTION_OBJECTSROWS; - else if(!strcmp(tok, "google_json")) - ret |= RRDR_OPTION_GOOGLE_JSON; - else if(!strcmp(tok, "percentage")) - ret |= RRDR_OPTION_PERCENTAGE; - else if(!strcmp(tok, "unaligned")) - ret |= RRDR_OPTION_NOT_ALIGNED; - } - - return ret; -} - -uint32_t web_client_api_request_v1_data_format(char *name) -{ - if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSON)) // datatable - return DATASOURCE_DATATABLE_JSON; - - else if(!strcmp(name, DATASOURCE_FORMAT_DATATABLE_JSONP)) // datasource - return DATASOURCE_DATATABLE_JSONP; - - else if(!strcmp(name, DATASOURCE_FORMAT_JSON)) // json - return DATASOURCE_JSON; - - else if(!strcmp(name, DATASOURCE_FORMAT_JSONP)) // jsonp - return DATASOURCE_JSONP; - - else if(!strcmp(name, DATASOURCE_FORMAT_SSV)) // ssv - return DATASOURCE_SSV; - - else if(!strcmp(name, DATASOURCE_FORMAT_CSV)) // csv - return DATASOURCE_CSV; - - else if(!strcmp(name, DATASOURCE_FORMAT_TSV) || !strcmp(name, "tsv-excel")) // tsv - return DATASOURCE_TSV; - - else if(!strcmp(name, DATASOURCE_FORMAT_HTML)) // html - return DATASOURCE_HTML; - - else if(!strcmp(name, DATASOURCE_FORMAT_JS_ARRAY)) // array - return DATASOURCE_JS_ARRAY; - - else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma - return DATASOURCE_SSV_COMMA; - - else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray - return DATASOURCE_CSV_JSON_ARRAY; - - return DATASOURCE_JSON; -} - -uint32_t web_client_api_request_v1_data_google_format(char *name) -{ - if(!strcmp(name, "json")) - return DATASOURCE_DATATABLE_JSONP; - - else if(!strcmp(name, "html")) - return DATASOURCE_HTML; - - else if(!strcmp(name, "csv")) - return DATASOURCE_CSV; - - else if(!strcmp(name, "tsv-excel")) - return DATASOURCE_TSV; - - return DATASOURCE_JSON; -} - const char *group_method2string(int group) { switch(group) { case GROUP_UNDEFINED: @@ -649,839 +563,27 @@ const char *group_method2string(int group) { } } -int web_client_api_request_v1_data_group(char *name, int def) -{ - if(!strcmp(name, "average")) - return GROUP_AVERAGE; - - else if(!strcmp(name, "min")) - return GROUP_MIN; - - else if(!strcmp(name, "max")) - return GROUP_MAX; - - else if(!strcmp(name, "sum")) - return GROUP_SUM; - - else if(!strcmp(name, "incremental-sum")) - return GROUP_INCREMENTAL_SUM; - - return def; -} - -int web_client_api_request_v1_alarms(struct web_client *w, char *url) -{ - int all = 0; - - while(url) { - char *value = mystrsep(&url, "?&"); - if (!value || !*value) continue; - - if(!strcmp(value, "all")) all = 1; - else if(!strcmp(value, "active")) all = 0; - } - - buffer_flush(w->response.data); - w->response.data->contenttype = CT_APPLICATION_JSON; - health_alarms2json(&localhost, w->response.data, all); - return 200; -} - -int web_client_api_request_v1_alarm_log(struct web_client *w, char *url) -{ - uint32_t after = 0; - - while(url) { - char *value = mystrsep(&url, "?&"); - if (!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - if(!strcmp(name, "after")) after = strtoul(value, NULL, 0); - } - - buffer_flush(w->response.data); - w->response.data->contenttype = CT_APPLICATION_JSON; - health_alarm_log2json(&localhost, w->response.data, after); - return 200; -} - -int web_client_api_request_single_chart(struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) -{ - int ret = 400; - char *chart = NULL; - - buffer_flush(w->response.data); - - while(url) { - char *value = mystrsep(&url, "?&"); - if(!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - // name and value are now the parameters - // they are not null and not empty - - if(!strcmp(name, "chart")) chart = value; - //else { - /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name); - // goto cleanup; - //} - } - - if(!chart || !*chart) { - buffer_sprintf(w->response.data, "No chart id is given at the request."); - goto cleanup; - } - - RRDSET *st = rrdset_find(chart); - if(!st) st = rrdset_find_byname(chart); - if(!st) { - buffer_strcat(w->response.data, "Chart is not found: "); - buffer_strcat_htmlescape(w->response.data, chart); - ret = 404; - goto cleanup; - } - - w->response.data->contenttype = CT_APPLICATION_JSON; - callback(st, w->response.data); - return 200; - - cleanup: - return ret; -} - -int web_client_api_request_v1_alarm_variables(struct web_client *w, char *url) -{ - return web_client_api_request_single_chart(w, url, health_api_v1_chart_variables2json); -} - -int web_client_api_request_v1_charts(struct web_client *w, char *url) -{ - (void)url; - - buffer_flush(w->response.data); - w->response.data->contenttype = CT_APPLICATION_JSON; - rrd_stats_api_v1_charts(w->response.data); - return 200; -} - -int web_client_api_request_v1_allmetrics(struct web_client *w, char *url) -{ - int format = ALLMETRICS_SHELL; - - while(url) { - char *value = mystrsep(&url, "?&"); - if (!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - if(!strcmp(name, "format")) { - if(!strcmp(value, ALLMETRICS_FORMAT_SHELL)) - format = ALLMETRICS_SHELL; - else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS)) - format = ALLMETRICS_PROMETHEUS; - else - format = 0; - } - } - - buffer_flush(w->response.data); - buffer_no_cacheable(w->response.data); - - switch(format) { - case ALLMETRICS_SHELL: - w->response.data->contenttype = CT_TEXT_PLAIN; - rrd_stats_api_v1_charts_allmetrics_shell(w->response.data); - return 200; - - case ALLMETRICS_PROMETHEUS: - w->response.data->contenttype = CT_PROMETHEUS; - rrd_stats_api_v1_charts_allmetrics_prometheus(w->response.data); - return 200; - - default: - w->response.data->contenttype = CT_TEXT_PLAIN; - buffer_strcat(w->response.data, "Which format? Only '" ALLMETRICS_FORMAT_SHELL "' and '" ALLMETRICS_FORMAT_PROMETHEUS "' is currently supported."); - return 400; - } -} - -int web_client_api_request_v1_chart(struct web_client *w, char *url) -{ - return web_client_api_request_single_chart(w, url, rrd_stats_api_v1_chart); -} - -int web_client_api_request_v1_badge(struct web_client *w, char *url) { - int ret = 400; - buffer_flush(w->response.data); - - BUFFER *dimensions = NULL; - - const char *chart = NULL - , *before_str = NULL - , *after_str = NULL - , *points_str = NULL - , *multiply_str = NULL - , *divide_str = NULL - , *label = NULL - , *units = NULL - , *label_color = NULL - , *value_color = NULL - , *refresh_str = NULL - , *precision_str = NULL - , *alarm = NULL; - - int group = GROUP_AVERAGE; - uint32_t options = 0x00000000; - - while(url) { - char *value = mystrsep(&url, "/?&"); - if(!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value); - - // name and value are now the parameters - // they are not null and not empty - - if(!strcmp(name, "chart")) chart = value; - else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { - if(!dimensions) - dimensions = buffer_create(100); - - buffer_strcat(dimensions, "|"); - buffer_strcat(dimensions, value); - } - else if(!strcmp(name, "after")) after_str = value; - else if(!strcmp(name, "before")) before_str = value; - else if(!strcmp(name, "points")) points_str = value; - else if(!strcmp(name, "group")) { - group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE); - } - else if(!strcmp(name, "options")) { - options |= web_client_api_request_v1_data_options(value); - } - else if(!strcmp(name, "label")) label = value; - else if(!strcmp(name, "units")) units = value; - else if(!strcmp(name, "label_color")) label_color = value; - else if(!strcmp(name, "value_color")) value_color = value; - else if(!strcmp(name, "multiply")) multiply_str = value; - else if(!strcmp(name, "divide")) divide_str = value; - else if(!strcmp(name, "refresh")) refresh_str = value; - else if(!strcmp(name, "precision")) precision_str = value; - else if(!strcmp(name, "alarm")) alarm = value; - } - - if(!chart || !*chart) { - buffer_no_cacheable(w->response.data); - buffer_sprintf(w->response.data, "No chart id is given at the request."); - goto cleanup; - } - - RRDSET *st = rrdset_find(chart); - if(!st) st = rrdset_find_byname(chart); - if(!st) { - buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1); - ret = 200; - goto cleanup; - } - - RRDCALC *rc = NULL; - if(alarm) { - rc = rrdcalc_find(st, alarm); - if (!rc) { - buffer_no_cacheable(w->response.data); - buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1); - ret = 200; - goto cleanup; - } - } - - long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1; - long long divide = (divide_str && *divide_str )?str2l(divide_str):1; - long long before = (before_str && *before_str )?str2l(before_str):0; - long long after = (after_str && *after_str )?str2l(after_str):-st->update_every; - int points = (points_str && *points_str )?str2i(points_str):1; - int precision = (precision_str && *precision_str)?str2i(precision_str):-1; - - if(!multiply) multiply = 1; - if(!divide) divide = 1; - - int refresh = 0; - if(refresh_str && *refresh_str) { - if(!strcmp(refresh_str, "auto")) { - if(rc) refresh = rc->update_every; - else if(options & RRDR_OPTION_NOT_ALIGNED) - refresh = st->update_every; - else { - refresh = (int)(before - after); - if(refresh < 0) refresh = -refresh; - } - } - else { - refresh = str2i(refresh_str); - if(refresh < 0) refresh = -refresh; - } - } - - if(!label) { - if(alarm) { - char *s = (char *)alarm; - while(*s) { - if(*s == '_') *s = ' '; - s++; - } - label = alarm; - } - else if(dimensions) { - const char *dim = buffer_tostring(dimensions); - if(*dim == '|') dim++; - label = dim; - } - else - label = st->name; - } - if(!units) { - if(alarm) { - if(rc->units) - units = rc->units; - else - units = ""; - } - else if(options & RRDR_OPTION_PERCENTAGE) - units = "%"; - else - units = st->units; - } - - debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" - , w->id - , chart - , alarm?alarm:"" - , (dimensions)?buffer_tostring(dimensions):"" - , after - , before - , points - , group - , options - ); - - if(rc) { - if (refresh > 0) { - buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); - w->response.data->expires = now_realtime_sec() + refresh; - } - else buffer_no_cacheable(w->response.data); - - if(!value_color) { - switch(rc->status) { - case RRDCALC_STATUS_CRITICAL: - value_color = "red"; - break; - - case RRDCALC_STATUS_WARNING: - value_color = "orange"; - break; - - case RRDCALC_STATUS_CLEAR: - value_color = "brightgreen"; - break; - - case RRDCALC_STATUS_UNDEFINED: - value_color = "lightgrey"; - break; - - case RRDCALC_STATUS_UNINITIALIZED: - value_color = "#000"; - break; - - default: - value_color = "grey"; - break; - } - } - - buffer_svg(w->response.data, - label, - (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide, - units, - label_color, - value_color, - precision); - ret = 200; - } - else { - time_t latest_timestamp = 0; - int value_is_null = 1; - calculated_number n = NAN; - ret = 500; - - // if the collected value is too old, don't calculate its value - if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above))) - ret = rrd2value(st, - w->response.data, - &n, - (dimensions) ? buffer_tostring(dimensions) : NULL, - points, - after, - before, - group, - options, - NULL, - &latest_timestamp, - &value_is_null); - - // if the value cannot be calculated, show empty badge - if (ret != 200) { - buffer_no_cacheable(w->response.data); - value_is_null = 1; - n = 0; - ret = 200; - } - else if (refresh > 0) { - buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); - w->response.data->expires = now_realtime_sec() + refresh; - } - else buffer_no_cacheable(w->response.data); - - // render the badge - buffer_svg(w->response.data, - label, - (value_is_null)?NAN:(n * multiply / divide), - units, - label_color, - value_color, - precision); - } - -cleanup: - if(dimensions) - buffer_free(dimensions); - return ret; -} - -// returns the HTTP code -int web_client_api_request_v1_data(struct web_client *w, char *url) -{ - debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url); - - int ret = 400; - BUFFER *dimensions = NULL; - - buffer_flush(w->response.data); - - char *google_version = "0.6", - *google_reqId = "0", - *google_sig = "0", - *google_out = "json", - *responseHandler = NULL, - *outFileName = NULL; - - time_t last_timestamp_in_data = 0, google_timestamp = 0; - - char *chart = NULL - , *before_str = NULL - , *after_str = NULL - , *points_str = NULL; - - int group = GROUP_AVERAGE; - uint32_t format = DATASOURCE_JSON; - uint32_t options = 0x00000000; - - while(url) { - char *value = mystrsep(&url, "?&"); - if(!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if(!name || !*name) continue; - if(!value || !*value) continue; - - debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value); - - // name and value are now the parameters - // they are not null and not empty - - if(!strcmp(name, "chart")) chart = value; - else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { - if(!dimensions) dimensions = buffer_create(100); - buffer_strcat(dimensions, "|"); - buffer_strcat(dimensions, value); - } - else if(!strcmp(name, "after")) after_str = value; - else if(!strcmp(name, "before")) before_str = value; - else if(!strcmp(name, "points")) points_str = value; - else if(!strcmp(name, "group")) { - group = web_client_api_request_v1_data_group(value, GROUP_AVERAGE); - } - else if(!strcmp(name, "format")) { - format = web_client_api_request_v1_data_format(value); - } - else if(!strcmp(name, "options")) { - options |= web_client_api_request_v1_data_options(value); - } - else if(!strcmp(name, "callback")) { - responseHandler = value; - } - else if(!strcmp(name, "filename")) { - outFileName = value; - } - else if(!strcmp(name, "tqx")) { - // parse Google Visualization API options - // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source - char *tqx_name, *tqx_value; - - while(value) { - tqx_value = mystrsep(&value, ";"); - if(!tqx_value || !*tqx_value) continue; - - tqx_name = mystrsep(&tqx_value, ":"); - if(!tqx_name || !*tqx_name) continue; - if(!tqx_value || !*tqx_value) continue; - - if(!strcmp(tqx_name, "version")) - google_version = tqx_value; - else if(!strcmp(tqx_name, "reqId")) - google_reqId = tqx_value; - else if(!strcmp(tqx_name, "sig")) { - google_sig = tqx_value; - google_timestamp = strtoul(google_sig, NULL, 0); - } - else if(!strcmp(tqx_name, "out")) { - google_out = tqx_value; - format = web_client_api_request_v1_data_google_format(google_out); - } - else if(!strcmp(tqx_name, "responseHandler")) - responseHandler = tqx_value; - else if(!strcmp(tqx_name, "outFileName")) - outFileName = tqx_value; - } - } - } - - if(!chart || !*chart) { - buffer_sprintf(w->response.data, "No chart id is given at the request."); - goto cleanup; - } - - RRDSET *st = rrdset_find(chart); - if(!st) st = rrdset_find_byname(chart); - if(!st) { - buffer_strcat(w->response.data, "Chart is not found: "); - buffer_strcat_htmlescape(w->response.data, chart); - ret = 404; - goto cleanup; - } - - long long before = (before_str && *before_str)?str2l(before_str):0; - long long after = (after_str && *after_str) ?str2l(after_str):0; - int points = (points_str && *points_str)?str2i(points_str):0; - - debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'" - , w->id - , chart - , (dimensions)?buffer_tostring(dimensions):"" - , after - , before - , points - , group - , format - , options - ); - - if(outFileName && *outFileName) { - buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName); - debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName); - } - - if(format == DATASOURCE_DATATABLE_JSONP) { - if(responseHandler == NULL) - responseHandler = "google.visualization.Query.setResponse"; - - debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'", - w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName - ); - - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:", - responseHandler, google_version, google_reqId, st->last_updated.tv_sec); - } - else if(format == DATASOURCE_JSONP) { - if(responseHandler == NULL) - responseHandler = "callback"; - - buffer_strcat(w->response.data, responseHandler); - buffer_strcat(w->response.data, "("); - } - - ret = rrd2format(st, w->response.data, dimensions, format, points, after, before, group, options, &last_timestamp_in_data); - - if(format == DATASOURCE_DATATABLE_JSONP) { - if(google_timestamp < last_timestamp_in_data) - buffer_strcat(w->response.data, "});"); - - else { - // the client already has the latest data - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});", - responseHandler, google_version, google_reqId); - } - } - else if(format == DATASOURCE_JSONP) - buffer_strcat(w->response.data, ");"); - -cleanup: - if(dimensions) buffer_free(dimensions); - return ret; -} - - -int web_client_api_request_v1_registry(struct web_client *w, char *url) -{ - static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0, - hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0, - hash_to = 0 /*, hash_redirects = 0 */; - - if(unlikely(!hash_action)) { - hash_action = simple_hash("action"); - hash_access = simple_hash("access"); - hash_hello = simple_hash("hello"); - hash_delete = simple_hash("delete"); - hash_search = simple_hash("search"); - hash_switch = simple_hash("switch"); - hash_machine = simple_hash("machine"); - hash_url = simple_hash("url"); - hash_name = simple_hash("name"); - hash_delete_url = simple_hash("delete_url"); - hash_for = simple_hash("for"); - hash_to = simple_hash("to"); -/* - hash_redirects = simple_hash("redirects"); -*/ - } - - char person_guid[GUID_LEN + 1] = ""; - - debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url); - - // FIXME - // The browser may send multiple cookies with our id - - char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "="); - if(cookie) - strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36); - - char action = '\0'; - char *machine_guid = NULL, - *machine_url = NULL, - *url_name = NULL, - *search_machine_guid = NULL, - *delete_url = NULL, - *to_person_guid = NULL; -/* - int redirects = 0; -*/ - - while(url) { - char *value = mystrsep(&url, "?&"); - if (!value || !*value) continue; - - char *name = mystrsep(&value, "="); - if (!name || !*name) continue; - if (!value || !*value) continue; - - debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value); - - uint32_t hash = simple_hash(name); - - if(hash == hash_action && !strcmp(name, "action")) { - uint32_t vhash = simple_hash(value); - - if(vhash == hash_access && !strcmp(value, "access")) action = 'A'; - else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H'; - else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D'; - else if(vhash == hash_search && !strcmp(value, "search")) action = 'S'; - else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W'; -#ifdef NETDATA_INTERNAL_CHECKS - else error("unknown registry action '%s'", value); -#endif /* NETDATA_INTERNAL_CHECKS */ - } -/* - else if(hash == hash_redirects && !strcmp(name, "redirects")) - redirects = atoi(value); -*/ - else if(hash == hash_machine && !strcmp(name, "machine")) - machine_guid = value; - - else if(hash == hash_url && !strcmp(name, "url")) - machine_url = value; - - else if(action == 'A') { - if(hash == hash_name && !strcmp(name, "name")) - url_name = value; - } - else if(action == 'D') { - if(hash == hash_delete_url && !strcmp(name, "delete_url")) - delete_url = value; - } - else if(action == 'S') { - if(hash == hash_for && !strcmp(name, "for")) - search_machine_guid = value; - } - else if(action == 'W') { - if(hash == hash_to && !strcmp(name, "to")) - to_person_guid = value; - } -#ifdef NETDATA_INTERNAL_CHECKS - else error("unused registry URL parameter '%s' with value '%s'", name, value); -#endif /* NETDATA_INTERNAL_CHECKS */ - } - - if(respect_web_browser_do_not_track_policy && w->donottrack) { +static inline int check_host_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { + if(unlikely(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) { buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work."); + buffer_strcat(w->response.data, "This host does not maintain a database"); return 400; } - if(action == 'A' && (!machine_guid || !machine_url || !url_name)) { - error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", url_name?url_name:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Access request."); - return 400; - } - else if(action == 'D' && (!machine_guid || !machine_url || !delete_url)) { - error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Delete request."); - return 400; - } - else if(action == 'S' && (!machine_guid || !machine_url || !search_machine_guid)) { - error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Search request."); - return 400; - } - else if(action == 'W' && (!machine_guid || !machine_url || !to_person_guid)) { - error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", - machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET"); - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry Switch request."); - return 400; - } - - switch(action) { - case 'A': - w->tracking_required = 1; - return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec()); - - case 'D': - w->tracking_required = 1; - return registry_request_delete_json(w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec()); - - case 'S': - w->tracking_required = 1; - return registry_request_search_json(w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec()); - - case 'W': - w->tracking_required = 1; - return registry_request_switch_json(w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec()); - - case 'H': - return registry_request_hello_json(w); - - default: - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search"); - return 400; - } -} - -int web_client_api_request_v1(struct web_client *w, char *url) { - static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0, hash_alarm_log = 0, hash_alarm_variables = 0, hash_raw = 0; - - if(unlikely(hash_data == 0)) { - hash_data = simple_hash("data"); - hash_chart = simple_hash("chart"); - hash_charts = simple_hash("charts"); - hash_registry = simple_hash("registry"); - hash_badge = simple_hash("badge.svg"); - hash_alarms = simple_hash("alarms"); - hash_alarm_log = simple_hash("alarm_log"); - hash_alarm_variables = simple_hash("alarm_variables"); - hash_raw = simple_hash("allmetrics"); - } - - // get the command - char *tok = mystrsep(&url, "/?&"); - if(tok && *tok) { - debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok); - uint32_t hash = simple_hash(tok); - - if(hash == hash_data && !strcmp(tok, "data")) - return web_client_api_request_v1_data(w, url); - - else if(hash == hash_chart && !strcmp(tok, "chart")) - return web_client_api_request_v1_chart(w, url); - - else if(hash == hash_charts && !strcmp(tok, "charts")) - return web_client_api_request_v1_charts(w, url); - - else if(hash == hash_registry && !strcmp(tok, "registry")) - return web_client_api_request_v1_registry(w, url); - - else if(hash == hash_badge && !strcmp(tok, "badge.svg")) - return web_client_api_request_v1_badge(w, url); - - else if(hash == hash_alarms && !strcmp(tok, "alarms")) - return web_client_api_request_v1_alarms(w, url); - - else if(hash == hash_alarm_log && !strcmp(tok, "alarm_log")) - return web_client_api_request_v1_alarm_log(w, url); - - else if(hash == hash_alarm_variables && !strcmp(tok, "alarm_variables")) - return web_client_api_request_v1_alarm_variables(w, url); - - else if(hash == hash_raw && !strcmp(tok, "allmetrics")) - return web_client_api_request_v1_allmetrics(w, url); - - else { - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Unsupported v1 API command: "); - buffer_strcat_htmlescape(w->response.data, tok); - return 404; - } - } - else { - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Which API v1 command?"); - return 400; - } + return func(host, w, url); } -int web_client_api_request(struct web_client *w, char *url) +int web_client_api_request(RRDHOST *host, struct web_client *w, char *url) { // get the api version char *tok = mystrsep(&url, "/?&"); if(tok && *tok) { debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok); if(strcmp(tok, "v1") == 0) - return web_client_api_request_v1(w, url); + return web_client_api_request_v1(host, w, url); else { buffer_flush(w->response.data); + w->response.data->contenttype = CT_TEXT_HTML; buffer_strcat(w->response.data, "Unsupported API version: "); buffer_strcat_htmlescape(w->response.data, tok); return 404; @@ -1494,179 +596,6 @@ int web_client_api_request(struct web_client *w, char *url) } } -int web_client_api_old_data_request(struct web_client *w, char *url, int datasource_type) -{ - if(!url || !*url) { - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Incomplete request."); - return 400; - } - - RRDSET *st = NULL; - - char *args = strchr(url, '?'); - if(args) { - *args='\0'; - args = &args[1]; - } - - // get the name of the data to show - char *tok = mystrsep(&url, "/"); - if(!tok) tok = ""; - - // do we have such a data set? - if(*tok) { - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); - st = rrdset_find_byname(tok); - if(!st) st = rrdset_find(tok); - } - - if(!st) { - // we don't have it - // try to send a file with that name - buffer_flush(w->response.data); - return(mysendfile(w, tok)); - } - - // we have it - debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok); - - // how many entries does the client want? - int lines = rrd_default_history_entries; - int group_count = 1; - time_t after = 0, before = 0; - int group_method = GROUP_AVERAGE; - int nonzero = 0; - - if(url) { - // parse the lines required - tok = mystrsep(&url, "/"); - if(tok) lines = str2i(tok); - if(lines < 1) lines = 1; - } - if(url) { - // parse the group count required - tok = mystrsep(&url, "/"); - if(tok && *tok) group_count = str2i(tok); - if(group_count < 1) group_count = 1; - //if(group_count > save_history / 20) group_count = save_history / 20; - } - if(url) { - // parse the grouping method required - tok = mystrsep(&url, "/"); - if(tok && *tok) { - if(strcmp(tok, "max") == 0) group_method = GROUP_MAX; - else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE; - else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM; - else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok); - } - } - if(url) { - // parse after time - tok = mystrsep(&url, "/"); - if(tok && *tok) after = str2ul(tok); - if(after < 0) after = 0; - } - if(url) { - // parse before time - tok = mystrsep(&url, "/"); - if(tok && *tok) before = str2ul(tok); - if(before < 0) before = 0; - } - if(url) { - // parse nonzero - tok = mystrsep(&url, "/"); - if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1; - } - - w->response.data->contenttype = CT_APPLICATION_JSON; - buffer_flush(w->response.data); - - char *google_version = "0.6"; - char *google_reqId = "0"; - char *google_sig = "0"; - char *google_out = "json"; - char *google_responseHandler = "google.visualization.Query.setResponse"; - char *google_outFileName = NULL; - time_t last_timestamp_in_data = 0; - if(datasource_type == DATASOURCE_DATATABLE_JSON || datasource_type == DATASOURCE_DATATABLE_JSONP) { - - w->response.data->contenttype = CT_APPLICATION_X_JAVASCRIPT; - - while(args) { - tok = mystrsep(&args, "&"); - if(tok && *tok) { - char *name = mystrsep(&tok, "="); - if(name && *name && strcmp(name, "tqx") == 0) { - char *key = mystrsep(&tok, ":"); - char *value = mystrsep(&tok, ";"); - if(key && value && *key && *value) { - if(strcmp(key, "version") == 0) - google_version = value; - - else if(strcmp(key, "reqId") == 0) - google_reqId = value; - - else if(strcmp(key, "sig") == 0) - google_sig = value; - - else if(strcmp(key, "out") == 0) - google_out = value; - - else if(strcmp(key, "responseHandler") == 0) - google_responseHandler = value; - - else if(strcmp(key, "outFileName") == 0) - google_outFileName = value; - } - } - } - } - - debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'", - w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName - ); - - if(datasource_type == DATASOURCE_DATATABLE_JSONP) { - last_timestamp_in_data = strtoul(google_sig, NULL, 0); - - // check the client wants json - if(strcmp(google_out, "json") != 0) { - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});", - google_responseHandler, google_version, google_reqId, google_out); - return 200; - } - } - } - - if(datasource_type == DATASOURCE_DATATABLE_JSONP) { - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:", - google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec); - } - - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %ld after, %ld before).", - w->id, st->name, st->id, lines, group_count, group_method, after, before); - - time_t timestamp_in_data = rrd_stats_json(datasource_type, st, w->response.data, lines, group_count, group_method, (unsigned long)after, (unsigned long)before, nonzero); - - if(datasource_type == DATASOURCE_DATATABLE_JSONP) { - if(timestamp_in_data > last_timestamp_in_data) - buffer_strcat(w->response.data, "});"); - - else { - // the client already has the latest data - buffer_flush(w->response.data); - buffer_sprintf(w->response.data, - "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});", - google_responseHandler, google_version, google_reqId); - } - } - - return 200; -} - const char *web_content_type_to_string(uint8_t contenttype) { switch(contenttype) { case CT_TEXT_HTML: @@ -1853,7 +782,13 @@ static inline char *http_header_parse(struct web_client *w, char *s) { // > 0 : request is not supported // < 0 : request is incomplete - wait for more data -static inline int http_request_validate(struct web_client *w) { +typedef enum http_validation { + HTTP_VALIDATION_OK, + HTTP_VALIDATION_NOT_SUPPORTED, + HTTP_VALIDATION_INCOMPLETE +} HTTP_VALIDATION; + +static inline HTTP_VALIDATION http_request_validate(struct web_client *w) { char *s = w->response.data->buffer, *encoded_url = NULL; // is is a valid request? @@ -1865,9 +800,13 @@ static inline int http_request_validate(struct web_client *w) { encoded_url = s = &s[8]; w->mode = WEB_CLIENT_MODE_OPTIONS; } + else if(!strncmp(s, "STREAM ", 7)) { + encoded_url = s = &s[7]; + w->mode = WEB_CLIENT_MODE_STREAM; + } else { w->wait_receive = 0; - return 1; + return HTTP_VALIDATION_NOT_SUPPORTED; } // find the SPACE + "HTTP/" @@ -1883,7 +822,7 @@ static inline int http_request_validate(struct web_client *w) { // incomplete requests if(unlikely(!*s)) { w->wait_receive = 1; - return -2; + return HTTP_VALIDATION_INCOMPLETE; } // we have the end of encoded_url - remember it @@ -1914,7 +853,7 @@ static inline int http_request_validate(struct web_client *w) { strncpyz(w->last_url, w->decoded_url, URL_MAX); w->wait_receive = 0; - return 0; + return HTTP_VALIDATION_OK; } // another header line @@ -1924,7 +863,7 @@ static inline int http_request_validate(struct web_client *w) { // incomplete request w->wait_receive = 1; - return -3; + return HTTP_VALIDATION_INCOMPLETE; } static inline void web_client_send_http_header(struct web_client *w) { @@ -1934,7 +873,7 @@ static inline void web_client_send_http_header(struct web_client *w) { // set a proper expiration date, if not already set if(unlikely(!w->response.data->expires)) { if(w->response.data->options & WB_CONTENT_NO_CACHEABLE) - w->response.data->expires = w->tv_ready.tv_sec + rrd_update_every; + w->response.data->expires = w->tv_ready.tv_sec + localhost->rrd_update_every; else w->response.data->expires = w->tv_ready.tv_sec + 86400; } @@ -2069,7 +1008,55 @@ static inline void web_client_send_http_header(struct web_client *w) { w->stats_sent_bytes += bytes; } -void web_client_process(struct web_client *w) { +static inline int web_client_process_url(RRDHOST *host, struct web_client *w, char *url); + +static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, char *url) { + static uint32_t hash_localhost = 0; + + if(unlikely(!hash_localhost)) { + hash_localhost = simple_hash("localhost"); + } + + if(host != localhost) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Nesting of hosts is not allowed."); + return 400; + } + + char *tok = mystrsep(&url, "/?&"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for host with name '%s'.", w->id, tok); + + // copy the URL, we need it to serve files + w->last_url[0] = '/'; + if(url && *url) strncpyz(&w->last_url[1], url, URL_MAX - 1); + else w->last_url[1] = '\0'; + + uint32_t hash = simple_hash(tok); + + if(unlikely(hash == hash_localhost && !strcmp(tok, "localhost"))) + return web_client_process_url(localhost, w, url); + + rrd_rdlock(); + RRDHOST *h; + rrdhost_foreach_read(h) { + if(unlikely((hash == h->hash_hostname && !strcmp(tok, h->hostname)) || + (hash == h->hash_machine_guid && !strcmp(tok, h->machine_guid)))) { + rrd_unlock(); + return web_client_process_url(h, w, url); + } + } + rrd_unlock(); + } + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "This netdata does not maintain a database for host: "); + buffer_strcat_htmlescape(w->response.data, tok?tok:""); + return 404; +} + +static inline int web_client_process_url(RRDHOST *host, struct web_client *w, char *url) { static uint32_t hash_api = 0, hash_netdata_conf = 0, @@ -2077,15 +1064,13 @@ void web_client_process(struct web_client *w) { hash_datasource = 0, hash_graph = 0, hash_list = 0, - hash_all_json = 0; + hash_all_json = 0, + hash_host = 0; #ifdef NETDATA_INTERNAL_CHECKS static uint32_t hash_exit = 0, hash_debug = 0, hash_mirror = 0; #endif - // start timing us - now_realtime_timeval(&w->tv_in); - if(unlikely(!hash_api)) { hash_api = simple_hash("api"); hash_netdata_conf = simple_hash("netdata.conf"); @@ -2094,6 +1079,7 @@ void web_client_process(struct web_client *w) { hash_graph = simple_hash(WEB_PATH_GRAPH); hash_list = simple_hash("list"); hash_all_json = simple_hash("all.json"); + hash_host = simple_hash("host"); #ifdef NETDATA_INTERNAL_CHECKS hash_exit = simple_hash("exit"); hash_debug = simple_hash("debug"); @@ -2101,202 +1087,174 @@ void web_client_process(struct web_client *w) { #endif } - int code = 500; - - int what_to_do = http_request_validate(w); - - // wait for more data - if(what_to_do < 0) { - if(w->response.data->len > TOO_BIG_REQUEST) { - strcpy(w->last_url, "too big request"); - - debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big (%zu bytes).", w->id, w->response.data->len); + char *tok = mystrsep(&url, "/?"); + if(likely(tok && *tok)) { + uint32_t hash = simple_hash(tok); + debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok); - code = 400; + if(unlikely(hash == hash_api && strcmp(tok, "api") == 0)) { // current API + debug(D_WEB_CLIENT_ACCESS, "%llu: API request ...", w->id); + return check_host_and_call(host, w, url, web_client_api_request); + } + else if(unlikely(hash == hash_host && strcmp(tok, "host") == 0)) { // host switching + debug(D_WEB_CLIENT_ACCESS, "%llu: host switch request ...", w->id); + return web_client_switch_host(host, w, url); + } + else if(unlikely(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0)) { // old API "data" + debug(D_WEB_CLIENT_ACCESS, "%llu: old API data request...", w->id); + return check_host_and_call(host, w, url, web_client_api_old_data_request_json); + } + else if(unlikely(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0)) { // old API "datasource" + debug(D_WEB_CLIENT_ACCESS, "%llu: old API datasource request...", w->id); + return check_host_and_call(host, w, url, web_client_api_old_data_request_jsonp); + } + else if(unlikely(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0)) { // old API "graph" + debug(D_WEB_CLIENT_ACCESS, "%llu: old API graph request...", w->id); + return check_host_and_call(host, w, url, web_client_api_old_graph_request); + } + else if(unlikely(hash == hash_list && strcmp(tok, "list") == 0)) { // old API "list" + debug(D_WEB_CLIENT_ACCESS, "%llu: old API list request...", w->id); + return check_host_and_call(host, w, url, web_client_api_old_list_request); + } + else if(unlikely(hash == hash_all_json && strcmp(tok, "all.json") == 0)) { // old API "all.json" + debug(D_WEB_CLIENT_ACCESS, "%llu: old API all.json request...", w->id); + return check_host_and_call(host, w, url, web_client_api_old_all_json); + } + else if(unlikely(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0)) { // netdata.conf + debug(D_WEB_CLIENT_ACCESS, "%llu: generating netdata.conf ...", w->id); + w->response.data->contenttype = CT_TEXT_PLAIN; buffer_flush(w->response.data); - buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len); + config_generate(w->response.data, 0); + return 200; } - else { - // wait for more data - return; +#ifdef NETDATA_INTERNAL_CHECKS + else if(unlikely(hash == hash_exit && strcmp(tok, "exit") == 0)) { + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_flush(w->response.data); + + if(!netdata_exit) + buffer_strcat(w->response.data, "ok, will do..."); + else + buffer_strcat(w->response.data, "I am doing it already"); + + error("web request to exit received."); + netdata_cleanup_and_exit(0); + return 200; } - } - else if(what_to_do > 0) { - // strcpy(w->last_url, "not a valid request"); + else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) { + buffer_flush(w->response.data); - debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer); + // get the name of the data to show + tok = mystrsep(&url, "/?&"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); + + // do we have such a data set? + RRDSET *st = rrdset_find_byname(host, tok); + if(!st) st = rrdset_find(host, tok); + if(!st) { + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, tok); + debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok); + return 404; + } + + debug_flags |= D_RRD_STATS; + + if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)) + rrdset_flag_clear(st, RRDSET_FLAG_DEBUG); + else + rrdset_flag_set(st, RRDSET_FLAG_DEBUG); + + w->response.data->contenttype = CT_TEXT_HTML; + buffer_sprintf(w->response.data, "Chart has now debug %s: ", rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled"); + buffer_strcat_htmlescape(w->response.data, tok); + debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled"); + return 200; + } - code = 500; - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "I don't understand you...\r\n"); - } - else { // what_to_do == 0 - if(w->mode == WEB_CLIENT_MODE_OPTIONS) { - code = 200; - w->response.data->contenttype = CT_TEXT_PLAIN; buffer_flush(w->response.data); - buffer_strcat(w->response.data, "OK"); + buffer_strcat(w->response.data, "debug which chart?\r\n"); + return 400; } - else { - char *url = w->decoded_url; - char *tok = mystrsep(&url, "/?"); - if(tok && *tok) { - uint32_t hash = simple_hash(tok); - debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok); + else if(unlikely(hash == hash_mirror && strcmp(tok, "mirror") == 0)) { + debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id); - if(hash == hash_api && strcmp(tok, "api") == 0) { - // the client is requesting api access - code = web_client_api_request(w, url); - } - else if(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0) { - code = 200; - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id); + // replace the zero bytes with spaces + buffer_char_replace(w->response.data, '\0', ' '); - w->response.data->contenttype = CT_TEXT_PLAIN; - buffer_flush(w->response.data); - generate_config(w->response.data, 0); - } - else if(hash == hash_data && strcmp(tok, WEB_PATH_DATA) == 0) { // "data" - // the client is requesting rrd data -- OLD API - code = web_client_api_old_data_request(w, url, DATASOURCE_JSON); - } - else if(hash == hash_datasource && strcmp(tok, WEB_PATH_DATASOURCE) == 0) { // "datasource" - // the client is requesting google datasource -- OLD API - code = web_client_api_old_data_request(w, url, DATASOURCE_DATATABLE_JSONP); - } - else if(hash == hash_graph && strcmp(tok, WEB_PATH_GRAPH) == 0) { // "graph" - // the client is requesting an rrd graph -- OLD API - - // get the name of the data to show - tok = mystrsep(&url, "/?&"); - if(tok && *tok) { - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); - - // do we have such a data set? - RRDSET *st = rrdset_find_byname(tok); - if(!st) st = rrdset_find(tok); - if(!st) { - // we don't have it - // try to send a file with that name - buffer_flush(w->response.data); - code = mysendfile(w, tok); - } - else { - code = 200; - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name); - w->response.data->contenttype = CT_APPLICATION_JSON; - buffer_flush(w->response.data); - rrd_stats_graph_json(st, url, w->response.data); - } - } - else { - code = 400; - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "Graph name?\r\n"); - } - } - else if(hash == hash_list && strcmp(tok, "list") == 0) { - // OLD API - code = 200; + // just leave the buffer as is + // it will be copied back to the client - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id); + return 200; + } +#endif /* NETDATA_INTERNAL_CHECKS */ + } - buffer_flush(w->response.data); - RRDSET *st = localhost.rrdset_root; + char filename[FILENAME_MAX+1]; + url = filename; + strncpyz(filename, w->last_url, FILENAME_MAX); + tok = mystrsep(&url, "?"); + buffer_flush(w->response.data); + return mysendfile(w, (tok && *tok)?tok:"/"); +} - for ( ; st ; st = st->next ) - buffer_sprintf(w->response.data, "%s\n", st->name); - } - else if(hash == hash_all_json && strcmp(tok, "all.json") == 0) { - // OLD API - code = 200; - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id); +void web_client_process_request(struct web_client *w) { - w->response.data->contenttype = CT_APPLICATION_JSON; - buffer_flush(w->response.data); - rrd_stats_all_json(w->response.data); - } -#ifdef NETDATA_INTERNAL_CHECKS - else if(hash == hash_exit && strcmp(tok, "exit") == 0) { - code = 200; - w->response.data->contenttype = CT_TEXT_PLAIN; - buffer_flush(w->response.data); + // start timing us + now_realtime_timeval(&w->tv_in); - if(!netdata_exit) - buffer_strcat(w->response.data, "ok, will do..."); - else - buffer_strcat(w->response.data, "I am doing it already"); + switch(http_request_validate(w)) { + case HTTP_VALIDATION_OK: + switch(w->mode) { + case WEB_CLIENT_MODE_STREAM: + w->response.code = rrdpush_receiver_thread_spawn(localhost, w, w->decoded_url); + return; - error("web request to exit received."); - netdata_cleanup_and_exit(0); - } - else if(hash == hash_debug && strcmp(tok, "debug") == 0) { + case WEB_CLIENT_MODE_OPTIONS: + w->response.data->contenttype = CT_TEXT_PLAIN; buffer_flush(w->response.data); + buffer_strcat(w->response.data, "OK"); + w->response.code = 200; + break; - // get the name of the data to show - tok = mystrsep(&url, "/?&"); - if(tok && *tok) { - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); - - // do we have such a data set? - RRDSET *st = rrdset_find_byname(tok); - if(!st) st = rrdset_find(tok); - if(!st) { - code = 404; - buffer_strcat(w->response.data, "Chart is not found: "); - buffer_strcat_htmlescape(w->response.data, tok); - debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok); - } - else { - code = 200; - debug_flags |= D_RRD_STATS; - st->debug = !st->debug; - buffer_sprintf(w->response.data, "Chart has now debug %s: ", st->debug?"enabled":"disabled"); - buffer_strcat_htmlescape(w->response.data, tok); - debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled"); - } - } - else { - code = 500; - buffer_flush(w->response.data); - buffer_strcat(w->response.data, "debug which chart?\r\n"); - } - } - else if(hash == hash_mirror && strcmp(tok, "mirror") == 0) { - code = 200; + case WEB_CLIENT_MODE_FILECOPY: + case WEB_CLIENT_MODE_NORMAL: + w->response.code = web_client_process_url(localhost, w, w->decoded_url); + break; + } + break; - debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id); + case HTTP_VALIDATION_INCOMPLETE: + if(w->response.data->len > TOO_BIG_REQUEST) { + strcpy(w->last_url, "too big request"); - // replace the zero bytes with spaces - buffer_char_replace(w->response.data, '\0', ' '); + debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big (%zu bytes).", w->id, w->response.data->len); - // just leave the buffer as is - // it will be copied back to the client - } -#endif /* NETDATA_INTERNAL_CHECKS */ - else { - char filename[FILENAME_MAX+1]; - url = filename; - strncpyz(filename, w->last_url, FILENAME_MAX); - tok = mystrsep(&url, "?"); - buffer_flush(w->response.data); - code = mysendfile(w, (tok && *tok)?tok:"/"); - } + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len); + w->response.code = 400; } else { - char filename[FILENAME_MAX+1]; - url = filename; - strncpyz(filename, w->last_url, FILENAME_MAX); - tok = mystrsep(&url, "?"); - buffer_flush(w->response.data); - code = mysendfile(w, (tok && *tok)?tok:"/"); + // wait for more data + return; } - } + break; + + case HTTP_VALIDATION_NOT_SUPPORTED: + debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer); + + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "I don't understand you...\r\n"); + w->response.code = 400; + break; } + // keep track of the time we done processing now_realtime_timeval(&w->tv_ready); + w->response.sent = 0; - w->response.code = code; // set a proper last modified date if(unlikely(!w->response.data->date)) @@ -2308,8 +1266,11 @@ void web_client_process(struct web_client *w) { if(w->response.data->len) w->wait_send = 1; else w->wait_send = 0; - // pretty logging switch(w->mode) { + case WEB_CLIENT_MODE_STREAM: + debug(D_WEB_CLIENT, "%llu: STREAM done.", w->id); + break; + case WEB_CLIENT_MODE_OPTIONS: debug(D_WEB_CLIENT, "%llu: Done preparing the OPTIONS response. Sending data (%zu bytes) to client.", w->id, w->response.data->len); break; @@ -2341,7 +1302,7 @@ void web_client_process(struct web_client *w) { break; default: - fatal("%llu: Unknown client mode %d.", w->id, w->mode); + fatal("%llu: Unknown client mode %u.", w->id, w->mode); break; } } @@ -2663,11 +1624,14 @@ void *web_client_main(void *ptr) struct web_client *w = ptr; struct pollfd fds[2], *ifd, *ofd; - int retval, fdmax = 0, timeout; + int retval, timeout; + nfds_t fdmax = 0; log_access("%llu: %s port %s connected on thread task id %d", w->id, w->client_ip, w->client_port, gettid()); for(;;) { + if(unlikely(netdata_exit)) break; + if(unlikely(w->dead)) { debug(D_WEB_CLIENT, "%llu: client is dead.", w->id); break; @@ -2719,6 +1683,8 @@ void *web_client_main(void *ptr) timeout = web_client_timeout * 1000; retval = poll(fds, fdmax, timeout); + if(unlikely(netdata_exit)) break; + if(unlikely(retval == -1)) { if(errno == EAGAIN || errno == EINTR) { debug(D_WEB_CLIENT, "%llu: EAGAIN received.", w->id); @@ -2733,6 +1699,8 @@ void *web_client_main(void *ptr) break; } + if(unlikely(netdata_exit)) break; + int used = 0; if(w->wait_send && ofd->revents & POLLOUT) { used++; @@ -2742,6 +1710,8 @@ void *web_client_main(void *ptr) } } + if(unlikely(netdata_exit)) break; + if(w->wait_receive && (ifd->revents & POLLIN || ifd->revents & POLLPRI)) { used++; if(web_client_receive(w) < 0) { @@ -2751,7 +1721,12 @@ void *web_client_main(void *ptr) if(w->mode == WEB_CLIENT_MODE_NORMAL) { debug(D_WEB_CLIENT, "%llu: Attempting to process received data.", w->id); - web_client_process(w); + web_client_process_request(w); + + // if the sockets are closed, may have transferred this client + // to plugins.d + if(unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) + break; } } diff --git a/src/web_client.h b/src/web_client.h index 76284e59..70c5b1ff 100644 --- a/src/web_client.h +++ b/src/web_client.h @@ -13,9 +13,12 @@ extern int web_enable_gzip, extern int respect_web_browser_do_not_track_policy; extern char *web_x_frame_options; -#define WEB_CLIENT_MODE_NORMAL 0 -#define WEB_CLIENT_MODE_FILECOPY 1 -#define WEB_CLIENT_MODE_OPTIONS 2 +typedef enum web_client_mode { + WEB_CLIENT_MODE_NORMAL = 0, + WEB_CLIENT_MODE_FILECOPY = 1, + WEB_CLIENT_MODE_OPTIONS = 2, + WEB_CLIENT_MODE_STREAM = 3 +} WEB_CLIENT_MODE; #define URL_MAX 8192 #define ZLIB_CHUNK 16384 @@ -55,14 +58,14 @@ struct web_client { uint8_t keepalive:1; // if set to 1, the web client will be re-used - uint8_t mode:3; // the operational mode of the client - uint8_t wait_receive:1; // 1 = we are waiting more input data uint8_t wait_send:1; // 1 = we have data to send to the client uint8_t donottrack:1; // 1 = we should not set cookies on this client uint8_t tracking_required:1; // 1 = if the request requires cookies + WEB_CLIENT_MODE mode; // the operational mode of the client + int tcp_cork; // 1 = we have a cork on the socket int ifd; @@ -103,7 +106,7 @@ extern struct web_client *web_client_create(int listener); extern struct web_client *web_client_free(struct web_client *w); extern ssize_t web_client_send(struct web_client *w); extern ssize_t web_client_receive(struct web_client *w); -extern void web_client_process(struct web_client *w); +extern void web_client_process_request(struct web_client *w); extern void web_client_reset(struct web_client *w); extern void *web_client_main(void *ptr); @@ -112,4 +115,7 @@ extern int web_client_api_request_v1_data_group(char *name, int def); extern const char *group_method2string(int group); extern void buffer_data_options2string(BUFFER *wb, uint32_t options); + +extern int mysendfile(struct web_client *w, char *filename); + #endif diff --git a/src/web_server.c b/src/web_server.c index 8e942a59..593a82a5 100644 --- a/src/web_server.c +++ b/src/web_server.c @@ -5,7 +5,8 @@ size_t listen_fds_count = 0; int listen_fds[MAX_LISTEN_FDS] = { [0 ... 99] = -1 }; char *listen_fds_names[MAX_LISTEN_FDS] = { [0 ... 99] = NULL }; int listen_port = LISTEN_PORT; -int web_server_mode = WEB_SERVER_MODE_MULTI_THREADED; + +WEB_SERVER_MODE web_server_mode = WEB_SERVER_MODE_MULTI_THREADED; static int shown_server_socket_error = 0; @@ -83,6 +84,29 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) { } #endif +WEB_SERVER_MODE web_server_mode_id(const char *mode) { + if(!strcmp(mode, "none")) + return WEB_SERVER_MODE_NONE; + else if(!strcmp(mode, "single") || !strcmp(mode, "single-threaded")) + return WEB_SERVER_MODE_SINGLE_THREADED; + else // if(!strcmp(mode, "multi") || !strcmp(mode, "multi-threaded")) + return WEB_SERVER_MODE_MULTI_THREADED; +} + +const char *web_server_mode_name(WEB_SERVER_MODE id) { + switch(id) { + case WEB_SERVER_MODE_NONE: + return "none"; + + case WEB_SERVER_MODE_SINGLE_THREADED: + return "single-threaded"; + + default: + case WEB_SERVER_MODE_MULTI_THREADED: + return "multi-threaded"; + } +} + int create_listen_socket4(const char *ip, int port, int listen_backlog) { int sock; int sockopt = 1; @@ -316,22 +340,16 @@ static inline int bind_to_one(const char *definition, int default_port, int list int create_listen_sockets(void) { shown_server_socket_error = 0; - listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG); - - if(config_exists("global", "bind socket to IP") && !config_exists("global", "bind to")) - config_rename("global", "bind socket to IP", "bind to"); - - if(config_exists("global", "port") && !config_exists("global", "default port")) - config_rename("global", "port", "default port"); + listen_backlog = (int) config_get_number(CONFIG_SECTION_WEB, "listen backlog", LISTEN_BACKLOG); - listen_port = (int) config_get_number("global", "default port", LISTEN_PORT); + listen_port = (int) config_get_number(CONFIG_SECTION_WEB, "default port", LISTEN_PORT); if(listen_port < 1 || listen_port > 65535) { error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT); - listen_port = (int) config_set_number("global", "default port", LISTEN_PORT); + listen_port = (int) config_set_number(CONFIG_SECTION_WEB, "default port", LISTEN_PORT); } debug(D_OPTIONS, "Default listen port set to %d.", listen_port); - char *s = config_get("global", "bind to", "*"); + char *s = config_get(CONFIG_SECTION_WEB, "bind to", "*"); while(*s) { char *e = s; @@ -614,7 +632,7 @@ void *socket_listen_main_single_threaded(void *ptr) { if (w->mode != WEB_CLIENT_MODE_FILECOPY) { debug(D_WEB_CLIENT, "%llu: Processing received data.", w->id); - web_client_process(w); + web_client_process_request(w); } } diff --git a/src/web_server.h b/src/web_server.h index 93adc5b2..41dcfcf0 100644 --- a/src/web_server.h +++ b/src/web_server.h @@ -13,9 +13,17 @@ #define MAX_LISTEN_FDS 100 #endif -#define WEB_SERVER_MODE_MULTI_THREADED 0 -#define WEB_SERVER_MODE_SINGLE_THREADED 1 -extern int web_server_mode; +typedef enum web_server_mode { + WEB_SERVER_MODE_SINGLE_THREADED, + WEB_SERVER_MODE_MULTI_THREADED, + WEB_SERVER_MODE_NONE +} WEB_SERVER_MODE; + +extern WEB_SERVER_MODE web_server_mode; + +extern WEB_SERVER_MODE web_server_mode_id(const char *mode); +extern const char *web_server_mode_name(WEB_SERVER_MODE id); + extern void *socket_listen_main_multi_threaded(void *ptr); extern void *socket_listen_main_single_threaded(void *ptr); diff --git a/web/demosites.html b/web/demosites.html index 2fa38802..6f6a4eaf 100644 --- a/web/demosites.html +++ b/web/demosites.html @@ -671,7 +671,7 @@ p { can be set on any metric monitored by netdata. Alarm notifications are role-based and support dynamic thresholds, hysteresis and can be dispatched via multiple methods - (such as email, slack.com, pushover.net, pushbullet.com telegram.org, twilio.com). + (such as email, slack.com, pushover.net, pushbullet.com, telegram.org, twilio.com).

In real-time

netdata collects thousands of metrics per server per second, diff --git a/web/index.html b/web/index.html index a5bf5aaf..2f116602 100644 --- a/web/index.html +++ b/web/index.html @@ -1422,7 +1422,7 @@ sidebar += '

  • add more charts
  • '; sidebar += '
  • add more alarms
  • '; - sidebar += '
  • netdata on ' + data.hostname.toString() + ', collects every ' + ((data.update_every == 1)?'second':data.update_every.toString() + ' seconds') + ' ' + data.dimensions_count.toLocaleString() + ' metrics, presented as ' + data.charts_count.toLocaleString() + ' charts and monitored by ' + data.alarms_count.toLocaleString() + ' alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + Math.round(data.history / (3600/data.update_every)).toLocaleString() + ' ' + ((data.history == (3600/data.update_every))?'hour':'hours').toString() + ' of real-time history.
     
    netdata
    v' + data.version.toString() +'
  • '; + sidebar += '
  • netdata on ' + data.hostname.toString() + ', collects every ' + ((data.update_every == 1)?'second':data.update_every.toString() + ' seconds') + ' ' + data.dimensions_count.toLocaleString() + ' metrics, presented as ' + data.charts_count.toLocaleString() + ' charts and monitored by ' + data.alarms_count.toLocaleString() + ' alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + seconds4human(data.update_every * data.history) + ' of real-time history.
     
    netdata
    v' + data.version.toString() +'
  • '; sidebar += ''; div.innerHTML = html; document.getElementById('sidebar').innerHTML = sidebar; @@ -1576,70 +1576,6 @@ return t.toLocaleDateString() + space + t.toLocaleTimeString(); } - function seconds4human(seconds, options) { - var default_options = { - now: 'now', - space: ' ', - negative_suffix: 'ago', - hour: 'hour', - hours: 'hours', - minute: 'minute', - minutes: 'minutes', - second: 'second', - seconds: 'seconds', - and: 'and' - }; - - if(typeof options !== 'object') - options = default_options; - else { - var x; - for(x in default_options) { - if(typeof options[x] !== 'string') - options[x] = default_options[x]; - } - } - - if(typeof seconds === 'string') - seconds = parseInt(seconds); - - if(seconds === 0) - return options.now; - - var suffix = ''; - if(seconds < 0) { - seconds = -seconds; - if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix; - } - - var hours = Math.floor(seconds / 3600); - seconds -= (hours * 3600); - - var minutes = Math.floor(seconds / 60); - seconds -= (minutes * 60); - - var txt = ''; - - if(hours > 1) txt += hours.toString() + options.space + options.hours; - else if(hours === 1) txt += hours.toString() + options.space + options.hour; - - if(hours > 0 && minutes > 0 && seconds == 0) - txt += options.space + options.and + options.space; - else if(hours > 0 && minutes > 0 && seconds > 0) - txt += ',' + options.space; - - if(minutes > 1) txt += minutes.toString() + options.space + options.minutes; - else if(minutes === 1) txt += minutes.toString() + options.space + options.minute; - - if((minutes > 0 || minutes > 0) && seconds > 0) - txt += options.space + options.and + options.space; - - if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds; - else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second; - - return txt + suffix; - } - function alarm_lookup_explain(alarm, chart) { var dimensions = ' of all values '; @@ -2221,6 +2157,70 @@ }); } + function seconds4human(seconds, options) { + var default_options = { + now: 'now', + space: ' ', + negative_suffix: 'ago', + hour: 'hour', + hours: 'hours', + minute: 'minute', + minutes: 'minutes', + second: 'second', + seconds: 'seconds', + and: 'and' + }; + + if(typeof options !== 'object') + options = default_options; + else { + var x; + for(x in default_options) { + if(typeof options[x] !== 'string') + options[x] = default_options[x]; + } + } + + if(typeof seconds === 'string') + seconds = parseInt(seconds); + + if(seconds === 0) + return options.now; + + var suffix = ''; + if(seconds < 0) { + seconds = -seconds; + if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix; + } + + var hours = Math.floor(seconds / 3600); + seconds -= (hours * 3600); + + var minutes = Math.floor(seconds / 60); + seconds -= (minutes * 60); + + var txt = ''; + + if(hours > 1) txt += hours.toString() + options.space + options.hours; + else if(hours === 1) txt += hours.toString() + options.space + options.hour; + + if(hours > 0 && minutes > 0 && seconds == 0) + txt += options.space + options.and + options.space; + else if(hours > 0 && minutes > 0 && seconds > 0) + txt += ',' + options.space; + + if(minutes > 1) txt += minutes.toString() + options.space + options.minutes; + else if(minutes === 1) txt += minutes.toString() + options.space + options.minute; + + if((minutes > 0 || minutes > 0) && seconds > 0) + txt += options.space + options.and + options.space; + + if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds; + else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second; + + return txt + suffix; + } + function alarmsCallback(data) { var count = 0; for(x in data.alarms) {