OpenTelemetry Export (OTLP)
KnoxCall’s integration logging is aligned to OpenTelemetry standards. Every request KnoxCall proxies and every webhook it delivers can be exported, in real time, to your own observability backend over the standard OTLP/HTTP protocol — so the same event stream you see in the dashboard lands in your SIEM with no custom glue.What gets exported
When an OTLP endpoint is configured, KnoxCall emits three signals:Traces
OneSERVER span per HTTP request through the platform, plus dedicated spans for AI Gateway calls (using the OpenTelemetry GenAI semantic conventions) and security events. Spans use the standard HTTP attributes (http.request.method, url.path, http.response.status_code) with KnoxCall-specific context under the knoxcall.* namespace.
KnoxCall participates in W3C distributed tracing:
- Inbound
traceparentheaders are honoured, so a request that arrives already traced continues the same trace. - Outbound calls — both the proxied upstream request and webhook deliveries — carry an injected
traceparent, so the trace extends end-to-end through KnoxCall into your upstream APIs.
Logs (integration logs)
Every proxied request and every webhook delivery is emitted as an OTLPLogRecord:
Severity maps from outcome:
2xx/3xx → INFO, 4xx → WARN, 5xx or transport error → ERROR.
Log records carry the structured envelope (method, path, status, IDs, latency) — not request or response bodies. Full payloads remain (obfuscated) in the API Logs store, so the OTLP stream stays cheap to ship and index.
Metrics (analytics)
Per-request analytics are exported as OTLP metrics on a 60-second interval, so request volume, error rate, and latency show up as native dashboards/monitors in your backend:
On the operator export these carry a
knoxcall.tenant_id dimension; on a per-tenant export (below) they don’t, since every point already belongs to that tenant.
Configuring the endpoint
There are two ways to point KnoxCall at a collector. Environment variables take precedence when set; otherwise the admin-UI integration is used.Option 1 — Admin UI (recommended for self-hosted)
- Go to Settings → Integrations and switch to the Global scope (admins only; available on both cloud and self-hosted deployments).
- Open OpenTelemetry export.
- Fill in:
- OTLP HTTP endpoint — the base URL of your collector, e.g.
https://otlp.your-collector.com. KnoxCall appends/v1/traces,/v1/logs, and/v1/metrics. - Service name (optional) — the resource
service.name(defaults toknoxcall). - Auth headers (optional, encrypted at rest) — comma-separated
key=valuepairs, e.g.Authorization=Bearer <token>, X-Scope-OrgID=acme. - Export traces / logs / metrics — per-signal toggles (all on by default); turn off any signal you don’t want shipped.
- OTLP HTTP endpoint — the base URL of your collector, e.g.
- Save. Export activates immediately — no restart required.
Option 2 — Environment variables
When neither an env endpoint nor the integration is configured, export is fully off and adds no overhead.
Compatible backends
Any OTLP/HTTP-compatible collector or backend, including:- Grafana (Tempo for traces, Loki for logs) / Grafana Cloud
- Datadog (OTLP intake)
- Elastic APM
- SigNoz
- Splunk (via the OpenTelemetry Collector)
- A self-run OpenTelemetry Collector that fans out to anything downstream
Operator export vs per-tenant export
There are two independent OTLP destinations, for two different audiences:- Operator export (this page’s OpenTelemetry (OTLP export) card, Global scope, or the env vars). Ships the whole gateway’s traces + logs + metrics to the operator’s collector — for whoever runs the deployment to monitor KnoxCall itself. Operator metrics/logs carry a
knoxcall.tenant_iddimension so you can facet by tenant. - Per-tenant export (the Telemetry export (OTLP) integration, tenant scope). Each tenant points KnoxCall at their own collector/SIEM and receives only their own request logs and analytics metrics — nothing from other tenants, and no traces. This is configured per workspace, right next to Email/Twilio/S3 in Settings → Integrations.
Configure per-tenant export
- As a workspace admin, go to Settings → Integrations → Telemetry export (OTLP).
- Set the OTLP HTTP endpoint (your collector — e.g. a Datadog Agent or OTel Collector), optional service name, and optional auth headers (encrypted at rest).
- Save. Only that workspace’s
knoxcall.proxy.requestlogs andknoxcall.proxy.requests/knoxcall.proxy.request.durationmetrics ship to it; applies on the next request, no restart.
Error tracking (Sentry)
The OTLP signals above are for shipping telemetry to your own collector. To catch errors — with native grouping, alerting, and release health — KnoxCall ships an optional Sentry integration covering both tiers:- Browser (
@sentry/react) — admin-UI uncaught exceptions, React render crashes, and unhandled promise rejections. - Operator console (
@sentry/react, separate DSN) — the same for the console SPA. Its own project on purpose: console events identify a KnoxCall operator and carry notenant_id, so it can be switched on independently of the tenant-facing admin UI, and its issue stream kept behind tighter access. - Backend (
@sentry/node) — server-side exceptions on any5xx, plus uncaught exceptions and unhandled rejections outside the request cycle, in every process: the API server, the standalone proxy, the workflow workers and each scheduled job. Events carry acomponenttag naming which one (api,proxy,workflow-worker,cron:retention-purge, …), so a crash in a 03:00 job is as visible as one on the request path.
Configure
- Create Sentry project(s) and copy the DSN(s) (
https://<key>@o0.ingest.sentry.io/0). A DSN identifies a project, not a secret. Using separate browser and server projects is recommended (cleaner source maps, releases, and access control), but one project for both works too. - In Settings → Integrations (Global scope) → Error tracking (Sentry):
- Sentry DSN — browser (admin UI errors) → the browser project DSN.
- Sentry DSN — server (backend errors) → the backend project DSN.
- Sentry DSN — operator console → the console project DSN (optional; a separate project is recommended, see above).
- Save. (Or set
SENTRY_DSN/SENTRY_DSN_BACKENDenv vars — env wins, same as the OTLP endpoint.SENTRY_ENVIRONMENTsets the environment tag.)
- The browser DSNs are delivered to their SPA shells at page-load time (no
rebuild) — the admin DSN only to the admin UI, the console DSN only to
console.knoxcall.com. The backend DSN stays server-side and applies immediately on save.
What it captures, and what it deliberately doesn’t
- Captures: browser uncaught errors / rejections / React render errors (with
the component stack); backend
5xxexceptions and process-level crashes — tagged with release and environment. Backend errors carry the opaqueerrorIdthat’s also in the server log and the client response, for correlation. - Tenant-filterable: events are tagged with
tenant_id(and identified by user UUID only — never email/name) on both tiers, so you can filter “all errors for tenant X” in Sentry. These are internal identifiers, not PII, but they are a data category sent to Sentry — see the note below. - No session replay. Replay records the live admin DOM, which on a multi-tenant console can capture other tenants’ data — off by design.
- No PII. Cookies, IPs, request bodies and URL query parameters are never
attached — every Sentry SDK sets
dataCollectionexplicitly to collect none of them, keeping only the browser’s User-Agent. Token/secret-shaped values are redacted, and query strings and URL fragments stripped, from event messages, breadcrumbs and page URLs before an event leaves the process or the browser; the backend reports the request path only. - Optional: warn+ logs. Set
SENTRY_LOGS=1to ship warn and error lines from the application logger to Sentry as structured logs, attached alongside the exceptions. Worth it because the backend SDK carries no breadcrumbs by design, so a stack trace otherwise arrives with no run-up. Only text that has already been through the redaction grammar is sent — Sentry’sconsoleLoggingIntegrationis deliberately not used, as it would ship un-redactedconsole.*output. Off by default: log ingest is billed by volume, and it widens what leaves the process from exceptions to log bodies. - No tracing interference. The backend SDK runs as a pure error reporter (no Sentry OpenTelemetry setup, no loader hook, no auto-instrumentation) — OpenTelemetry above keeps owning all traces and propagation. (Backend errors are therefore not OTel-trace-linked; the traces live in your OTLP backend.)
Browser source maps
Without source maps a browser stack trace is minified frames against hashed chunk names. SetSENTRY_ORG, SENTRY_PROJECT and SENTRY_AUTH_TOKEN on the
machine that builds admin-ui, and the build uploads maps to Sentry and then
deletes them from dist/. The console build reads the same variables, with
SENTRY_PROJECT_CONSOLE overriding SENTRY_PROJECT when the two SPAs report
to separate projects. These are build-time variables, not runtime
config — they do not belong in the server env file.
A build without all three emits no maps at all. That is deliberate: an
un-uploaded map left in dist/ would serve readable admin-console source from
the admin origin, which is a worse outcome than unsymbolicated traces.
Sentry as an OTLP backend
You can point the OTLP HTTP endpoint at Sentry’s own OTLP ingest, so spans and integration logs land in the same project as your errors. Copy the values from Project Settings → OpenTelemetry in Sentry:
Give the endpoint without a signal suffix — KnoxCall appends
/v1/traces and
/v1/logs itself, which is exactly what Sentry expects.
Sending one signal somewhere else
Each signal can override the endpoint above, using the standard OpenTelemetry variable names:- A signal endpoint is used verbatim — it already carries its path, so give
the full URL ending in
/v1/metrics. Nothing is appended. - Signal headers replace the generic ones, they do not merge. That is what keeps your Sentry key out of requests to the metrics backend, and the metrics backend’s token out of requests to Sentry.
TRACES and LOGS. Signals with no override keep using the
endpoint and headers above. These are env-only; the Integrations tab keeps a
single endpoint field, since splitting signals across vendors is an operator
concern rather than a self-host one.
To simply turn metrics off instead, untick Export metrics or set
OTEL_METRICS_EXPORTER=none.
Two things this does not replace. Sentry’s OTLP ingest is in open beta and is
thinner on grouping and breadcrumbs than the native SDK, so keep the Sentry DSN
— server field set for errors. And OTLP retention is a Sentry plan setting
measured in weeks, so it is a place to alert and triage from, not a system of
record — audit evidence belongs in the audit log and its offsite archive.
Configuring a Sentry DSN sends error reports to Sentry. For the hosted service
that makes Sentry a sub-processor; if you run KnoxCall yourself the data goes
to your Sentry project. Either way, review your sub-processor disclosures
before enabling it in production.
Related
- API Request Logs — full request/response history in the dashboard
- Audit Logs — security and configuration events (also deliverable via the
audit.eventwebhook) - Webhooks — push individual events to your own endpoints