Telemetry Export (OpenTelemetry / OTLP)

The Athena server can send its own metrics, traces and logs over OTLP, the OpenTelemetry protocol, to an OpenTelemetry Collector or any other backend that accepts OTLP. You set it up in Settings → Telemetry. It is an extra output only: the Prometheus /metrics endpoint and the System Health tab keep working as before. Changes apply when you save. No restart is needed.

Off by default, and nothing leaves the server until you turn it on

A new server has no OTLP exporter running. Athena only sends telemetry after you enable it in the tab, in appsettings.json, or with an OTEL_* environment variable. On an air-gapped network, point it at a collector inside that network.

For the numbers the server shows in its own console and on /metrics, see System Health & Prometheus Metrics. For the server log files, see Server Logging.

Who can see and change it#

ToYou needBuilt-in roles
See the Telemetry tab in Settingssettings.health.view, plus settings.manage to open the Settings pageAdmin
Change, save or Test connectionsettings.manageAdmin
Read the settings and export status over REST (GET /api/settings/telemetry)settings.health.viewAdmin, Operator

A custom role with settings.health.view but without settings.manage sees the form as read-only, with the note "Read-only: changing these settings needs settings.manage." See Permission Model & Role Bundles.

Turning it on#

  1. Open Settings and click the Telemetry tab (right after System Health), or go to https://<server>:8443/settings/telemetry.
  2. Tick Export telemetry over OTLP.
  3. Enter the collector's Endpoint and pick the Protocol.
  4. If your collector needs an API key or other header, enter it in Headers.
  5. Choose which Signals to send: Metrics, Traces and Logs. All three are on by default.
  6. Click Test connection. This sends one test span and one metric point using the values in the form, before they are saved.
  7. Click Save. The toast reads "Telemetry settings saved and applied." and the exporter starts at once.

Settings#

FieldDefaultWhat it does
Export telemetry over OTLPOffTurns the exporter on or off.
EndpointBlank. Then http://localhost:4317 for gRPC, http://localhost:4318 for HTTPThe collector's base URL. Must start with http:// or https:// and must not have a query string. For HTTP/protobuf, Athena adds /v1/traces, /v1/metrics and /v1/logs for you. For gRPC the URL is used as entered.
ProtocolgRPCgRPC (usually port 4317) or HTTP/protobuf (usually port 4318).
HeadersNonekey=value pairs separated by commas, for example api-key=… or Authorization=Basic …. See Headers are write-only.
SignalsMetrics, Traces and Logs all onWhich of the three to send.
Trace sampling ratio (0-1)1Parent-based. 1 keeps every trace, 0.1 keeps one in ten.
Log minimum levelInformationThe lowest log level sent: Trace, Debug, Information, Warning, Error or Critical. This only affects the OTLP output, not the server's own log files.
Service nameathena-serverSent as service.name. Use it to tell servers apart in your backend.
Deployment environmentNoneOptional, for example production. Sent as deployment.environment.
Metric export interval (seconds)60How often metrics are pushed. 1 to 3600.

Every export also carries service.version (the server version) and service.instance.id (the server's machine name in lower case). Each export request times out after 10 seconds.

If a value is not valid, Save shows one of these messages and nothing is changed:

Headers are write-only#

What is sent#

Only what the server is doing is sent, not the data it manages. Each signal is filtered before it leaves the server.

SignalContentsKept out
MetricsThe same allow-listed server metrics that /metrics publishes, with the same labels.Any label that /metrics also drops.
TracesOne span per request the server handles (REST API, web console and agent gRPC calls) and per outgoing HTTP call. Every console page load is a ui.page span, and every Settings tab or agent-details section switch is a ui.subpage span, so the work a page does shows up in one trace.Requests to /metrics and /health, static files, the console's live connection and other WebSocket traffic. On each span, only a fixed set of attributes is kept: method, status code, route template, scheme, protocol, port, error type and gRPC service/method/status, plus the page, trigger and tab of page spans. URL paths and query strings, client and server addresses, user agents, headers and exception messages are removed.
LogsThe server log events at or above Log minimum level. Each one carries the message template (for example Page {Route} loaded in {ElapsedMs} ms) and its values as separate attributes. Logs written inside a traced request carry its trace ID.The fully rendered message. Values whose name suggests a secret (password, token, secret, cookie, API key, connection string, credential, authorization, header, query) are sent as redacted. URLs lose their query string. For an exception, only its type is sent.

Export status#

The Status row on the Telemetry tab updates live after every export attempt. It shows the overall state, the endpoint, the time of the last successful export, and the failures since that success. Below it, one chip per enabled signal shows that signal's state and its failure count. While an export is failing, Last error shows the most recent error.

StateMeaning
OffExport is turned off.
WaitingExport is on, but nothing has been sent yet.
HealthyThe last export of every enabled signal succeeded.
FailingA signal has failed since its last success (or failed before its first success).
DownA signal has been failing for more than 5 minutes, or every enabled signal is failing.
# Any OTLP export failures in the last 5 minutes
increase(athena_otlp_export_failures_total[5m])

Environment variables and appsettings.json#

The standard OpenTelemetry OTEL_* environment variables are honoured. For each field, an environment variable wins over the Settings tab, and the tab wins over the default. A field set by a variable is read-only in the tab and shows "Set by environment variable …", so a container's configuration cannot be overridden by accident from the console.

VariableSetsNotes
OTEL_EXPORTER_OTLP_ENDPOINTEndpointSetting it also turns export on.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
One signal's endpointUsed exactly as given (nothing is appended). Setting any of them also turns export on.
OTEL_EXPORTER_OTLP_PROTOCOLProtocolgrpc or http/protobuf.
OTEL_EXPORTER_OTLP_HEADERSHeaderskey=value,key2=value2.
OTEL_METRICS_EXPORTER
OTEL_TRACES_EXPORTER
OTEL_LOGS_EXPORTER
Signalsnone switches that signal off. Any other value leaves it on.
OTEL_TRACES_SAMPLER
OTEL_TRACES_SAMPLER_ARG
Trace samplingalways_on, always_off, traceidratio, parentbased_always_on, parentbased_always_off or parentbased_traceidratio. The ratio goes in _ARG. An unknown name is ignored.
OTEL_SERVICE_NAMEService name
OTEL_RESOURCE_ATTRIBUTESDeployment environment and extra attributesFor example deployment.environment=production.
OTEL_METRIC_EXPORT_INTERVALMetric export intervalIn milliseconds, as in the OpenTelemetry specification (the tab uses seconds).
OTEL_SDK_DISABLED=trueEverythingForces export off, whatever else is set.

Log minimum level has no environment variable. It always comes from the tab or from configuration.

You can also configure the exporter in the Telemetry:Otlp section of appsettings.json, or with Telemetry__Otlp__* environment variables in a container. The keys are Enabled, Endpoint, Protocol, Headers, Metrics, Traces, Logs, TraceSampleRatio, LogMinimumLevel, ServiceName, DeploymentEnvironment and MetricExportIntervalSeconds. A plain-text Headers value set this way works. The tab always stores headers encrypted.

{
  "Telemetry": {
    "Otlp": {
      "Enabled": true,
      "Endpoint": "http://otel-collector.corp.local:4317",
      "Protocol": "grpc",
      "ServiceName": "athena-server",
      "DeploymentEnvironment": "production"
    }
  }
}
# docker-compose.yml: the same, with the standard OpenTelemetry variables
    environment:
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
      - OTEL_SERVICE_NAME=athena-server
      - OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production

REST API#

EndpointPermissionDoes
GET /api/settings/telemetrysettings.health.viewReturns the settings (headers masked), environmentOverrides (which fields an OTEL_* variable owns) and status (state, endpoint, last success, failures, last error, and the same per signal).
PUT /api/settings/telemetrysettings.manageSaves and applies the settings. Returns HTTP 400 with one of the messages above if a value is not valid.
POST /api/settings/telemetry/testsettings.manageSends a test span and a metric point using the values in the body, without saving them. A failed test still returns HTTP 200, with success: false and the error in message.
$headers = @{ Authorization = "Bearer $token" }
$t = (Invoke-RestMethod "https://athena.contoso.com:8443/api/settings/telemetry" `
  -Headers $headers -SkipCertificateCheck).data
$t.status | Select-Object state, endpoint, lastSuccessAt, failures, lastError
$t.status.signals | Format-Table signal, state, failures, lastError

See API Reference for signing in and getting a token.

Audit trail#

Each save writes one SettingsChanged event per changed field, with the old and new value and the user who saved. A change to the headers is recorded only as [Hidden] → [Changed]. The header value itself is never recorded. See Audit Event Types Reference.

Troubleshooting#

Message or symptomWhat to check
Timed out waiting for the endpoint. with a localhost endpointlocalhost resolved to IPv6 (::1) and the collector listens on IPv4 only. Use 127.0.0.1 instead.
Unreachable: …Nothing is listening at that address and port, or a firewall is in the way. Check the collector's host, port (4317 for gRPC, 4318 for HTTP) and the network path from the Athena server.
TLS handshake failed: …The endpoint is https:// and the server does not trust the collector's certificate, or the collector does not speak TLS on that port.
HTTP 401 or gRPC status 16 (Unauthenticated)The headers (API key) are missing or wrong. Enter them again and save.
HTTP 404 with HTTP/protobufEnter the collector's base URL only. Athena adds /v1/traces, /v1/metrics and /v1/logs itself.
Everything fails with the protocol set to gRPC on port 4318 (or HTTP on 4317)The protocol and port don't match. Usually gRPC is 4317 and HTTP/protobuf is 4318.
A connection test is already running.Only one test runs at a time. Wait for it to finish.
No answer from … within the timeout.The collector accepted the connection but did not confirm both test items. Check the collector's own logs.
A field is greyed out with "Set by environment variable …"That variable is set on the server or container and overrides the tab. Change or remove the variable and restart the server.
Traces arrive but some requests are missingThe Trace sampling ratio is below 1, or OTEL_TRACES_SAMPLER is set. Requests to /metrics, /health, static files and live-connection traffic are never traced.
Log records have no message textBy design, the message template is sent as the body and the values as attributes. Use the attributes in your backend.