Add a plugin for the system clock synchronization state (#10895)
Co-authored-by: Joel Hans <joel.g.hans@gmail.com>
Vladimir Kobal committed
Apr 14, 2021 at 12:20 UTC
7de64f49ff88375f76c253c8cc50ec4f07e5a806
15 files changed
+304
-32
CMakeLists.txt
+6
@@ -458,6 +458,11 @@ set(DISKSPACE_PLUGIN_FILES
458
collectors/diskspace.plugin/plugin_diskspace.c
459
)
460
461
+set(TIMEX_PLUGIN_FILES
462
+ collectors/timex.plugin/plugin_timex.h
463
+ collectors/timex.plugin/plugin_timex.c
464
+ )
465
+
466
set(FREEIPMI_PLUGIN_FILES
467
collectors/freeipmi.plugin/freeipmi_plugin.c
468
)
@@ -984,6 +989,7 @@ IF(LINUX)
989
add_executable(netdata config.h ${NETDATA_FILES}
990
${CGROUPS_PLUGIN_FILES}
991
${DISKSPACE_PLUGIN_FILES}
992
+ ${TIMEX_PLUGIN_FILES}
993
${PROC_PLUGIN_FILES}
994
${TC_PLUGIN_FILES}
995
)
Makefile.am
+6
@@ -258,6 +258,11 @@ DISKSPACE_PLUGIN_FILES = \
258
collectors/diskspace.plugin/plugin_diskspace.c \
259
$(NULL)
260
261
+TIMEX_PLUGIN_FILES = \
262
+ collectors/timex.plugin/plugin_timex.h \
263
+ collectors/timex.plugin/plugin_timex.c \
264
+ $(NULL)
265
+
266
FREEIPMI_PLUGIN_FILES = \
267
collectors/freeipmi.plugin/freeipmi_plugin.c \
268
$(LIBNETDATA_FILES) \
@@ -714,6 +719,7 @@ if LINUX
719
NETDATA_FILES += \
720
$(CGROUPS_PLUGIN_FILES) \
721
$(DISKSPACE_PLUGIN_FILES) \
722
+ $(TIMEX_PLUGIN_FILES) \
723
$(PROC_PLUGIN_FILES) \
724
$(TC_PLUGIN_FILES) \
725
$(NULL)
collectors/COLLECTORS.md
+33
-29
@@ -26,35 +26,38 @@ issues](https://github.com/netdata/netdata/issues). Use the search bar to look f
26
collector—we may be looking for contributions from users such as yourself! If you don't see the collector there, make a
27
[feature request](https://community.netdata.cloud/c/feature-requests/7/none) on our community forums.
28
29
-- [Service and application collectors](#service-and-application-collectors)
30
- - [APM (application performance monitoring)](#apm-application-performance-monitoring)
31
- - [Containers and VMs](#containers-and-vms)
32
- - [Data stores](#data-stores)
33
- - [Distributed computing](#distributed-computing)
34
- - [Email](#email)
35
- - [Kubernetes](#kubernetes)
36
- - [Logs](#logs)
37
- - [Messaging](#messaging)
38
- - [Network](#network)
39
- - [Provisioning](#provisioning)
40
- - [Remote devices](#remote-devices)
41
- - [Search](#search)
42
- - [Storage](#storage)
43
- - [Web](#web)
44
-- [System collectors](#system-collectors)
45
- - [Applications](#applications)
46
- - [Disks and filesystems](#disks-and-filesystems)
47
- - [eBPF (extended Berkeley Packet Filter)](#ebpf)
48
- - [Hardware](#hardware)
49
- - [Memory](#memory)
50
- - [Networks](#networks)
51
- - [Processes](#processes)
52
- - [Resources](#resources)
53
- - [Users](#users)
54
-- [Netdata collectors](#netdata-collectors)
55
-- [Orchestrators](#orchestrators)
56
-- [Third-party collectors](#third-party-collectors)
57
-- [Etc](#etc)
29
+- [Supported collectors list](#supported-collectors-list)
30
+ - [Service and application collectors](#service-and-application-collectors)
31
+ - [Generic](#generic)
32
+ - [APM (application performance monitoring)](#apm-application-performance-monitoring)
33
+ - [Containers and VMs](#containers-and-vms)
34
+ - [Data stores](#data-stores)
35
+ - [Distributed computing](#distributed-computing)
36
+ - [Email](#email)
37
+ - [Kubernetes](#kubernetes)
38
+ - [Logs](#logs)
39
+ - [Messaging](#messaging)
40
+ - [Network](#network)
41
+ - [Provisioning](#provisioning)
42
+ - [Remote devices](#remote-devices)
43
+ - [Search](#search)
44
+ - [Storage](#storage)
45
+ - [Web](#web)
46
+ - [System collectors](#system-collectors)
47
+ - [Applications](#applications)
48
+ - [Disks and filesystems](#disks-and-filesystems)
49
+ - [eBPF](#ebpf)
50
+ - [Hardware](#hardware)
51
+ - [Memory](#memory)
52
+ - [Networks](#networks)
53
+ - [Operating systems](#operating-systems)
54
+ - [Processes](#processes)
55
+ - [Resources](#resources)
56
+ - [Users](#users)
57
+ - [Netdata collectors](#netdata-collectors)
58
+ - [Orchestrators](#orchestrators)
59
+ - [Third-party collectors](#third-party-collectors)
60
+ - [Etc](#etc)
61
62
## Service and application collectors
63
@@ -366,6 +369,7 @@ The Netdata Agent can collect these system- and hardware-level metrics using a v
369
- [Device mapper](/collectors/proc.plugin/README.md): Gather metrics about the Linux device mapper with the proc
370
collector.
371
- [Disk space](/collectors/diskspace.plugin/README.md): Collect disk space usage metrics on Linux mount points.
372
+- [Clock synchronization](/collectors/timex.plugin/README.md): Collect the system clock synchronization status on Linux.
373
- [Files and directories](https://learn.netdata.cloud/docs/agent/collectors/go.d.plugin/modules/filecheck): Gather
374
metrics about the existence, modification time, and size of files or directories.
375
- [ioping.plugin](/collectors/ioping.plugin/README.md): Measure disk read/write latency.
collectors/Makefile.am
+1
@@ -10,6 +10,7 @@ SUBDIRS = \
10
checks.plugin \
11
cups.plugin \
12
diskspace.plugin \
13
+ timex.plugin \
14
fping.plugin \
15
ioping.plugin \
16
freebsd.plugin \
collectors/REFERENCE.md
+1
@@ -96,6 +96,7 @@ This section features a list of Netdata's plugins, with a boolean setting to ena
96
# PYTHONPATH environment variable =
97
# proc = yes
98
# diskspace = yes
99
+ # timex = yes
100
# cgroups = yes
101
# tc = yes
102
# idlejitter = yes
collectors/all.h
+4
@@ -12,6 +12,7 @@
12
#include "idlejitter.plugin/plugin_idlejitter.h"
13
#include "cgroups.plugin/sys_fs_cgroup.h"
14
#include "diskspace.plugin/plugin_diskspace.h"
15
+#include "timex.plugin/plugin_timex.h"
16
#include "proc.plugin/plugin_proc.h"
17
#include "tc.plugin/plugin_tc.h"
18
#include "macos.plugin/plugin_macos.h"
@@ -53,6 +54,8 @@
54
#define NETDATA_CHART_PRIO_SYSTEM_SOFT_INTR 1100 // freebsd only
55
#define NETDATA_CHART_PRIO_SYSTEM_ENTROPY 1000
56
#define NETDATA_CHART_PRIO_SYSTEM_UPTIME 1000
57
+#define NETDATA_CHART_PRIO_CLOCK_SYNC_STATE 1100
58
+#define NETDATA_CHART_PRIO_CLOCK_SYNC_OFFSET 1110
59
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_QUEUES 1200 // freebsd only
60
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_MESSAGES 1201
61
#define NETDATA_CHART_PRIO_SYSTEM_IPC_MSQ_SIZE 1202
@@ -339,6 +342,7 @@
342
#define NETDATA_CHART_PRIO_CHECKS 99999
343
344
#define NETDATA_CHART_PRIO_NETDATA_DISKSPACE 132020
345
+#define NETDATA_CHART_PRIO_NETDATA_TIMEX 132030
346
#define NETDATA_CHART_PRIO_NETDATA_TC_CPU 135000
347
#define NETDATA_CHART_PRIO_NETDATA_TC_TIME 135001
348
collectors/timex.plugin/Makefile.am
new
+8
@@ -0,0 +1,8 @@
1
+# SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+AUTOMAKE_OPTIONS = subdir-objects
4
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5
+
6
+dist_noinst_DATA = \
7
+ README.md \
8
+ $(NULL)
collectors/timex.plugin/README.md
new
+29
@@ -0,0 +1,29 @@
1
+<!--
2
+title: "timex.plugin"
3
+description: "Monitor the system clock synchronization state."
4
+custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/timex.plugin/README.md
5
+-->
6
+
7
+# timex.plugin
8
+
9
+This plugin monitors the system clock synchronization state on Linux nodes.
10
+
11
+This plugin creates two charts:
12
+
13
+- System clock synchronization state
14
+- Computed time offset between local system and reference clock
15
+
16
+## Configuration
17
+
18
+Edit the `netdata.conf` configuration file using [`edit-config`](/docs/configure/nodes.md#use-edit-config-to-edit-configuration-files) from the [Netdata config directory](/docs/configure/nodes.md#the-netdata-config-directory), which is typically at `/etc/netdata`.
19
+
20
+Scroll down to the `[plugin:timex]` section to find the available options:
21
+
22
+```
23
+[plugin:timex]
24
+ # update every = 1
25
+ # clock synchronization state = yes
26
+ # time offset = yes
27
+```
28
+
29
+[](<>)
collectors/timex.plugin/plugin_timex.c
new
+176
@@ -0,0 +1,176 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#include "plugin_timex.h"
4
+#include "sys/timex.h"
5
+
6
+#define PLUGIN_TIMEX_NAME "timex.plugin"
7
+
8
+#define CONFIG_SECTION_TIMEX "plugin:timex"
9
+
10
+static void timex_main_cleanup(void *ptr)
11
+{
12
+ struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;
13
+ static_thread->enabled = NETDATA_MAIN_THREAD_EXITING;
14
+
15
+ info("cleaning up...");
16
+
17
+ static_thread->enabled = NETDATA_MAIN_THREAD_EXITED;
18
+}
19
+
20
+void *timex_main(void *ptr)
21
+{
22
+ netdata_thread_cleanup_push(timex_main_cleanup, ptr);
23
+
24
+ int vdo_cpu_netdata = config_get_boolean(CONFIG_SECTION_TIMEX, "timex plugin resource charts", CONFIG_BOOLEAN_YES);
25
+
26
+ int update_every = (int)config_get_number(CONFIG_SECTION_TIMEX, "update every", 10);
27
+ if (update_every < localhost->rrd_update_every)
28
+ update_every = localhost->rrd_update_every;
29
+
30
+ int do_sync = config_get_boolean(CONFIG_SECTION_TIMEX, "clock synchronization state", CONFIG_BOOLEAN_YES);
31
+ int do_offset = config_get_boolean(CONFIG_SECTION_TIMEX, "time offset", CONFIG_BOOLEAN_YES);
32
+
33
+ if (unlikely(do_sync == CONFIG_BOOLEAN_NO && do_offset == CONFIG_BOOLEAN_NO)) {
34
+ info("No charts to show");
35
+ goto exit;
36
+ }
37
+
38
+ usec_t step = update_every * USEC_PER_SEC;
39
+ heartbeat_t hb;
40
+ heartbeat_init(&hb);
41
+ while (!netdata_exit) {
42
+ usec_t duration = heartbeat_monotonic_dt_to_now_usec(&hb);
43
+ heartbeat_next(&hb, step);
44
+
45
+ struct timex timex_buf = {};
46
+ int sync_state = 0;
47
+ sync_state = adjtimex(&timex_buf);
48
+
49
+ collected_number divisor = USEC_PER_MS;
50
+ if (timex_buf.status & STA_NANO)
51
+ divisor = NSEC_PER_MSEC;
52
+
53
+ // ----------------------------------------------------------------
54
+
55
+ if (do_sync) {
56
+ static RRDSET *st_sync_state = NULL;
57
+ static RRDDIM *rd_sync_state;
58
+
59
+ if (unlikely(!st_sync_state)) {
60
+ st_sync_state = rrdset_create_localhost(
61
+ "system",
62
+ "clock_sync_state",
63
+ NULL,
64
+ "clock synchronization",
65
+ NULL,
66
+ "System Clock Synchronization State",
67
+ "state",
68
+ PLUGIN_TIMEX_NAME,
69
+ NULL,
70
+ NETDATA_CHART_PRIO_CLOCK_SYNC_STATE,
71
+ update_every,
72
+ RRDSET_TYPE_LINE);
73
+
74
+ rd_sync_state = rrddim_add(st_sync_state, "state", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
75
+ } else {
76
+ rrdset_next(st_sync_state);
77
+ }
78
+
79
+ rrddim_set_by_pointer(st_sync_state, rd_sync_state, sync_state != TIME_ERROR ? 1 : 0);
80
+ rrdset_done(st_sync_state);
81
+ }
82
+
83
+ if (do_sync) {
84
+ static RRDSET *st_offset = NULL;
85
+ static RRDDIM *rd_offset;
86
+
87
+ if (unlikely(!st_offset)) {
88
+ st_offset = rrdset_create_localhost(
89
+ "system",
90
+ "clock_sync_offset",
91
+ NULL,
92
+ "clock synchronization",
93
+ NULL,
94
+ "Computed Time Offset Between Local System and Reference Clock",
95
+ "milliseconds",
96
+ PLUGIN_TIMEX_NAME,
97
+ NULL,
98
+ NETDATA_CHART_PRIO_CLOCK_SYNC_OFFSET,
99
+ update_every,
100
+ RRDSET_TYPE_LINE);
101
+
102
+ rd_offset = rrddim_add(st_offset, "offset", NULL, 1, divisor, RRD_ALGORITHM_ABSOLUTE);
103
+ } else {
104
+ rrdset_next(st_offset);
105
+ }
106
+
107
+ rrddim_set_by_pointer(st_offset, rd_offset, timex_buf.offset);
108
+ rrdset_done(st_offset);
109
+ }
110
+
111
+ if (vdo_cpu_netdata) {
112
+ static RRDSET *stcpu_thread = NULL, *st_duration = NULL;
113
+ static RRDDIM *rd_user = NULL, *rd_system = NULL, *rd_duration = NULL;
114
+
115
+ // ----------------------------------------------------------------
116
+
117
+ struct rusage thread;
118
+ getrusage(RUSAGE_THREAD, &thread);
119
+
120
+ if (unlikely(!stcpu_thread)) {
121
+ stcpu_thread = rrdset_create_localhost(
122
+ "netdata",
123
+ "plugin_timex",
124
+ NULL,
125
+ "timex",
126
+ NULL,
127
+ "NetData Timex Plugin CPU usage",
128
+ "milliseconds/s",
129
+ PLUGIN_TIMEX_NAME,
130
+ NULL,
131
+ NETDATA_CHART_PRIO_NETDATA_TIMEX,
132
+ update_every,
133
+ RRDSET_TYPE_STACKED);
134
+
135
+ rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, USEC_PER_MS, RRD_ALGORITHM_INCREMENTAL);
136
+ rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, USEC_PER_MS, RRD_ALGORITHM_INCREMENTAL);
137
+ } else {
138
+ rrdset_next(stcpu_thread);
139
+ }
140
+
141
+ rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * USEC_PER_SEC + thread.ru_utime.tv_usec);
142
+ rrddim_set_by_pointer(
143
+ stcpu_thread, rd_system, thread.ru_stime.tv_sec * USEC_PER_SEC + thread.ru_stime.tv_usec);
144
+ rrdset_done(stcpu_thread);
145
+
146
+ // ----------------------------------------------------------------
147
+
148
+ if (unlikely(!st_duration)) {
149
+ st_duration = rrdset_create_localhost(
150
+ "netdata",
151
+ "plugin_timex_dt",
152
+ NULL,
153
+ "timex",
154
+ NULL,
155
+ "NetData Timex Plugin Duration",
156
+ "milliseconds/run",
157
+ PLUGIN_TIMEX_NAME,
158
+ NULL,
159
+ NETDATA_CHART_PRIO_NETDATA_TIMEX + 1,
160
+ update_every,
161
+ RRDSET_TYPE_AREA);
162
+
163
+ rd_duration = rrddim_add(st_duration, "duration", NULL, 1, USEC_PER_MS, RRD_ALGORITHM_ABSOLUTE);
164
+ } else {
165
+ rrdset_next(st_duration);
166
+ }
167
+
168
+ rrddim_set_by_pointer(st_duration, rd_duration, duration);
169
+ rrdset_done(st_duration);
170
+ }
171
+ }
172
+
173
+exit:
174
+ netdata_thread_cleanup_pop(1);
175
+ return NULL;
176
+}
collectors/timex.plugin/plugin_timex.h
new
+29
@@ -0,0 +1,29 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+#ifndef NETDATA_PLUGIN_TIMEX_H
4
+#define NETDATA_PLUGIN_TIMEX_H
5
+
6
+#include "../../daemon/common.h"
7
+
8
+#if (TARGET_OS == OS_LINUX)
9
+
10
+#define NETDATA_PLUGIN_HOOK_LINUX_TIMEX \
11
+ { \
12
+ .name = "PLUGIN[timex]", \
13
+ .config_section = CONFIG_SECTION_PLUGINS, \
14
+ .config_name = "timex", \
15
+ .enabled = 1, \
16
+ .thread = NULL, \
17
+ .init_routine = NULL, \
18
+ .start_routine = timex_main \
19
+ },
20
+
21
+extern void *timex_main(void *ptr);
22
+
23
+#else // (TARGET_OS == OS_LINUX)
24
+
25
+#define NETDATA_PLUGIN_HOOK_LINUX_TIMEX
26
+
27
+#endif // (TARGET_OS == OS_LINUX)
28
+
29
+#endif //NETDATA_PLUGIN_TIMEX_H
configure.ac
+1
@@ -1561,6 +1561,7 @@ AC_CONFIG_FILES([
1561
collectors/charts.d.plugin/Makefile
1562
collectors/checks.plugin/Makefile
1563
collectors/diskspace.plugin/Makefile
1564
+ collectors/timex.plugin/Makefile
1565
collectors/fping.plugin/Makefile
1566
collectors/ioping.plugin/Makefile
1567
collectors/freebsd.plugin/Makefile
daemon/main.c
+1
@@ -79,6 +79,7 @@ struct netdata_static_thread static_threads[] = {
79
// linux internal plugins
80
NETDATA_PLUGIN_HOOK_LINUX_PROC
81
NETDATA_PLUGIN_HOOK_LINUX_DISKSPACE
82
+ NETDATA_PLUGIN_HOOK_LINUX_TIMEX
83
NETDATA_PLUGIN_HOOK_LINUX_CGROUPS
84
NETDATA_PLUGIN_HOOK_LINUX_TC
85
tests/alarm_repetition/netdata.conf_with_repetition
+1
@@ -29,6 +29,7 @@
29
[plugins]
30
proc = yes
31
diskspace = no
32
+ timex = no
33
cgroups = no
34
tc = no
35
idlejitter = no
tests/alarm_repetition/netdata.conf_without_repetition
+1
@@ -29,6 +29,7 @@
29
[plugins]
30
proc = yes
31
diskspace = no
32
+ timex = no
33
cgroups = no
34
tc = no
35
idlejitter = no
web/gui/dashboard_info.js
+7
-3
@@ -842,6 +842,10 @@ netdataDashboard.context = {
842
info: '<a href="https://en.wikipedia.org/wiki/Entropy_(computing)" target="_blank">Entropy</a>, is a pool of random numbers (<a href="https://en.wikipedia.org/wiki//dev/random" target="_blank">/dev/random</a>) that is mainly used in cryptography. If the pool of entropy gets empty, processes requiring random numbers may run a lot slower (it depends on the interface each program uses), waiting for the pool to be replenished. Ideally a system with high entropy demands should have a hardware device for that purpose (TPM is one such device). There are also several software-only options you may install, like <code>haveged</code>, although these are generally useful only in servers.'
843
},
844
845
+ 'system.clock_sync_state': {
846
+ info: 'State map: 0 - not synchronized, 1 - synchronized'
847
+ },
848
+
849
'system.forks': {
850
colors: '#5555DD',
851
info: 'Number of new processes created.'
@@ -1461,13 +1465,13 @@ netdataDashboard.context = {
1465
info: 'inodes (or index nodes) are filesystem objects (e.g. files and directories). On many types of file system implementations, the maximum number of inodes is fixed at filesystem creation, limiting the maximum number of files the filesystem can hold. It is possible for a device to run out of inodes. When this happens, new files cannot be created on the device, even though there may be free space available.'
1466
},
1467
1468
+ // ------------------------------------------------------------------------
1469
+ // MYSQL
1470
+
1471
'mysql.net': {
1472
info: 'The amount of data sent to mysql clients (<strong>out</strong>) and received from mysql clients (<strong>in</strong>).'
1473
},
1474
1468
- // ------------------------------------------------------------------------
1469
- // MYSQL
1470
-
1475
'mysql.queries': {
1476
info: 'The number of statements executed by the server.<ul>' +
1477
'<li><strong>queries</strong> counts the statements executed within stored SQL programs.</li>' +