topic_metrics
Compute temporal metrics for a DDS topic over a recent time window. Get frequency, sequence gaps, and latency percentiles to inspect ROS2 graph health.
Instructions
Return temporal metrics (frequency, sequence gaps, latency percentiles) for a DDS topic over a recent time window. Returns a TopicMetrics payload carrying status, samples_observed, frequency_hz_observed, frequency_hz_declared, sequence_gaps_count, latency_ns_p50/p95/p99, and boolean availability flags. Read status first: unsupported_user_topic means the topic is a user topic, whose payload is not decoded, so there are no metrics: every number is null or 0 and none of it is a measurement. no_samples_yet means a builtin topic with nothing buffered in the window. ok means metrics were computed. Limits: the buffer is filled only when peek_dds_samples runs on the topic, so frequency_hz_observed reflects how often it was called, not the real publish rate: treat it as a coarse presence signal. frequency_hz_declared is declared, not measured: 1 / deadline of the shortest QoS Deadline a writer on the topic announced in discovery, null when none announced one. Read-only by architecture. Raises an MCP error when no DDS module is active or window_seconds is out of range (1..3600). Right after server start the call waits up to 3 s for discovery to warm up.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| topic | Yes | DDS topic name. Bare DDS names such as `scan` are valid, as are ROS 2 mangled names such as `rt/scan` and the builtin discovery topics `DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`. Letters, digits, `_`, `/` and `::` are allowed; anything else is rejected. | |
| domain_id | No | Accepted for compatibility (0..232). TopicForge observes the domain it joined at startup (TOPICFORGE_DDS_DOMAIN_ID); this argument does not switch domains, and the response `domain_id` says which one was observed. | |
| window_seconds | No | Window in seconds over which to compute metrics (1..3600). Defaults to 60 seconds. Smaller windows reflect more recent state; larger windows smooth transient anomalies. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| topic | Yes | Topic the metrics were computed for. | |
| status | No | How to read the numbers. `unsupported_user_topic`: the topic is a user topic, whose payload is not decoded, so no metric exists and the null fields are not a measurement. `no_samples_yet`: a supported topic with nothing buffered in the window. `ok`: metrics computed from buffered samples. | ok |
| latency_ns_p50 | No | Median publish-to-receive latency in nanoseconds, computed only when the sample type exposes a publish timestamp (typically via `header.stamp` on `Header`-stamped messages). `None` when `latency_available=False`. | |
| latency_ns_p95 | No | 95th-percentile publish-to-receive latency (ns). | |
| latency_ns_p99 | No | 99th-percentile publish-to-receive latency (ns). | |
| mode_effective | Yes | Runtime mode the adapter served this response in: `live` (real ROS2 introspection) or `mock` (deterministic fixtures). Lets a caller tell a real graph from a demo one without calling `health_check`. | |
| window_seconds | Yes | Requested window in seconds (1..3600). Echoed back from the tool call so the LLM can correlate the request. | |
| samples_observed | Yes | Number of samples in the buffer matching `topic` within the window. `0` means TopicForge has not seen any sample on this topic recently: it does NOT mean the topic has no publisher, only that no `peek_dds_samples` call captured one in the window. | |
| latency_available | No | True when at least one sample in the window carried both a publish timestamp and a receive timestamp. The percentile fields are `None` when this is False. | |
| sequence_gaps_count | No | Number of missing sequence numbers detected in the buffered samples. `0` either means no gaps observed OR the sample type did not expose a sequence number (check `sequence_numbers_available` to disambiguate). | |
| frequency_hz_declared | No | Declared, not measured: `1 / deadline` for the shortest QoS Deadline period announced by a writer on this topic in discovery. `None` when no writer announced a finite Deadline or the topic is not announced. It is the rate the application promised, not the rate observed. | |
| frequency_hz_observed | No | `samples_observed / window_seconds_actual`. `None` when fewer than 2 samples were observed (a single sample does not define a frequency). | |
| window_seconds_actual | Yes | Actual elapsed seconds within the window. May be smaller than `window_seconds` when the adapter buffered samples for less time than the requested window (e.g., the server just started). `0.0` when `samples_observed=0`. | |
| sequence_numbers_available | No | True when the adapter successfully extracted sequence numbers from at least one sample. Sequence number support depends on the message type: `Header`-stamped messages with a `seq` field expose it; primitives like `std_msgs/String` do not. |