SIP signaling reference
Use this page when you need which SIP message was logged, where it was captured, or what a response code means on a Delphi deployment. The primary operator surface is the conversation Debug tab SIP ladder in TelWeb; this reference explains what feeds it and how to query the same data in SigNoz.
For TelPro routing, Redis keys, and firewall rules, see TelPro operations. For SigNoz dashboards, PII, and general call investigation, see SigNoz monitoring.
Where to look first
| Surface | Best for |
|---|---|
| TelWeb → conversation → Debug → SIP ladder | Per-call timeline with Outside / TelPro / TelSys lanes, raw message inspector, DTMF chips, and text export. |
| SigNoz Logs | Ad-hoc search by call_id, trace_id, or recordKind=sip_message when you do not have a conversation row open. |
| Container stdout | Last resort when telemetry is missing — docker compose logs voiceai-telpro / voiceai-telsys. |
Correlate with call_id (SIP Call-ID, same value as TelPhi X-Call-ID) and trace_id across TelPro, Voice, and TelAPI.
Three-lane ladder
The Debug SIP ladder reconstructs signaling across three lanes. In v0.9.14-patch3, the Call Detail Debug tab separates Logs, Spans, and SIP Ladder panes; use Export on the SIP Ladder pane when support needs a plain-text capture bundle.
| Lane | Component | Typical peer |
|---|---|---|
| Outside | Carrier trunk or WebRTC (Janus User-Agent: VoiceAI-WebRTC/…) | Public SIP provider, browser voice client |
| TelPro | voiceai-telpro (Kamailio) | Terminates carrier/WebRTC hop, RTPEngine anchor, dispatches to Voice |
| TelSys | voiceai-telsys (Asterisk PJSIP) | Accepts relayed INVITE from Kamailio, bridges to TelPhi via ARI |
TelPro egress toward the carrier (telpro_egress_to_outside) is the source of truth for custom headers applied after TelSys emits a message. TelSys captures may show the pre-mutation copy; Kamailio egress captures show what actually left the platform.
What gets logged
Kamailio (TelPro) — structured [SIP_CAPTURE] JSON
Kamailio writes one JSON object per line to voiceai-telpro stdout for every captured SIP request or response:
| JSON field | Meaning |
|---|---|
recordKind | Always sip_message for ladder captures. |
logType | sip_capture |
service / service.component | telpro / kamailio |
capturePoint | Where in the proxy the message was seen — see Capture points. |
sipCallId / callId | SIP Call-ID (use as call_id in SigNoz). |
trace_id | Distributed trace id (WebRTC calls may be updated from Redis after TelAPI validation). |
method | SIP method on requests (INVITE, CANCEL, PRACK, …). |
statusCode | Numeric SIP response code on replies (180, 200, 481, …). |
capturedAtMs | Kamailio clock at capture time — used for ladder ordering. |
sip100relReliable / sip100relSupported | RFC 3262 flags when Require: 100rel, RSeq, or PRACK is involved. |
rawMessage | Escaped first line (request or SIP/2.0 … status line). |
Operational routing logs use recordKind=log via the same JSON emitter (LOG_DELPHI) — search by component (for example routing, egress, dispatcher).
Not re-emitted by log-to-span: Kamailio already emits final JSON; the TelPro log-to-span sidecar ingests RTPEngine/Janus spans but skips duplicate Kamailio sip_message lines.
TelSys (Voice) — PJSIP packet traces
When SIP_CAPTURE_ENABLE_PJSIP_LOGGER=1 (default), Asterisk logs multiline PJSIP frames prefixed with:
<--- Received SIP response/request from …→ capture pointtelsys_ingress_from_telpro<--- Transmitting SIP …→ capture pointtelsys_egress_to_telpro
PJSIP output is buffered until the full SIP frame (headers + SDP) is present, so TelSys rows can appear slightly after Kamailio's single-line captures for the same leg.
The Voice host log-to-span sidecar (sipcapture mode) assembles these multiline frames into the same recordKind=sip_message shape and exports OTLP logs with service.name=telsys.
Media and WebRTC (related, not SIP ladder rows)
| Source | Logged as | Use |
|---|---|---|
RTPEngine (voiceai-rtpengine) | Structured media events via TelPro log-to-span | No-audio, one-way audio, codec mismatch |
Janus (voiceai-webrtc) | Janus log config via TelPro log-to-span | WebRTC WSS / SIP-plugin bridge failures |
Pipeline to SigNoz and TelWeb
- OTel collector on TelPro and Voice parses JSON container logs, promotes Kamailio records to
service.name=telpro, and forwards to SigNoz. - TelAPI loads captures for a conversation trace, deduplicates Kamailio worker duplicates, merges TelPro ↔ TelSys legs, and builds ladder events.
- Tasker persists the ladder snapshot after call end (delay
SIGNOZ_SIP_LADDER_PERSIST_DELAY_SECONDS, default 90s) so support can reopen it after SigNoz retention expires.
SIP ladder logs are not PII-scrubbed — raw SIP text is kept intentionally for routing debug. See SigNoz monitoring → PII.
Capture points
| Capture point | Component | Meaning |
|---|---|---|
telpro_ingress_from_outside | Kamailio | Request or response from carrier / WebRTC side |
telpro_egress_to_telsys | Kamailio | Forwarded toward TelSys |
telpro_ingress_from_telsys | Kamailio | Reply received from TelSys |
telpro_egress_to_outside | Kamailio | Forwarded toward carrier / WebRTC (carrier header source of truth) |
telpro_local_response | Kamailio | Locally generated reply (sl_send_reply, OPTIONS keepalive, validation failures) |
telsys_ingress_from_telpro | TelSys PJSIP | Received from TelPro |
telsys_egress_to_telpro | TelSys PJSIP | Sent toward TelPro |
Matching TelPro egress and TelSys ingress (same method + CSeq) collapse to one ladder row with up to two raw captures in the inspector.
SigNoz query patterns
Starting filters (adjust time range to the call window):
service.name = "telpro" AND attributes.callId = "<call-id>"
attributes.recordKind = "sip_message" AND attributes.callId = "<call-id>"
service.name = "telsys" AND attributes.callId = "<call-id>"
attributes.trace_id = "<trace-id>" AND attributes.recordKind = "sip_message"
Older deployments may still index Kamailio under service.name = "kamailio" before collector promotion — try both if a query returns empty.
Hide OPTIONS health checks in TelWeb by default; enable Show health-check SIP (OPTIONS) on the ladder tab when debugging carrier keepalives.
SIP methods — scenarios
| Method | Typical role on Delphi | Where it appears |
|---|---|---|
| OPTIONS | Out-of-dialog keepalive / reachability probe. Kamailio answers proxy OPTIONS with 200 OK (telpro_local_response). In-dialog OPTIONS relay like other mid-dialog methods. | Often hidden in TelWeb; visible in SigNoz or with health-check toggle. |
| INVITE | Call setup (inbound carrier, outbound transfer, WebRTC leg). | First row of a new dialog; pairs with 100 Trying → 180/183 → 200 OK. |
| PRACK | RFC 3262 acknowledgment of a reliable provisional (180/183 with Require: 100rel). Kamailio relays in-dialog PRACK; ladder label PRACK (100rel). | TelPro + TelSys when SIP_100REL_MODE is not off. |
| UPDATE | Mid-call SDP or session-timer refresh. | TelSys ↔ TelPro during hold, codec renegotiation, or session timers. |
| ACK | Confirms final response to INVITE. Ladder marks Call connected after first ACK following 200 OK. | Required for dialog establishment. |
| BYE | Normal hangup from either side. | Ladder Call disconnected divider prefers BYE, then CANCEL, then TelPhi hangup logs. |
| CANCEL | Cancels an unanswered or ringing INVITE (UAC side). Kamailio matches or rejects with 481 if no transaction exists. RTPEngine session may be deleted on matched CANCEL. | Common on caller abandon before answer. |
| REFER | Blind or attended transfer toward carrier/PBX. TelPhi publishes egress intents; Kamailio applies headers before telpro_egress_to_outside. | Transfer failures — correlate TelPhi action logs. |
| INFO | DTMF or feature payloads (carrier-dependent). | DTMF timeline merges INFO bodies with RFC4733 SDP and TelPhi dtmf_received. |
| NOTIFY / SUBSCRIBE | Uncommon on default flows; relayed when present. | Check carrier integration docs. |
RFC 3262 (100rel / PRACK)
Controlled on TelSys via SIP_100REL_MODE (PJSIP endpoint 100rel):
| Value | Behavior |
|---|---|
off | Default — no PRACK / reliable provisionals. |
peer_supported | Reliable 180/183 only when peer sends Supported: 100rel. Start here for carriers that expect PRACK. |
yes | Always send reliable provisionals toward TelPro. |
required | Strict 100rel on the TelSys leg. |
Kamailio logs [SIP_100REL] debug lines and sets sip100relReliable / sip100relSupported on captures. TelWeb labels reliable 1xx and PRACK as (100rel).
SIP response codes — operator reference
Use response codes as evidence along the ladder, not as application error codes. The first failing response on the Outside or TelPro ingress lane usually explains why no conversation was created.
1xx — Provisional
| Code | Meaning | Delphi notes |
|---|---|---|
| 100 | Trying | Kamailio auto_inv_100 may appear as telpro_local_response while routing to TelSys. |
| 180 | Ringing | 180 Ringing (upstream) when first seen on telpro_ingress_from_outside. Append (100rel) when 100rel headers present. |
| 183 | Session progress | Early media possible; check RTPEngine spans if audio starts before answer. |
2xx — Success
| Code | Meaning | Delphi notes |
|---|---|---|
| 200 | OK | INVITE answered — look for following ACK to mark connected phase. |
4xx — Client / dialog errors
| Code | Phrase | Typical cause on Delphi |
|---|---|---|
| 403 | Forbidden | TelSys source IP not in Kamailio allowlist — check SMEMBERS voiceai:telsys:server_ips. |
| 404 | Not Found | Unknown base number / trunk, or egress target not in Redis. |
| 408 | Request Timeout | Carrier or egress member timeout; outbound pools may fail over to next member on 408 or 5xx. |
| 481 | Call/Transaction Does Not Exist | Kamailio-generated when a late CANCEL, ACK, or stray in-dialog request does not match an active transaction (see sl_send_reply("481", …) on unmatched CANCEL). Often benign on teardown races — compare CSeq and timing. |
| 486 | Busy Here | Callee busy or policy rejection from TelSys/carrier. |
| 487 | Request Terminated | INVITE transaction cancelled — usually follows a matched CANCEL (caller hung up while ringing). |
| 488 | Not Acceptable Here | Codec / SDP mismatch — check trunk codec preferences and RTPEngine offer. |
5xx — Server / proxy errors
| Code | Phrase | Typical cause on Delphi |
|---|---|---|
| 500 | Server Internal Error | TelSys or carrier internal failure — inspect TelSys logs at the same timestamp. |
| 503 | Service Unavailable | No healthy Voice dispatcher target, TelPro misconfig, or carrier overload. |
6xx — Global failure
| Code | Phrase | Typical cause on Delphi |
|---|---|---|
| 603 | Decline | Carrier or policy explicitly declined the call — TelPhi transfer mapping may classify as declined. |
If capturePoint is telpro_local_response, Kamailio generated the code (routing validation, OPTIONS, unmatched CANCEL). If the code appears on telpro_ingress_from_outside, it came from the carrier or WebRTC peer. If on telpro_ingress_from_telsys, TelSys/Asterisk generated it before Kamailio relayed outward.
Configuration
| Variable | Service | Default | Purpose |
|---|---|---|---|
SIP_CAPTURE_ENABLE_PJSIP_LOGGER | Voice | 1 | Asterisk PJSIP packet logging for TelSys ladder lane |
SIP_100REL_MODE | Voice | off | PRACK / reliable provisional mode toward TelPro |
SIP_CAPTURE_MAX_MESSAGE_BYTES | log-to-span | 65536 | Max assembled SIP frame size |
SIP_CAPTURE_MAX_BUFFER_AGE_MS | log-to-span | 5000 | PJSIP fragment assembly timeout |
SIGNOZ_SIP_LADDER_PERSIST_DELAY_SECONDS | Tasker | 90 | Delay before persisting ladder snapshot |
LOG_TO_SPAN_EXPORT_LOGS | TelPro | false | Export parsed SIP as OTLP logs in addition to spans — increases volume |
TELPRO_LOG_LEVEL | TelPro | LOG_LEVEL | Raises Kamailio routing verbosity — use briefly; SIP captures remain independent |
RTPENGINE_LOG_LEVEL | TelPro | LOG_LEVEL | RTPEngine media log verbosity, mapped from Pino labels |
WEBRTC_LOG_LEVEL | TelPro | LOG_LEVEL | Janus WebRTC log verbosity, mapped from Pino labels |
Container log access
When SigNoz is unavailable:
# TelPro — JSON sip_message lines (grep Call-ID or capturePoint)
docker compose logs voiceai-telpro 2>&1 | grep '"recordKind": "sip_message"'
# Voice — raw PJSIP frames
docker compose logs voiceai-telsys 2>&1 | grep -E 'Received SIP|Transmitting SIP'
Raise TELPRO_LOG_LEVEL=debug on TelPro only for short windows — routing LOG_DELPHI lines add volume but do not replace [SIP_CAPTURE] rows.
See also
- SigNoz monitoring — dashboards, alerts, Debug tab workflow, DTMF timeline.
- TelPro operations — SIP edge routing, Redis keys, transfers, firewall.
- Voice operations — TelSys, ARI,
SIP_100REL_MODEenv bundle. - SIP trunks (admin) — inbound trunk identification and TLS.
- Egress trunks — outbound transfer routing pools.