@cryptotaxi247 / netdata-1 / commits / 244918fa4

Statistics for precision of local chrony

Dominik Schloesser committed Aug 27, 2017 at 18:27 UTC 244918fa4659082141ada17f799f708fad71c625
2 files changed +166
conf.d/python.d/chrony.conf new
+72
@@ -0,0 +1,72 @@
1 +# netdata python.d.plugin configuration for chrony
2 +#
3 +# This file is in YaML format. Generally the format is:
4 +#
5 +# name: value
6 +#
7 +# There are 2 sections:
8 +# - global variables
9 +# - one or more JOBS
10 +#
11 +# JOBS allow you to collect values from multiple sources.
12 +# Each source will have its own set of charts.
13 +#
14 +# JOB parameters have to be indented (using spaces only, example below).
15 +
16 +# ----------------------------------------------------------------------
17 +# Global Variables
18 +# These variables set the defaults for all JOBs, however each JOB
19 +# may define its own, overriding the defaults.
20 +
21 +# update_every sets the default data collection frequency.
22 +# If unset, the python.d.plugin default is used.
23 +update_every: 1
24 +
25 +# priority controls the order of charts at the netdata dashboard.
26 +# Lower numbers move the charts towards the top of the page.
27 +# If unset, the default for python.d.plugin is used.
28 +# priority: 60000
29 +
30 +# retries sets the number of retries to be made in case of failures.
31 +# If unset, the default for python.d.plugin is used.
32 +# Attempts to restore the service are made once every update_every
33 +# and only if the module has collected values in the past.
34 +# retries: 5
35 +
36 +# ----------------------------------------------------------------------
37 +# JOBS (data collection sources)
38 +#
39 +# The default JOBS share the same *name*. JOBS with the same name
40 +# are mutually exclusive. Only one of them will be allowed running at
41 +# any time. This allows autodetection to try several alternatives and
42 +# pick the one that works.
43 +#
44 +# Any number of jobs is supported.
45 +#
46 +# All python.d.plugin JOBS (for all its modules) support a set of
47 +# predefined parameters. These are:
48 +#
49 +# job_name:
50 +# name: myname # the JOB's name as it will appear at the
51 +# # dashboard (by default is the job_name)
52 +# # JOBs sharing a name are mutually exclusive
53 +# update_every: 1 # the JOB's data collection frequency
54 +# priority: 60000 # the JOB's order on the dashboard
55 +# retries: 5 # the JOB's number of restoration attempts
56 +#
57 +# Additionally to the above, chrony also supports the following:
58 +#
59 +# command: 'chrony tracking' # the command to run
60 +#
61 +
62 +# ----------------------------------------------------------------------
63 +# REQUIRED chrony CONFIGURATION
64 +#
65 +# netdata will query chrony as user netdata.
66 +# verify that user netdata is allowed to call 'chronyc tracking'
67 +# Check cmdallow in chrony.conf
68 +# ----------------------------------------------------------------------
69 +# AUTO-DETECTION JOBS
70 +
71 +local:
72 + command: 'chronyc -n tracking'
python.d/chrony.chart.py new
+94
@@ -0,0 +1,94 @@
1 +# -*- coding: utf-8 -*-
2 +# Description: chrony netdata python.d module
3 +# Author: Dominik Schloesser (domschl)
4 +
5 +from base import ExecutableService
6 +
7 +# default module values (can be overridden per job in `config`)
8 +# update_every = 10
9 +priority = 60000
10 +retries = 10
11 +
12 +# charts order (can be overridden if you want less charts, or different order)
13 +ORDER = ['timediff', 'lastoffset', 'rmsoffset', 'rootdelay',
14 + 'rootdispersion', 'skew', 'frequency', 'residualfreq']
15 +
16 +CHARTS = {
17 + # id: {
18 + # 'options': [name, title, units, family, context, charttype],
19 + # 'lines': [
20 + # [unique_dimension_name, name, algorithm, multiplier, divisor]
21 + # ]}
22 + 'timediff': {
23 + 'options': [None, "Difference system time to NTP", "us", 'chrony', 'chrony.timediff', 'line'],
24 + 'lines': [
25 + ['timediff', None, 'absolute', 1, 1000]
26 + ]},
27 + 'lastoffset': {
28 + 'options': [None, "Last offset", "us", 'chrony', 'chrony.lastoffset', 'line'],
29 + 'lines': [
30 + ['lastoffset', None, 'absolute', 1, 1000]
31 + ]},
32 + 'rmsoffset': {
33 + 'options': [None, "RMS offset", "us", 'chrony', 'chrony.rmsoffset', 'line'],
34 + 'lines': [
35 + ['rmsoffset', None, 'absolute', 1, 1000]
36 + ]},
37 + 'rootdelay': {
38 + 'options': [None, "Root delay", "us", 'chrony', 'chrony.rootdelay', 'line'],
39 + 'lines': [
40 + ['rootdelay', None, 'absolute', 1, 1000]
41 + ]},
42 + 'rootdispersion': {
43 + 'options': [None, "Root dispersion", "us", 'chrony', 'chrony.rootdispersion', 'line'],
44 + 'lines': [
45 + ['rootdispersion', None, 'absolute', 1, 1000]
46 + ]},
47 + 'skew': {
48 + 'options': [None, "Skew, error bound on frequency", "ppm", 'chrony', 'chrony.skew', 'line'],
49 + 'lines': [
50 + ['skew', None, 'absolute', 1, 1000]
51 + ]},
52 + 'frequency': {
53 + 'options': [None, "Frequency", "ppm", 'chrony', 'chrony.frequency', 'line'],
54 + 'lines': [
55 + ['frequency', None, 'absolute', 1, 1000]
56 + ]},
57 + 'residualfreq': {
58 + 'options': [None, "Residual frequency", "ppm", 'chrony', 'chrony.residualfreq', 'line'],
59 + 'lines': [
60 + ['residualfreq', None, 'absolute', 1, 1000]
61 + ]}
62 +}
63 +
64 +
65 +class Service(ExecutableService):
66 + def __init__(self, configuration=None, name=None):
67 + ExecutableService.__init__(
68 + self, configuration=configuration, name=name)
69 + self.command = "chronyc -n tracking"
70 + self.order = ORDER
71 + self.definitions = CHARTS
72 + self.error("Chrony netdata started")
73 +
74 + def _get_data(self):
75 + """
76 + Format data received from shell command
77 + :return: dict
78 + """
79 + try:
80 + # self.error("Chrony:" + self._get_raw_data())
81 + chrony_dict = {ln.split(':', 1)[0].strip(): ln.split(':', 1)[1].strip().split(' ')[0]
82 + for ln in self._get_raw_data()[1:]}
83 + return {'timediff': int(float(chrony_dict['System time']) * 1e9),
84 + 'lastoffset': int(float(chrony_dict['Last offset']) * 1e9),
85 + 'rmsoffset': int(float(chrony_dict['RMS offset']) * 1e9),
86 + 'rootdelay': int(float(chrony_dict['Root delay']) * 1e9),
87 + 'rootdispersion': int(float(chrony_dict['Root dispersion']) * 1e9),
88 + 'skew': int(float(chrony_dict['Skew']) * 1e3),
89 + 'frequency': int(float(chrony_dict['Frequency']) * 1e3),
90 + 'residualfreq': int(float(chrony_dict['Residual freq']) * 1e3)
91 + }
92 + except (ValueError, AttributeError):
93 + self.error("Chrony parser exception")
94 + return None