diff options
Diffstat (limited to '')
-rw-r--r-- | collectors/timex.plugin/Makefile.am | 8 | ||||
l--------- | collectors/timex.plugin/README.md | 1 | ||||
-rw-r--r-- | collectors/timex.plugin/integrations/timex.md | 143 | ||||
-rw-r--r-- | collectors/timex.plugin/metadata.yaml | 112 | ||||
-rw-r--r-- | collectors/timex.plugin/plugin_timex.c | 176 |
5 files changed, 440 insertions, 0 deletions
diff --git a/collectors/timex.plugin/Makefile.am b/collectors/timex.plugin/Makefile.am new file mode 100644 index 00000000..161784b8 --- /dev/null +++ b/collectors/timex.plugin/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/collectors/timex.plugin/README.md b/collectors/timex.plugin/README.md new file mode 120000 index 00000000..89c1bd0d --- /dev/null +++ b/collectors/timex.plugin/README.md @@ -0,0 +1 @@ +integrations/timex.md
\ No newline at end of file diff --git a/collectors/timex.plugin/integrations/timex.md b/collectors/timex.plugin/integrations/timex.md new file mode 100644 index 00000000..754b2368 --- /dev/null +++ b/collectors/timex.plugin/integrations/timex.md @@ -0,0 +1,143 @@ +<!--startmeta +custom_edit_url: "https://github.com/netdata/netdata/edit/master/collectors/timex.plugin/README.md" +meta_yaml: "https://github.com/netdata/netdata/edit/master/collectors/timex.plugin/metadata.yaml" +sidebar_label: "Timex" +learn_status: "Published" +learn_rel_path: "Data Collection/System Clock and NTP" +most_popular: False +message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE" +endmeta--> + +# Timex + + +<img src="https://netdata.cloud/img/syslog.png" width="150"/> + + +Plugin: timex.plugin +Module: timex.plugin + +<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" /> + +## Overview + +Examine Timex metrics to gain insights into system clock operations. Study time sync status, clock drift, and adjustments to ensure accurate system timekeeping. + +It uses system call adjtimex on Linux and ntp_adjtime on FreeBSD or Mac to monitor the system kernel clock synchronization state. + +This collector is supported on all platforms. + +This collector supports collecting metrics from multiple instances of this integration, including remote instances. + + +### Default Behavior + +#### Auto-Detection + +This integration doesn't support auto-detection. + +#### Limits + +The default configuration for this integration does not impose any limits on data collection. + +#### Performance Impact + +The default configuration for this integration is not expected to impose a significant performance impact on the system. + + +## Metrics + +Metrics grouped by *scope*. + +The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels. + + + +### Per Timex instance + +These metrics refer to the entire monitored application. + +This scope has no labels. + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| system.clock_sync_state | state | state | +| system.clock_status | unsync, clockerr | status | +| system.clock_sync_offset | offset | milliseconds | + + + +## Alerts + + +The following alerts are available: + +| Alert name | On metric | Description | +|:------------|:----------|:------------| +| [ system_clock_sync_state ](https://github.com/netdata/netdata/blob/master/health/health.d/timex.conf) | system.clock_sync_state | when set to 0, the system kernel believes the system clock is not properly synchronized to a reliable server | + + +## Setup + +### Prerequisites + +No action required. + +### Configuration + +#### File + +The configuration file name for this integration is `netdata.conf`. +Configuration for this specific integration is located in the `[plugin:timex]` section within that file. + +The file format is a modified INI syntax. The general structure is: + +```ini +[section1] + option1 = some value + option2 = some other value + +[section2] + option3 = some third value +``` +You can edit the configuration file using the `edit-config` script from the +Netdata [config directory](https://github.com/netdata/netdata/blob/master/docs/configure/nodes.md#the-netdata-config-directory). + +```bash +cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata +sudo ./edit-config netdata.conf +``` +#### Options + +At least one option ('clock synchronization state', 'time offset') needs to be enabled for this collector to run. + +<details><summary>Config options</summary> + +| Name | Description | Default | Required | +|:----|:-----------|:-------|:--------:| +| update every | Data collection frequency. | 1 | no | +| clock synchronization state | Make chart showing system clock synchronization state. | yes | yes | +| time offset | Make chart showing computed time offset between local system and reference clock | yes | yes | + +</details> + +#### Examples + +##### Basic + +A basic configuration example. + +<details><summary>Config</summary> + +```yaml +[plugin:timex] + update every = 1 + clock synchronization state = yes + time offset = yes + +``` +</details> + + diff --git a/collectors/timex.plugin/metadata.yaml b/collectors/timex.plugin/metadata.yaml new file mode 100644 index 00000000..2b43d8a2 --- /dev/null +++ b/collectors/timex.plugin/metadata.yaml @@ -0,0 +1,112 @@ +plugin_name: timex.plugin +modules: + - meta: + plugin_name: timex.plugin + module_name: timex.plugin + monitored_instance: + name: Timex + link: "" + categories: + - data-collection.system-clock-and-ntp + icon_filename: "syslog.png" + related_resources: + integrations: + list: [] + info_provided_to_referring_integrations: + description: "" + keywords: [] + most_popular: false + overview: + data_collection: + metrics_description: "Examine Timex metrics to gain insights into system clock operations. Study time sync status, clock drift, and adjustments to ensure accurate system timekeeping." + method_description: "It uses system call adjtimex on Linux and ntp_adjtime on FreeBSD or Mac to monitor the system kernel clock synchronization state." + supported_platforms: + include: [] + exclude: [] + multi_instance: true + additional_permissions: + description: "" + default_behavior: + auto_detection: + description: "" + limits: + description: "" + performance_impact: + description: "" + setup: + prerequisites: + list: [] + configuration: + file: + name: "netdata.conf" + section_name: "[plugin:timex]" + description: "The netdata main configuration file." + options: + description: "At least one option ('clock synchronization state', 'time offset') needs to be enabled for this collector to run." + folding: + title: "Config options" + enabled: true + list: + - name: update every + description: Data collection frequency. + default_value: 1 + required: false + - name: clock synchronization state + description: Make chart showing system clock synchronization state. + default_value: yes + required: true + - name: time offset + description: Make chart showing computed time offset between local system and reference clock + default_value: yes + required: true + examples: + folding: + enabled: true + title: "Config" + list: + - name: Basic + description: A basic configuration example. + config: | + [plugin:timex] + update every = 1 + clock synchronization state = yes + time offset = yes + troubleshooting: + problems: + list: [] + alerts: + - name: system_clock_sync_state + link: https://github.com/netdata/netdata/blob/master/health/health.d/timex.conf + metric: system.clock_sync_state + info: when set to 0, the system kernel believes the system clock is not properly synchronized to a reliable server + os: "linux" + metrics: + folding: + title: Metrics + enabled: false + description: "" + availability: [] + scopes: + - name: global + description: "These metrics refer to the entire monitored application." + labels: [] + metrics: + - name: system.clock_sync_state + description: System Clock Synchronization State + unit: "state" + chart_type: line + dimensions: + - name: state + - name: system.clock_status + description: System Clock Status + unit: "status" + chart_type: line + dimensions: + - name: unsync + - name: clockerr + - name: system.clock_sync_offset + description: Computed Time Offset Between Local System and Reference Clock + unit: "milliseconds" + chart_type: line + dimensions: + - name: offset diff --git a/collectors/timex.plugin/plugin_timex.c b/collectors/timex.plugin/plugin_timex.c new file mode 100644 index 00000000..025b699a --- /dev/null +++ b/collectors/timex.plugin/plugin_timex.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "daemon/common.h" +#include "libnetdata/os.h" + +#define PLUGIN_TIMEX_NAME "timex.plugin" + +#define CONFIG_SECTION_TIMEX "plugin:timex" + +struct status_codes { + char *name; + int code; + RRDDIM *rd; +} sta_codes[] = { + // {"pll", STA_PLL, NULL}, + // {"ppsfreq", STA_PPSFREQ, NULL}, + // {"ppstime", STA_PPSTIME, NULL}, + // {"fll", STA_FLL, NULL}, + // {"ins", STA_INS, NULL}, + // {"del", STA_DEL, NULL}, + {"unsync", STA_UNSYNC, NULL}, + // {"freqhold", STA_FREQHOLD, NULL}, + // {"ppssignal", STA_PPSSIGNAL, NULL}, + // {"ppsjitter", STA_PPSJITTER, NULL}, + // {"ppswander", STA_PPSWANDER, NULL}, + // {"ppserror", STA_PPSERROR, NULL}, + {"clockerr", STA_CLOCKERR, NULL}, + // {"nano", STA_NANO, NULL}, + // {"clk", STA_CLK, NULL}, + {NULL, 0, NULL}, +}; + +static void timex_main_cleanup(void *ptr) +{ + worker_unregister(); + + struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; + static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; + + netdata_log_info("cleaning up..."); + + static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; +} + +void *timex_main(void *ptr) +{ + worker_register("TIMEX"); + worker_register_job_name(0, "clock check"); + + netdata_thread_cleanup_push(timex_main_cleanup, ptr); + + int update_every = (int)config_get_number(CONFIG_SECTION_TIMEX, "update every", 10); + if (update_every < localhost->rrd_update_every) + update_every = localhost->rrd_update_every; + + int do_sync = config_get_boolean(CONFIG_SECTION_TIMEX, "clock synchronization state", CONFIG_BOOLEAN_YES); + int do_offset = config_get_boolean(CONFIG_SECTION_TIMEX, "time offset", CONFIG_BOOLEAN_YES); + + if (unlikely(do_sync == CONFIG_BOOLEAN_NO && do_offset == CONFIG_BOOLEAN_NO)) { + netdata_log_info("No charts to show"); + goto exit; + } + + usec_t step = update_every * USEC_PER_SEC; + heartbeat_t hb; + heartbeat_init(&hb); + while (service_running(SERVICE_COLLECTORS)) { + worker_is_idle(); + heartbeat_next(&hb, step); + worker_is_busy(0); + + struct timex timex_buf = {}; + int sync_state = 0; + static int prev_sync_state = 0; + + sync_state = ADJUST_TIMEX(&timex_buf); + + int non_seq_failure = (sync_state == -1 && prev_sync_state != -1); + prev_sync_state = sync_state; + + if (non_seq_failure) { + netdata_log_error("Cannot get clock synchronization state"); + continue; + } + + collected_number divisor = USEC_PER_MS; + if (timex_buf.status & STA_NANO) + divisor = NSEC_PER_MSEC; + + // ---------------------------------------------------------------- + + if (do_sync) { + static RRDSET *st_sync_state = NULL; + static RRDDIM *rd_sync_state; + + if (unlikely(!st_sync_state)) { + st_sync_state = rrdset_create_localhost( + "system", + "clock_sync_state", + NULL, + "clock synchronization", + NULL, + "System Clock Synchronization State", + "state", + PLUGIN_TIMEX_NAME, + NULL, + NETDATA_CHART_PRIO_CLOCK_SYNC_STATE, + update_every, + RRDSET_TYPE_LINE); + + rd_sync_state = rrddim_add(st_sync_state, "state", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + + rrddim_set_by_pointer(st_sync_state, rd_sync_state, sync_state != TIME_ERROR ? 1 : 0); + rrdset_done(st_sync_state); + + static RRDSET *st_clock_status = NULL; + + if (unlikely(!st_clock_status)) { + st_clock_status = rrdset_create_localhost( + "system", + "clock_status", + NULL, + "clock synchronization", + NULL, + "System Clock Status", + "status", + PLUGIN_TIMEX_NAME, + NULL, + NETDATA_CHART_PRIO_CLOCK_STATUS, + update_every, + RRDSET_TYPE_LINE); + + for (int i = 0; sta_codes[i].name != NULL; i++) { + sta_codes[i].rd = + rrddim_add(st_clock_status, sta_codes[i].name, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); + } + } + + for (int i = 0; sta_codes[i].name != NULL; i++) + rrddim_set_by_pointer(st_clock_status, sta_codes[i].rd, timex_buf.status & sta_codes[i].code ? 1 : 0); + + rrdset_done(st_clock_status); + } + + if (do_offset) { + static RRDSET *st_offset = NULL; + static RRDDIM *rd_offset; + + if (unlikely(!st_offset)) { + st_offset = rrdset_create_localhost( + "system", + "clock_sync_offset", + NULL, + "clock synchronization", + NULL, + "Computed Time Offset Between Local System and Reference Clock", + "milliseconds", + PLUGIN_TIMEX_NAME, + NULL, + NETDATA_CHART_PRIO_CLOCK_SYNC_OFFSET, + update_every, + RRDSET_TYPE_LINE); + + rd_offset = rrddim_add(st_offset, "offset", NULL, 1, divisor, RRD_ALGORITHM_ABSOLUTE); + } + + rrddim_set_by_pointer(st_offset, rd_offset, timex_buf.offset); + rrdset_done(st_offset); + } + } + +exit: + netdata_thread_cleanup_pop(1); + return NULL; +} |