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
One SERVER 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
traceparent headers 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 OTLP LogRecord:
| Event | event.name | Key attributes |
|---|
| Proxied API request | knoxcall.proxy.request | http.request.method, url.path, http.response.status_code, server.address, knoxcall.request_id, knoxcall.tenant_id, knoxcall.route_name, knoxcall.latency_ms |
| Webhook delivery | knoxcall.webhook.delivery | http.request.method, http.response.status_code, server.address, knoxcall.webhook.event_type, knoxcall.webhook.success, knoxcall.webhook.retry_count |
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:
| Instrument | Type | Unit | Dimensions |
|---|
knoxcall.proxy.requests | Counter | {request} | http.response.status_code, http.response.status_class, knoxcall.route_name, knoxcall.environment, error |
knoxcall.proxy.request.duration | Histogram | ms | (same) |
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 to knoxcall).
- Auth headers (optional, encrypted at rest) — comma-separated
key=value pairs, 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.
- Save. Export activates immediately — no restart required.
Option 2 — Environment variables
| Variable | Purpose |
|---|
OTEL_EXPORTER_OTLP_ENDPOINT | Base OTLP/HTTP endpoint (enables export) |
OTEL_EXPORTER_OTLP_HEADERS | Auth headers, key=value,key2=value2 |
OTEL_SERVICE_NAME | Resource service.name (default knoxcall) |
OTEL_TRACES_EXPORTER=none | Disable the traces signal only |
OTEL_LOGS_EXPORTER=none | Disable the logs signal only |
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_id dimension 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.
Both can run at once: a request fans out to the operator’s collector and the originating tenant’s collector.
- 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.request logs and knoxcall.proxy.requests / knoxcall.proxy.request.duration metrics 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.
- Backend (
@sentry/node) — server-side exceptions on any 5xx, plus
uncaught exceptions and unhandled rejections outside the request cycle.
It’s a separate integration card — Error tracking (Sentry) — independent
of the OpenTelemetry export above. Configure either, both, or neither.
- 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.
- Save. (Or set
SENTRY_DSN / SENTRY_DSN_BACKEND env vars — env wins, same
as the OTLP endpoint. SENTRY_ENVIRONMENT sets the environment tag.)
- The browser DSN is delivered to the admin UI at page-load time (no rebuild);
the backend DSN stays server-side and applies immediately on save.
When a DSN isn’t set, that SDK never initialises and adds no overhead.
What it captures, and what it deliberately doesn’t
- Captures: browser uncaught errors / rejections / React render errors (with
the component stack); backend
5xx exceptions and process-level crashes —
tagged with release and environment. Backend errors carry the opaque
errorId that’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, and request bodies are never attached
(
sendDefaultPii: false); token/secret-shaped values are redacted before an
event leaves the process; the backend reports the request path only (no
query string).
- No tracing interference. The backend SDK runs as a pure error reporter
(
skipOpenTelemetrySetup, 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.)
Sentry as an OTLP backend (alternative)
If you’d rather not run the native backend SDK, you can instead point the OTLP
HTTP endpoint above at Sentry’s OTLP ingest; 5xx exceptions recorded on the
request span then surface as Sentry errors. Sentry’s OTLP ingest is newer and
thinner on grouping/breadcrumbs than the native SDK, so prefer the Sentry DSN —
server field above unless you’re consolidating on OTLP.
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.
- API Request Logs — full request/response history in the dashboard
- Audit Logs — security and configuration events (also deliverable via the
audit.event webhook)
- Webhooks — push individual events to your own endpoints