Skip to main content
Version: Next — legacy draft snapshot

Application and call-flow logging

Retained Next source

This page preserves the merged Next documentation snapshot at e1ddcf6940adb7b619ce509063749e740eecc795. It can describe implementation beyond the source revision selected for the rebuilt Next guides. Retain the implementation-scope notes below and confirm your deployed version before applying these details. This is not a current-release availability or deployment claim. For the task-based entry point, see the rebuilt guide.

Use this page to understand what is logged during a call’s application and media path, what each log level means, and how to correlate those logs with SIP signaling. It covers TelSys (voice PBX), TelPro (SIP edge), and RTPEngine (media).

For JSON field names, SigNoz queries, and per-service *_LOG_LEVEL variables, see Monitoring in SigNoz. For SIP ladder captures and response codes, see SIP signaling reference.

Purpose​

Structured logs let operators reconstruct:

  • Call lifecycle on the voice PBX (answer, AI session, hangup, transfer)
  • Edge routing and call-control outcomes (trunk/number selection, outbound transfer, BYE handling, failover)
  • Media quality and media-layer failures (MOS, ICE/DTLS/SRTP, DTMF)

Together with the Debug SIP ladder, these logs support end-to-end investigation of a single conversation.

Log levels​

SigNoz uses canonical uppercase severity labels. Raw Pino JSON can retain lowercase level values; the collector normalizes telemetry severity. See severity casing and historical records.

LevelMeaning
ERRORFailed call path or hard failure (auth reject, media/control failure).
WARNDegraded but recoverable (failover, sticky miss, non-SUCCESS transfer, poor MOS).
INFONormal lifecycle milestones (call start/end, successful route, hangup).
DEBUGTroubleshooting detail (session teardown chatter, temporary verbosity).
TRACERare deep diagnostics.
FATALProcess- or edge-level unrecoverable failure.

Control verbosity with the global LOG_LEVEL or service overrides such as TELSYS_LOG_LEVEL, TELPRO_LOG_LEVEL, RTPENGINE_LOG_LEVEL, and TELPHI_LOG_LEVEL. See Per-service log levels and the environment variable index.

SIP ladder capture is independent of general log verbosity: lowering info/warn filtering does not remove sip_message captures used by the Debug SIP ladder.

Correlation​

Use the same identifiers across TelPro, TelSys, media, and application logs:

IdentifierUse
trace_idDistributed trace across edge, voice, and app logs.
sipCallIdSIP Call-ID (also shown as call id in TelWeb / Debug).
ConversationTelWeb conversation id when investigating from a call detail page.

Start from TelWeb Conversations → call detail → Debug (Logs / Spans / SIP ladder), then search SigNoz with the same trace_id, Call-ID, or transactionId.

What is logged​

TelSys (voice PBX)​

Call and AI-session lifecycle events (typically info):

AreaExamplesTypical level
Call entryCall start, channel created, channel answerinfo
AI sessionSession enter / exit with the voice AI appinfo
HangupHangup with cause / optional hangup reasoninfo
TransferTransfer initiated; transfer resultinfo / warn if not SUCCESS
Dialplan errorsError-handling pathserror

Operational bootstrap and config notes use operational log records (see Structured logging schema).

TelPro (SIP edge)​

Routing and call-control outcomes (not the raw SIP frames — those are in the SIP ladder):

AreaExamplesTypical level
Ingress / routingTrunk identified, number/customer route, server selectedinfo
RejectsUnknown trunk, TLS/auth failure, unverified internal sourcewarn / error
Outbound / transferOutbound or direct-URI transfer detected or rejectedinfo / warn
BYE / disconnectCarrier-bound BYE routing; loop prevention when edge misroutesinfo / warn / error
FailoverTelSys server failure, failover attempt or abortwarn / error
Media control (via TelPro)RTPEngine offer / answer success or failureinfo / error

RTPEngine (media)​

Data-plane media outcomes. Control-plane offer/answer commands are logged from TelPro (see SigNoz monitoring).

AreaExamplesTypical level
Call qualityEnd-of-call stats (rtpengine_call_stats: MOS, jitter, loss)info; warn / error when MOS is poor
Media errorsICE / DTLS / SRTP failureserror
Resource errorsPort / socket exhaustionerror
Control errorsUnknown call, offer/answer rejected at the media engineerror
DTMFRFC4733 media DTMF eventsinfo
Session endMedia session teardown noticesdebug

Transaction logging schema​

Next implementation scope

The transaction fields and explicit security-event tagging described below refer to platform PR 554 (internal implementation reference), reviewed at commit 300e8a9956ada4ac628fd5fceda13855510a73b0. They are not a statement that the current released platform or a customer deployment contains that change. Confirm the deployed implementation before relying on these fields; source checks do not establish live ingestion or delivery.

Instrumented application-level interactions within a conversation emit transaction records for the legs their producer observes. An outbound exchange can produce request-out and response-in records, but transport failure, missing context or an uninstrumented host can leave a partial sequence. The implemented paths include bot traffic, speech services, webhooks and HTTP tool calls; Limits and gaps describes coverage boundaries.

Transaction records are ordinary structured log entries extended with the properties below. There is no parallel log format and no separate logType, so existing SigNoz queries, TelWeb log-type chips, and the AppLog sink are unchanged; the new properties are additive and appear only on records that carry them.

Properties​

The helper requires category, logpoint, component and operation; other context and transport fields are conditional. Undefined inputs are omitted, not emitted as empty values. Aliases are added only when their source value exists and do not overwrite an explicit value. “Response only” means the field is eligible on a response, not guaranteed on every response.

PropertyTypeValue and notesPresent on
categorystringbot, stt, tts, sip — plus the Delphi extensions webhook (a webhook exchange that is not a bot platform call) and http (any other outbound HTTP call made on behalf of a conversation). A transaction record gets its category from the emitting service; the collector sets sip on SIP captures, which are not transaction records.All legs
logpointstringrequest-in, request-out, response-in, response-out. See directions.All legs
servicestringEmitting component (telphi, telapi, tasker, telpro, …).When available from producer/context
server-namestringInstance that executed the transaction (the container host name).When available from producer/context
operationstringExecuted operation, for example create_conversation, send_message, synthesize, fetch. On system-style records it is also written to the structural action field.All legs
verbstringHTTP verb of the request (GET, POST, …); WS for a websocket lifecycle event.When available from producer/context
urlstringTarget URL. Credentials in the query string are scrubbed before the record is written.When available from producer/context
botNamestringBot or app that owns the conversation.When available from producer/context
transaction-IdstringAlias of transactionId when supplied by the producer/context; its scope depends on that producer. Do not infer one universal per-exchange or per-conversation lifetime.When available from producer/context
conversation-idstringDelphi conversation id. Alias of conversationId.When available from producer/context
call-idstringAlias of callId, falling back to sipCallId when callId is null/undefined. callId can be a Delphi call/session ID or a producer-specific SIP ID; this alias is not universally the SIP Call-ID.When available from producer/context
trace-idstringDistributed trace id. Alias of trace_id, and the string to search on — the OTLP collector removes the trace_id attribute itself.When available from producer/context
caller-idstringIdentifier of the credentials in use (for example the variable key name) — not the caller’s number, and never the secret value.When available from producer/context
payloadstringRequest or response body, redacted and truncated. See Payload and detail policy.Flag or failure
headersobjectRequest or response headers, redacted. Same switch as payload.Flag or failure
statusstringsuccess or error. The ticket’s ok is spelled success here, because the logger derives the log level from this value.Response legs when supplied
status-codenumberResponse status code. Alias of statusCode.Response legs when supplied
durationnumberResponse latency in milliseconds. Alias of durationMs — on a response leg only, because durationMs means something else on other records.Response legs when supplied
timestampnumberEvent time in epoch milliseconds, the platform convention, for filtering and ordering.All records
timestamp-isostringThe same time as ISO-8601 with offset, for example 2026-07-28T12:13:06.301+02:00. Delphi writes millisecond precision.When available from producer/context
attemptnumber1-based attempt number, present only when the request was retried.Retried requests
bodyOnlyboolMarks a companion record that carries only a successful response body.Success path

Available aliases are written alongside their canonical fields; an explicit alias is not overwritten. A missing source identifier remains absent.

logpoint directions​

logpoint is read from Delphi’s point of view, so the same category can appear in both directions — for example a bot send_message is request-out, the bot platform’s reply is response-in.

logpointMeaningExample
request-inSomething called us.Inbound bot-platform webhook at TelAPI.
request-outWe called someone.send_message to the bot platform, synthesize to TTS, a sandbox tool fetch.
response-inThe answer to our request.The bot platform’s HTTP reply; a websocket upgrade or close.
response-outOur answer to an inbound request.The TelAPI webhook reply.

Finding transaction records only​

Transaction records are exactly the records that carry a logpoint, so filter on its presence:

logpoint IS NOT NULL

The retry-control records (provider_request_retry, provider_request_error) deliberately carry no logpoint, so retry noise never appears in that result set. Within it, key alarms on the response-in record that carries status-code: on the success path a companion bodyOnly record may be written after it when the response body was buffered, and that companion has no status-code.

Limits and gaps​

  • STT has no HTTP path. Both STT providers are websocket-only, so speech-to-text cannot produce an HTTP verb, a request payload, or an ordinary status-code. Its transaction records are the websocket lifecycle (request-out at connect, response-in at open or close) with verb: WS; the upgrade response supplies status-code where there is one.
  • A websocket transport yields lifecycle records only — one request-out and one response-in per connection, never one record per frame.
  • Payloads are guaranteed on error and best-effort on success. Binary audio and JSON-lines streams are never buffered; such a record carries status, duration and the content type instead of the body.
  • SIP capture records are categorised, not transactions. The SIP edge does not emit transaction records: the OTLP collector tags recordKind=sip_message captures with category: "sip". They carry no logpoint, because a SIP frame is not one of the four transaction legs and a fabricated leg would put non-transaction traffic into the transaction-record result set. Correlate a capture by trace_id and SIP Call-ID instead — see Correlation.
  • Not every HTTP call is a transaction. Only interactions within a conversation are recorded. Service-level calls such as an access-token fetch are logged as ordinary structured logs.
  • The inbound webhook leg carries no headers map. The TelAPI callback projects the headers that identify the exchange onto named fields (transaction-Id, call-id, botName) instead, so a callback token value can never reach a transaction record.
  • Flow-engine runner records depend on the host that runs the flow. The engine emits them only when the flow host injects a logger, and never throws when it does not: TelPhi's in-call flow host injects one, TelAPI web-chat sessions do not.

Payload and detail policy​

PolicyBehavior
Metadata alwaysThe payload switch does not suppress supplied metadata. URL, verb, status codes, bot identity and handling labels remain conditional on the producer/context; requests do not gain response-only fields.
Bodies on failureAt instrumented failure paths, the producer can force available payloads and headers even with LOG_INTEGRATION_PAYLOADS=false. Missing body/header inputs stay absent; the helper does not reconstruct them.
LOG_INTEGRATION_PAYLOADSSet to true to also log payloads and headers on successful legs. Default false. Set per service (the same variable name in each service’s deployment), so it can be raised for one service and one short support window. Expect higher volume and cost.
PIIRedaction before SigNoz export is controlled separately — see PII redaction.
LOG_INTEGRATION_PAYLOADS is a volume control, not a privacy control

Transaction payloads are PII-bearing by construction. Speech transcripts and TTS bodies go through the transcript classifier and are stored as [REDACTED] unless ENABLE_PII_LOGGING=true; credentials in headers and query strings (authorization, Ocp-Apim-Subscription-Key, cookies, tokens, API keys) are always redacted, whatever either switch says, and bodies are truncated before storage. As defence in depth the OTLP collector replaces every payload value with [REDACTED] while ENABLE_PII_LOGGING is not true, in each of the three envelopes a record can arrive in (the flat attribute, metadata.payload, pino.payload). The payload flag controls volume; it is not a privacy guarantee. Review emitted fields and effective redaction before enabling it.

Security-relevant events​

Security-relevant events are marked with two log attributes, so they can be selected directly instead of by the wording of a message: security_event = true, plus one of four security_category values (authentication, authorization, audit, certificate). Filter on security_event in SigNoz. Security event export has the full contract, the action-to-category mapping, and what is deliberately not exported.

The integration-side refusals that reach this path are Kamailio's trunk-admission rejects, logged as structured warn or error records:

Eventsecurity_categoryRefused because
trunk_identify_failedcertificateThe peer's TLS certificate or identity did not verify
trunk_identify_failedauthorizationThe trunk is unknown or unauthorized to this platform
trunk_call_rejectedauthenticationThe trunk requires an X-Call-ID and it was invalid or missing
xcall_invalidauthenticationA Janus call's X-Call-ID had no entry, so it did not resolve
xcall_missingauthenticationA Janus call arrived without an X-Call-ID at all

Application-side refusals — failed sign-ins, session terminations, permission denials — are emitted as security events by the services themselves through @delphi/logger, and carry the same attributes. They are not SIP-level events, so they are not listed here.

Not recorded as structured logs. Five further rejects in kamailio.cfg are written with xlog only. They produce a plain log line, are dropped before the structured log path, and therefore cannot be tagged or exported: the transfer-from-unverified-source rejects (kamailio.cfg:617, :646), authentication misconfiguration (:810), source IP not authorized (:816), and digest username mismatch (:835). There is no BYE self-relay reject at all — the route that would classify one is defined and never called. Making these exportable means emitting them as structured records, which is a change to the voice application and its image.

Where to look​

SurfaceBest for
TelWeb → conversation → DebugPer-call logs, spans, and SIP ladder for one conversation.
SigNoz LogsCross-call search by trace_id, Call-ID, level, or event.
SIP signaling referenceWhich SIP messages were captured and what response codes mean.
Monitoring in SigNozSchema keys, log-level env vars, dashboards, and PII.

Integration-specific field mapping​

Log field value definitions​

These generic value tables describe the Next implementation scope above.

category — the integration domain the event belongs to:

ValueMeaning
sttSpeech-to-text: audio → text (recognize / streaming recognition).
ttsText-to-speech: text → audio (synthesize / streaming synthesis).
sipSIP signaling / call control (invite, bye, register, …).
webhookDelphi extension: a webhook exchange that is not a bot platform interaction.
httpDelphi extension: any other outbound HTTP call made on behalf of a conversation — a flow runner, a sandbox tool fetch.

logpoint — which leg of the exchange the record is. See logpoint directions for the full table; the four values are request-in, request-out, response-in, response-out. The implemented spelling is response-out.

service — the Delphi component that emitted the event:

ValueComponent
telproSIP edge / SBC (Kamailio).
telsysVoice PBX (Asterisk).
telphiVoice AI application (STT / TTS / bot orchestration).
telwebWeb UI.
taskerBackground task runner.
scalerAutoscaling.
rtpengineMedia engine (data plane; control-plane offer/answer is logged from telpro).
audioprocAudio processing.
portalPortal.

operation — the executed operation, per category. Representative values; the exact value is always on the record's operation field, which is also written to the structural action.

categoryRepresentative operations
botcreate_conversation, send_message, end_conversation, refresh_access_token
sttconnect, transcribe (websocket lifecycle — see limits)
ttssynthesize, connect
sipSIP methods: invite, ack, bye, cancel, register, update, reinvite
webhookexecute (flow-engine webhook runner)
httpfetch (sandbox tool), execute (flow-engine LLM query runner), conversation scoring

Cross-service logging schema​

Canonical Node service names: telpro, telsys, telphi, telapi, telweb, tasker, scaler.

Telephony (Kamailio / TelSys) uses a parallel JSON shape with recordKind:

recordKindMeaning
logOperational / lifecycle event
traceCall-lifecycle span-like event (TelSys dialplan)
sip_messageCaptured SIP frame for the Debug ladder

App logs from @delphi/logger use logType values such as conversation, model_usage, system, telephony, audio, error, audit, and cdr, plus injected trace_id / span_id. See Service logs and Monitoring in SigNoz.

Transaction records are this same app-log shape — they add the properties above to the existing entries rather than introducing a new logType, which is why no log-type chip, dashboard, or sink changed. Remaining instrumentation gaps require separate implementation and verification.