summaryrefslogtreecommitdiffstats
path: root/src/collectors/timex.plugin
diff options
context:
space:
mode:
Diffstat (limited to 'src/collectors/timex.plugin')
l---------src/collectors/timex.plugin/README.md1
-rw-r--r--src/collectors/timex.plugin/integrations/timex.md143
-rw-r--r--src/collectors/timex.plugin/metadata.yaml112
-rw-r--r--src/collectors/timex.plugin/plugin_timex.c176
4 files changed, 432 insertions, 0 deletions
diff --git a/src/collectors/timex.plugin/README.md b/src/collectors/timex.plugin/README.md
new file mode 120000
index 000000000..89c1bd0d4
--- /dev/null
+++ b/src/collectors/timex.plugin/README.md
@@ -0,0 +1 @@
+integrations/timex.md \ No newline at end of file
diff --git a/src/collectors/timex.plugin/integrations/timex.md b/src/collectors/timex.plugin/integrations/timex.md
new file mode 100644
index 000000000..ce0e0ed2c
--- /dev/null
+++ b/src/collectors/timex.plugin/integrations/timex.md
@@ -0,0 +1,143 @@
+<!--startmeta
+custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/collectors/timex.plugin/README.md"
+meta_yaml: "https://github.com/netdata/netdata/edit/master/src/collectors/timex.plugin/metadata.yaml"
+sidebar_label: "Timex"
+learn_status: "Published"
+learn_rel_path: "Collecting Metrics/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/src/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/netdata-agent/configuration.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/src/collectors/timex.plugin/metadata.yaml b/src/collectors/timex.plugin/metadata.yaml
new file mode 100644
index 000000000..fc11f2d92
--- /dev/null
+++ b/src/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/src/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/src/collectors/timex.plugin/plugin_timex.c b/src/collectors/timex.plugin/plugin_timex.c
new file mode 100644
index 000000000..025b699a1
--- /dev/null
+++ b/src/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;
+}