Skip to main content

Export signalling and call quality

sipx exposes the observations and leaves storage, dashboards, labels and retention to the application. It does not bundle a metrics backend. That boundary keeps a collector outage or slow backend out of the call path and lets an embedding application use the telemetry system it already operates.

Send signalling to a HEP3 collector

HEP3 is an optional sink on the existing sipx-transport capture path. Configure the local pcapng file first, then attach the collector:

use sipx_transport::{CaptureConfig, Config, HepConfig};

let mut transport = Config::new("0.0.0.0:5060".parse()?);
transport.capture = Some(
CaptureConfig::new("/var/lib/sipx/signalling.pcapng").with_hep(HepConfig::new(
"192.0.2.40:9060".parse()?,
42,
)),
);

Export is off by default. When enabled, the transport stamps the message once, applies the same redaction used by the local capture, and hands the record to one bounded writer queue. The HEP UDP socket is non-blocking. A full queue or unavailable collector drops and counts the export instead of delaying a SIP timer or failing a call; inspect Handle::counters().capture.hep_dropped and hep_records.

Redaction is mandatory for HEP export. Digest responses, opaque authorization credentials, SDP key material, push tokens and instance identifiers are removed before the HEP payload leaves the process. Combining HEP with CaptureConfig::without_redaction() is rejected before the endpoint binds. Redaction does not anonymize a call: identities, addresses, routes and timing remain, so use a trusted network path to the collector and apply the collector's access controls.

The pcapng file is retained as the reliable local diagnostic record. HEP uses best-effort UDP and sipx does not retry, acknowledge or create an unbounded delivery queue for it.

Feed RTCP quality into your telemetry

Install a callback on a running call. The callback receives the peer's report for this RTP stream: interval loss, cumulative loss, jitter as a Duration, and an optional round-trip time.

use sipx_media::RtcpQualityHook;

let (quality_tx, mut quality_rx) = tokio::sync::mpsc::channel(64);
call.set_rtcp_quality_hook(Some(RtcpQualityHook::new(move |sample| {
// Never block the RTCP worker. The application owns this queue and its drop policy.
let _ = quality_tx.try_send(sample);
})));

while let Some(sample) = quality_rx.recv().await {
record_quality_in_your_backend(sample).await;
}

The callback runs only after an RTCP packet has passed authentication when SRTCP is active and has parsed successfully. A report about another SSRC is ignored. Round trip remains None until the peer echoes a sender report; sipx never substitutes zero for missing evidence.

The hook belongs to the logical call. It remains installed across an ordinary re-INVITE, a re-INVITE that replaces the media session, and an ICE restart. A callback must return promptly; put blocking aggregation or network work behind a bounded application queue as in the example. If application callback code panics, sipx logs it and keeps the RTCP worker alive.