Skip to main content
Version: 0.9.14

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

SurfaceBest for
TelWeb → conversation → Debug → SIP ladderPer-call timeline with Outside / TelPro / TelSys lanes, raw message inspector, DTMF chips, and text export.
SigNoz LogsAd-hoc search by call_id, trace_id, or recordKind=sip_message when you do not have a conversation row open.
Container stdoutLast 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.

LaneComponentTypical peer
OutsideCarrier trunk or WebRTC (Janus User-Agent: VoiceAI-WebRTC/…)Public SIP provider, browser voice client
TelProvoiceai-telpro (Kamailio)Terminates carrier/WebRTC hop, RTPEngine anchor, dispatches to Voice
TelSysvoiceai-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 fieldMeaning
recordKindAlways sip_message for ladder captures.
logTypesip_capture
service / service.componenttelpro / kamailio
capturePointWhere in the proxy the message was seen — see Capture points.
sipCallId / callIdSIP Call-ID (use as call_id in SigNoz).
trace_idDistributed trace id (WebRTC calls may be updated from Redis after TelAPI validation).
methodSIP method on requests (INVITE, CANCEL, PRACK, …).
statusCodeNumeric SIP response code on replies (180, 200, 481, …).
capturedAtMsKamailio clock at capture time — used for ladder ordering.
sip100relReliable / sip100relSupportedRFC 3262 flags when Require: 100rel, RSeq, or PRACK is involved.
rawMessageEscaped 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 point telsys_ingress_from_telpro
  • <--- Transmitting SIP … → capture point telsys_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.

SourceLogged asUse
RTPEngine (voiceai-rtpengine)Structured media events via TelPro log-to-spanNo-audio, one-way audio, codec mismatch
Janus (voiceai-webrtc)Janus log config via TelPro log-to-spanWebRTC WSS / SIP-plugin bridge failures

Pipeline to SigNoz and TelWeb

  1. OTel collector on TelPro and Voice parses JSON container logs, promotes Kamailio records to service.name=telpro, and forwards to SigNoz.
  2. TelAPI loads captures for a conversation trace, deduplicates Kamailio worker duplicates, merges TelPro ↔ TelSys legs, and builds ladder events.
  3. 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 pointComponentMeaning
telpro_ingress_from_outsideKamailioRequest or response from carrier / WebRTC side
telpro_egress_to_telsysKamailioForwarded toward TelSys
telpro_ingress_from_telsysKamailioReply received from TelSys
telpro_egress_to_outsideKamailioForwarded toward carrier / WebRTC (carrier header source of truth)
telpro_local_responseKamailioLocally generated reply (sl_send_reply, OPTIONS keepalive, validation failures)
telsys_ingress_from_telproTelSys PJSIPReceived from TelPro
telsys_egress_to_telproTelSys PJSIPSent 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

MethodTypical role on DelphiWhere it appears
OPTIONSOut-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.
INVITECall setup (inbound carrier, outbound transfer, WebRTC leg).First row of a new dialog; pairs with 100 Trying180/183200 OK.
PRACKRFC 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.
UPDATEMid-call SDP or session-timer refresh.TelSys ↔ TelPro during hold, codec renegotiation, or session timers.
ACKConfirms final response to INVITE. Ladder marks Call connected after first ACK following 200 OK.Required for dialog establishment.
BYENormal hangup from either side.Ladder Call disconnected divider prefers BYE, then CANCEL, then TelPhi hangup logs.
CANCELCancels 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.
REFERBlind or attended transfer toward carrier/PBX. TelPhi publishes egress intents; Kamailio applies headers before telpro_egress_to_outside.Transfer failures — correlate TelPhi action logs.
INFODTMF or feature payloads (carrier-dependent).DTMF timeline merges INFO bodies with RFC4733 SDP and TelPhi dtmf_received.
NOTIFY / SUBSCRIBEUncommon on default flows; relayed when present.Check carrier integration docs.

RFC 3262 (100rel / PRACK)

Controlled on TelSys via SIP_100REL_MODE (PJSIP endpoint 100rel):

ValueBehavior
offDefault — no PRACK / reliable provisionals.
peer_supportedReliable 180/183 only when peer sends Supported: 100rel. Start here for carriers that expect PRACK.
yesAlways send reliable provisionals toward TelPro.
requiredStrict 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

CodeMeaningDelphi notes
100TryingKamailio auto_inv_100 may appear as telpro_local_response while routing to TelSys.
180Ringing180 Ringing (upstream) when first seen on telpro_ingress_from_outside. Append (100rel) when 100rel headers present.
183Session progressEarly media possible; check RTPEngine spans if audio starts before answer.

2xx — Success

CodeMeaningDelphi notes
200OKINVITE answered — look for following ACK to mark connected phase.

4xx — Client / dialog errors

CodePhraseTypical cause on Delphi
403ForbiddenTelSys source IP not in Kamailio allowlist — check SMEMBERS voiceai:telsys:server_ips.
404Not FoundUnknown base number / trunk, or egress target not in Redis.
408Request TimeoutCarrier or egress member timeout; outbound pools may fail over to next member on 408 or 5xx.
481Call/Transaction Does Not ExistKamailio-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.
486Busy HereCallee busy or policy rejection from TelSys/carrier.
487Request TerminatedINVITE transaction cancelled — usually follows a matched CANCEL (caller hung up while ringing).
488Not Acceptable HereCodec / SDP mismatch — check trunk codec preferences and RTPEngine offer.

5xx — Server / proxy errors

CodePhraseTypical cause on Delphi
500Server Internal ErrorTelSys or carrier internal failure — inspect TelSys logs at the same timestamp.
503Service UnavailableNo healthy Voice dispatcher target, TelPro misconfig, or carrier overload.

6xx — Global failure

CodePhraseTypical cause on Delphi
603DeclineCarrier or policy explicitly declined the call — TelPhi transfer mapping may classify as declined.
Upstream vs local

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

VariableServiceDefaultPurpose
SIP_CAPTURE_ENABLE_PJSIP_LOGGERVoice1Asterisk PJSIP packet logging for TelSys ladder lane
SIP_100REL_MODEVoiceoffPRACK / reliable provisional mode toward TelPro
SIP_CAPTURE_MAX_MESSAGE_BYTESlog-to-span65536Max assembled SIP frame size
SIP_CAPTURE_MAX_BUFFER_AGE_MSlog-to-span5000PJSIP fragment assembly timeout
SIGNOZ_SIP_LADDER_PERSIST_DELAY_SECONDSTasker90Delay before persisting ladder snapshot
LOG_TO_SPAN_EXPORT_LOGSTelProfalseExport parsed SIP as OTLP logs in addition to spans — increases volume
TELPRO_LOG_LEVELTelProLOG_LEVELRaises Kamailio routing verbosity — use briefly; SIP captures remain independent
RTPENGINE_LOG_LEVELTelProLOG_LEVELRTPEngine media log verbosity, mapped from Pino labels
WEBRTC_LOG_LEVELTelProLOG_LEVELJanus 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