PTP Metrics Exporter API v1

This section contains the API reference for the PTP Metrics Exporter.

The application pod runs as a DaemonSet on nodes labeled ptp-metrics-exporter=enabled. It collects PTP synchronization statistics from ptp4l (via UDS), phc2sys and ts2phc (via monitoring sockets), and exposes them in OpenMetrics format.

For in-cluster access (e.g., from Prometheus or other monitoring tools), use the Kubernetes service DNS name:

ptp-metrics-exporter.ptp-metrics-exporter.svc.cluster.local:9110

This headless service (clusterIP: None) resolves directly to the pod IPs of the exporter DaemonSet on each node. Individual pods can also be reached via their host IP or pod IP on port 9110.

Endpoints

GET
/metrics

Get all PTP metrics for the node

Provides OpenMetrics-formatted statistics for all PTP instances configured on the node, including ptp4l, phc2sys, and ts2phc sources.

Normal response codes

200

Request parameters

None

Response parameters

PTP statistics in OpenMetrics format.

# HELP ptp_exporter_build Exporter build identification
# TYPE ptp_exporter_build info
ptp_exporter_build_info{node="controller-0",python="3.11.15",version="1.0.0"} 1.0
# HELP ptp_grandmaster_clock_class IEEE 1588 Grandmaster clock class
# TYPE ptp_grandmaster_clock_class gauge
ptp_grandmaster_clock_class{domain="0",gm_identity="001e67fffe0a1234",instance="ptpinst0",node="controller-0"} 6.0
# HELP ptp_grandmaster_clock_accuracy IEEE 1588 Grandmaster clock accuracy
# TYPE ptp_grandmaster_clock_accuracy gauge
ptp_grandmaster_clock_accuracy{domain="0",gm_identity="001e67fffe0a1234",instance="ptpinst0",node="controller-0"} 33.0
# HELP ptp_grandmaster_clock_variance IEEE 1588 Grandmaster offset scaled log variance
# TYPE ptp_grandmaster_clock_variance gauge
ptp_grandmaster_clock_variance{domain="0",gm_identity="001e67fffe0a1234",instance="ptpinst0",node="controller-0"} 20061.0
# HELP ptp_grandmaster_priority1 BMCA Grandmaster Priority1
# TYPE ptp_grandmaster_priority1 gauge
ptp_grandmaster_priority1{domain="0",gm_identity="001e67fffe0a1234",instance="ptpinst0",node="controller-0"} 128.0
# HELP ptp_grandmaster_priority2 BMCA Grandmaster Priority2
# TYPE ptp_grandmaster_priority2 gauge
ptp_grandmaster_priority2{domain="0",gm_identity="001e67fffe0a1234",instance="ptpinst0",node="controller-0"} 128.0
# HELP ptp_grandmaster_identity Grandmaster clock identity
# TYPE ptp_grandmaster_identity info
ptp_grandmaster_identity_info{domain="0",gm_identity="001e67fffe0a1234",iface="ens1f0",instance="ptpinst0",node="controller-0"} 1.0
# HELP ptp_time_traceable 1 if time is traceable to a primary reference, 0 otherwise
# TYPE ptp_time_traceable gauge
ptp_time_traceable{domain="0",instance="ptpinst0",node="controller-0"} 1.0
# HELP ptp_sync_state 1 if synchronized, 0 otherwise
# TYPE ptp_sync_state gauge
ptp_sync_state{domain="0",instance="ptpinst0",node="controller-0"} 1.0
# HELP ptp_offset_from_master_ns PTP slave clock offset to master in nanoseconds
# TYPE ptp_offset_from_master_ns gauge
ptp_offset_from_master_ns{domain="0",instance="ptpinst0",node="controller-0"} -42.0
# HELP ptp_mean_path_delay_ns Mean path delay in nanoseconds
# TYPE ptp_mean_path_delay_ns gauge
ptp_mean_path_delay_ns{domain="0",instance="ptpinst0",node="controller-0"} 312.0
# HELP ptp_port_state IEEE 1588 port state enumeration
# TYPE ptp_port_state gauge
ptp_port_state{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 9.0
# HELP ptp_offset_rms_ns RMS of PTP offset in nanoseconds
# TYPE ptp_offset_rms_ns gauge
ptp_offset_rms_ns{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 51.0
# HELP ptp_offset_mean_ns Mean PTP offset in nanoseconds
# TYPE ptp_offset_mean_ns gauge
ptp_offset_mean_ns{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} -10.0
# HELP ptp_offset_stddev_ns Standard deviation of PTP offset in nanoseconds
# TYPE ptp_offset_stddev_ns gauge
ptp_offset_stddev_ns{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 50.0
# HELP ptp_instance_summary_interval summary_interval config value (0=no meaningful aggregation)
# TYPE ptp_instance_summary_interval gauge
ptp_instance_summary_interval{domain="0",instance="ptpinst0",node="controller-0"} 6.0
# HELP ptp_sync_messages_received Total Sync messages received
# TYPE ptp_sync_messages_received counter
ptp_sync_messages_received_total{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 15230.0
# HELP ptp_sync_messages_lost Total Sync messages lost (sequence gaps)
# TYPE ptp_sync_messages_lost counter
ptp_sync_messages_lost_total{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 0.0
# HELP ptp_sync_timeout_events Total Sync timeout events
# TYPE ptp_sync_timeout_events counter
ptp_sync_timeout_events_total{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 0.0
# HELP ptp_announce_timeout_events Total announce timeout events
# TYPE ptp_announce_timeout_events counter
ptp_announce_timeout_events_total{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 2.0
# HELP ptp_sync_mismatch Total Sync/FollowUp mismatch events
# TYPE ptp_sync_mismatch counter
ptp_sync_mismatch_total{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 0.0
# HELP ptp_followup_mismatch Total FollowUp mismatch events
# TYPE ptp_followup_mismatch counter
ptp_followup_mismatch_total{domain="0",iface="ens1f0",instance="ptpinst0",node="controller-0"} 0.0
# HELP ptp_gm_transition Total Grandmaster identity transitions
# TYPE ptp_gm_transition counter
ptp_gm_transition_total{domain="0",instance="ptpinst0",node="controller-0"} 1.0
# HELP ptp_phc_adjustment_ns Servo-filtered PHC-to-system-clock offset in nanoseconds
# TYPE ptp_phc_adjustment_ns gauge
ptp_phc_adjustment_ns{clock="ens1f0",domain="0",instance="phcinst0",node="controller-0"} 54.0
# HELP ptp_phc_delay_ns Estimated delay between PHC and system clock in nanoseconds
# TYPE ptp_phc_delay_ns gauge
ptp_phc_delay_ns{clock="ens1f0",domain="0",instance="phcinst0",node="controller-0"} 0.0
# HELP ptp_phc_offset_rms_ns Windowed RMS of PHC-to-system-clock offset in nanoseconds
# TYPE ptp_phc_offset_rms_ns gauge
ptp_phc_offset_rms_ns{clock="ens1f0",domain="0",instance="phcinst0",node="controller-0"} 73.0
# HELP ptp_phc_offset_stddev_ns Windowed standard deviation of PHC offset in nanoseconds
# TYPE ptp_phc_offset_stddev_ns gauge
ptp_phc_offset_stddev_ns{clock="ens1f0",domain="0",instance="phcinst0",node="controller-0"} 35.0
# HELP ptp_phc_offset_max_abs_ns Maximum absolute offset in current stats window in nanoseconds
# TYPE ptp_phc_offset_max_abs_ns gauge
ptp_phc_offset_max_abs_ns{clock="ens1f0",domain="0",instance="phcinst0",node="controller-0"} 105.0
# HELP ptp_phc_offset_num_samples Number of samples in most recent stats window
# TYPE ptp_phc_offset_num_samples gauge
ptp_phc_offset_num_samples{clock="ens1f0",domain="0",instance="phcinst0",node="controller-0"} 8.0
# HELP ptp_phc2sys_utc_offset_seconds TAI-UTC offset configured for phc2sys (-O option)
# TYPE ptp_phc2sys_utc_offset_seconds gauge
ptp_phc2sys_utc_offset_seconds{instance="phcinst0",node="controller-0"} 37.0
# HELP ptp_ts2phc_offset_ns ts2phc servo offset in nanoseconds
# TYPE ptp_ts2phc_offset_ns gauge
ptp_ts2phc_offset_ns{clock="NMEA0",instance="tsinst0",node="controller-0"} 150.0
# HELP ptp_ts2phc_delay_ns ts2phc delay in nanoseconds (-1 = unavailable)
# TYPE ptp_ts2phc_delay_ns gauge
ptp_ts2phc_delay_ns{clock="NMEA0",instance="tsinst0",node="controller-0"} -1.0
# HELP ptp_exporter_collection_errors Number of failed collection attempts
# TYPE ptp_exporter_collection_errors counter
ptp_exporter_collection_errors_total{instance="ptpinst0",node="controller-0"} 0.0
ptp_exporter_collection_errors_total{instance="phcinst0",node="controller-0"} 0.0
ptp_exporter_collection_errors_total{instance="tsinst0",node="controller-0"} 0.0
# HELP ptp_exporter_collection_duration_seconds Duration of most recent collection cycle
# TYPE ptp_exporter_collection_duration_seconds gauge
ptp_exporter_collection_duration_seconds{instance="ptpinst0",node="controller-0"} 0.000453
ptp_exporter_collection_duration_seconds{instance="phcinst0",node="controller-0"} 0.001012
ptp_exporter_collection_duration_seconds{instance="tsinst0",node="controller-0"} 0.000142
# HELP ptp_exporter_source_state Probe state: 0=unknown, 1=enabled, 2=disabled
# TYPE ptp_exporter_source_state gauge
ptp_exporter_source_state{instance="ptpinst0",node="controller-0",source="offset_stats_np"} 1.0
ptp_exporter_source_state{instance="ptpinst0",node="controller-0",source="sync_lost_field"} 1.0
ptp_exporter_source_state{instance="phcinst0",node="controller-0",source="phc2sys_mon_socket"} 1.0
ptp_exporter_source_state{instance="tsinst0",node="controller-0",source="ts2phc_mon_socket"} 1.0
# HELP ptp_exporter_last_success_seconds Unix timestamp of last successful collection
# TYPE ptp_exporter_last_success_seconds gauge
ptp_exporter_last_success_seconds{instance="ptpinst0",node="controller-0"} 1.7836136875e+09
ptp_exporter_last_success_seconds{instance="phcinst0",node="controller-0"} 1.7836136868e+09
ptp_exporter_last_success_seconds{instance="tsinst0",node="controller-0"} 1.7836136870e+09
# EOF
GET
/healthz

Health check (liveness)

Returns 200 if the exporter process is alive. Used as the Kubernetes liveness probe target.

Normal response codes

200

GET
/readyz

Readiness check

Returns 200 after the first successful collection cycle completes. Returns 503 during startup before any data is available. Used as the Kubernetes readiness probe target.

Normal response codes

200

Error response codes

serviceUnavailable (503)

Deployment Prerequisites

  1. linuxptp patches — The host must run the patched linuxptp that provides:

    • Read-only UDS socket for ptp4l (uds_ro_address)

    • OFFSET_STATS_NP management TLV (summary_interval > 0)

    • PORT_SERVICE_STATS_NP with sync_lost field

    • Monitoring socket for phc2sys (mon_socket_path)

    • Monitoring socket for ts2phc (mon_socket_path)

  2. PTP instance configuration — Config files must exist at /etc/linuxptp/ptpinstance/ in the format:

    • ptp4l-<instance>.conf — contains uds_ro_address in [global]

    • phc2sys-<instance>.conf — contains mon_socket_path in [global]

    • ts2phc-<instance>.conf — contains mon_socket_path in [global]

  3. Node label — Target nodes must be labeled:

    ~(keystone_admin)]$ system host-label-assign <hostname> ptp-metrics-exporter=enabled
    
  4. Application upload and apply:

    ~(keystone_admin)]$ system application-upload ptp-metrics-exporter-<version>.tgz
    ~(keystone_admin)]$ system application-apply ptp-metrics-exporter
    

Configuration Parameters

The exporter is configured via Helm chart values. Overrides can be applied using system helm-override-update.

Parameter

Default

Description

exporter.collectionIntervalPtp4lSeconds

60

How often (seconds) to poll ptp4l via UDS

exporter.collectionIntervalPhc2sysSeconds

60

How often (seconds) to poll phc2sys monitoring socket

exporter.collectionIntervalTs2phcSeconds

60

How often (seconds) to poll ts2phc monitoring socket

exporter.npProbeIntervalSeconds

60

How often to re-probe disabled data sources (e.g., OFFSET_STATS_NP)

exporter.ptp4lClockClassLockedList

"6,7,135"

Comma-separated clock classes considered “locked” for sync_state

exporter.logLevel

INFO

Log verbosity (DEBUG, INFO, WARNING, ERROR)

service.port

9110

TCP port for the metrics HTTP endpoint

nodeSelector.ptp-metrics-exporter

"enabled"

Node label selector for DaemonSet scheduling

resources.requests.cpu

0

CPU request

resources.limits.cpu

200m

CPU limit

resources.requests.memory

0

Memory request

resources.limits.memory

128Mi

Memory limit

Override example:

~(keystone_admin)]$ system helm-override-update ptp-metrics-exporter \
    ptp-metrics-exporter ptp-metrics-exporter \
    --set exporter.collectionIntervalPtp4lSeconds=2

Then re-apply:

~(keystone_admin)]$ system application-apply ptp-metrics-exporter

Metrics Reference

Grandmaster Quality

Metric

Type

Labels

Description

ptp_grandmaster_clock_class

Gauge

domain, gm_identity, instance, node

IEEE 1588 clock class (6=locked, 7=holdover, 135=holdover-in-spec)

ptp_grandmaster_clock_accuracy

Gauge

domain, gm_identity, instance, node

IEEE 1588 clock accuracy enumeration

ptp_grandmaster_clock_variance

Gauge

domain, gm_identity, instance, node

Scaled log variance of GM offset

ptp_grandmaster_priority1

Gauge

domain, gm_identity, instance, node

BMCA Priority1 field

ptp_grandmaster_priority2

Gauge

domain, gm_identity, instance, node

BMCA Priority2 field

ptp_grandmaster_identity

Info

domain, gm_identity, iface, instance, node

GM clock identity (info metric, value always 1)

ptp_time_traceable

Gauge

domain, instance, node

1 if time is traceable to primary reference, 0 otherwise

Sync Quality

Metric

Type

Labels

Description

ptp_offset_from_master_ns

Gauge

domain, instance, node

Current slave-to-master offset (nanoseconds)

ptp_mean_path_delay_ns

Gauge

domain, instance, node

Mean path delay (nanoseconds)

ptp_sync_state

Gauge

domain, instance, node

1=synchronized, 0=not synchronized, NaN=unknown

ptp_port_state

Gauge

domain, iface, instance, node

IEEE 1588 port state (9=SLAVE, 6=MASTER, 3=LISTENING, etc.)

Offset Stability (requires summary_interval > 0)

Metric

Type

Labels

Description

ptp_offset_rms_ns

Gauge

domain, iface, instance, node

Root mean square of offset over summary window

ptp_offset_mean_ns

Gauge

domain, iface, instance, node

Mean offset over summary window

ptp_offset_stddev_ns

Gauge

domain, iface, instance, node

Standard deviation of offset over summary window

ptp_instance_summary_interval

Gauge

domain, instance, node

Configured summary_interval value (0=no meaningful aggregation)

phc2sys Servo

Metric

Type

Labels

Description

ptp_phc_adjustment_ns

Gauge

clock, domain, instance, node

PHC-to-system-clock servo offset (nanoseconds)

ptp_phc_delay_ns

Gauge

clock, domain, instance, node

Estimated delay between PHC and system clock

ptp_phc_offset_rms_ns

Gauge

clock, domain, instance, node

Windowed RMS of PHC offset

ptp_phc_offset_stddev_ns

Gauge

clock, domain, instance, node

Windowed standard deviation of PHC offset

ptp_phc_offset_max_abs_ns

Gauge

clock, domain, instance, node

Maximum absolute offset in stats window

ptp_phc_offset_num_samples

Gauge

clock, domain, instance, node

Number of samples in stats window

ptp_phc2sys_utc_offset_seconds

Gauge

instance, node

TAI-UTC offset configured for phc2sys (-O option)

ts2phc (GNSS-synced GM nodes)

Metric

Type

Labels

Description

ptp_ts2phc_offset_ns

Gauge

instance, clock, node

ts2phc servo offset (nanoseconds)

ptp_ts2phc_delay_ns

Gauge

instance, clock, node

ts2phc delay (-1 sentinel = delay unavailable)

Message Sync/Loss Counters

Metric

Type

Labels

Description

ptp_sync_messages_received_total

Counter

domain, iface, instance, node

Total Sync messages received

ptp_sync_messages_lost_total

Counter

domain, iface, instance, node

Expected Sync messages not received (sequence gaps)

ptp_sync_timeout_events_total

Counter

domain, iface, instance, node

Port state changes due to sync timeout

ptp_announce_timeout_events_total

Counter

domain, iface, instance, node

Announce receipt timeout events

ptp_sync_mismatch_total

Counter

domain, iface, instance, node

Sync/FollowUp mismatch events

ptp_followup_mismatch_total

Counter

domain, iface, instance, node

FollowUp mismatch events

ptp_gm_transition_total

Counter

domain, instance, node

Number of Grandmaster identity transitions

Self-Monitoring

Metric

Type

Labels

Description

ptp_exporter_collection_errors_total

Counter

instance, node

Failed collection attempts per instance

ptp_exporter_collection_duration_seconds

Gauge

instance, node

Duration of most recent collection cycle

ptp_exporter_source_state

Gauge

instance, node, source

Probe state: 0=unknown, 1=enabled, 2=disabled

ptp_exporter_last_success_seconds

Gauge

instance, node

Unix timestamp of last successful collection

ptp_exporter_build_info

Info

node, version, python

Build identification

Troubleshooting

Exporter pods not scheduling

Verify the node label:

~(keystone_admin)]$ system host-label-list <hostname> | grep ptp-metrics-exporter

If missing, assign it:

~(keystone_admin)]$ system host-label-assign <hostname> ptp-metrics-exporter=enabled

Metrics returning NaN

  • ptp4l not running or UDS socket missing: check that /var/run/ptp4l-<instance>-ro exists on the host.

  • phc2sys/ts2phc not patched: verify mon_socket_path is present in the daemon config and the socket file exists.

  • summary_interval not configured or set to 0: stability metrics (ptp_offset_rms_ns, ptp_offset_mean_ns, ptp_offset_stddev_ns) will report NaN because no meaningful aggregation occurs with a single sample.

Collection errors incrementing

Check ptp_exporter_source_state:

  • 0 (unknown) — probe pending, will be attempted at next NP_PROBE_INTERVAL_S boundary.

  • 1 (enabled) — source healthy and being collected.

  • 2 (disabled) — source returned error on probe. Will re-probe periodically. Check that the daemon is running and socket exists.

Pod CrashLoopBackOff

Check logs:

~(keystone_admin)]$ kubectl -n ptp-metrics-exporter logs -l app=ptp-metrics-exporter

Verifying metrics endpoint manually

From the host:

~(keystone_admin)]$ curl http://<pod-ip>:9110/metrics
~(keystone_admin)]$ curl http://<pod-ip>:9110/healthz
~(keystone_admin)]$ curl http://<pod-ip>:9110/readyz

Architecture Note

The exporter runs as a DaemonSet with one pod per labeled node. Each pod:

  1. Watches /host/etc/linuxptp/ptpinstance/ for config file changes (inotify)

  2. For each discovered ptp4l instance, polls via SOCK_DGRAM UDS at the configured interval

  3. For each phc2sys/ts2phc instance, connects to the monitoring socket (SOCK_STREAM, JSON protocol)

  4. Stores collected data in an in-memory snapshot (not on-demand per HTTP request)

  5. Serves /metrics from the snapshot — HTTP serving never blocks on collection

Volume mounts:

Container Path

Host Path

Mode

Purpose

/var/run

/var/run

RW

UDS sockets (exporter creates reply socket for DGRAM)

/host/proc

/proc

RO

psutil reads phc2sys/ts2phc cmdline for config discovery

/host/etc/linuxptp/ptpinstance

/etc/linuxptp/ptpinstance

RO

Configuration watcher (inotify)

/tmp

emptyDir (memory-backed, 32Mi)

RW

Python tempfiles

Security context:

  • Runs as non-root (UID 65534 / nobody)

  • Read-only root filesystem

  • All Linux capabilities dropped

  • No privilege escalation