OpenTelemetry (OTLP)

Point your OpenTelemetry exporter at Obsivara — gen_ai.* attributes are mapped automatically to LLM cost and token tracking.

Obsivara accepts JSON-encoded OTLP only. Protobuf-encoded requests return 415 Unsupported Media Type. Set Content-Type: application/json on every request.

Endpoint

text
POST https://api.obsivara.com/ingest/otlp/v1/traces

Auth: Authorization: Bearer obs_live_YOUR_KEY (scope: ingest:write).

Use with an OTel SDK exporter

Most OpenTelemetry SDKs read the exporter endpoint and headers from environment variables. Set these two variables and your existing traces will flow to Obsivara automatically:

bash
# Set your OTel SDK exporter to point at Obsivara
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.obsivara.com/ingest/otlp
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer obs_live_YOUR_KEY"

The exporter will send to /ingest/otlp/v1/traces automatically. No code changes needed.

Minimal JSON payload

If you are constructing OTLP JSON directly, here is a minimal payload with all fields Obsivara reads:

json
{
  "resourceSpans": [
    {
      "resource": {
        "attributes": [
          { "key": "obsivara.asset_id", "value": { "stringValue": "support-agent" } },
          { "key": "service.name",      "value": { "stringValue": "support-agent"  } }
        ]
      },
      "scopeSpans": [
        {
          "scope": { "name": "my-app" },
          "spans": [
            {
              "traceId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
              "spanId": "a1b2c3d4e5f6a1b2",
              "name": "llm-chat",
              "kind": 3,
              "startTimeUnixNano": "1720000000000000000",
              "endTimeUnixNano":   "1720000001240000000",
              "attributes": [
                { "key": "gen_ai.system",               "value": { "stringValue": "openai"  } },
                { "key": "gen_ai.request.model",         "value": { "stringValue": "gpt-4o" } },
                { "key": "gen_ai.usage.prompt_tokens",   "value": { "intValue":    "312"    } },
                { "key": "gen_ai.usage.output_tokens",   "value": { "intValue":    "87"     } },
                { "key": "gen_ai.usage.cost",            "value": { "doubleValue": 0.0048   } }
              ]
            }
          ]
        }
      ]
    }
  ]
}
bash
curl -X POST https://api.obsivara.com/ingest/otlp/v1/traces \
  -H "Authorization: Bearer obs_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d @payload.json

Attribute mapping

Obsivara maps the following OpenTelemetry semantic conventions to its internal event model:

OTel attributeObsivara field
gen_ai.system / llm.vendorprovider
gen_ai.request.model / llm.request.modelmodel
gen_ai.usage.prompt_tokens / llm.usage.prompt_tokenspromptTokens
gen_ai.usage.output_tokens / llm.usage.completion_tokenscompletionTokens
gen_ai.usage.costcostUsd
obsivara.asset_id (resource attribute)assetId

Auto-detection

Spans are classified as llm_call events automatically when any of the following are true:

  • The span has a gen_ai.* or llm.* attribute
  • The span name contains "llm" or "chat" (case-insensitive)

All other spans are recorded as generic span events and associated with the same trace.

Setting the asset ID

Set the obsivara.asset_id resource attribute on your OTel resource to attribute all spans from that resource to the named asset in Obsivara. This is the recommended approach for SDK-based exporters.

The resource attribute service.name is also captured but is separate from the Obsivara asset. Always set obsivara.asset_id explicitly.

Troubleshooting

  • 415 Unsupported Media Type — you are sending protobuf. Switch to the JSON OTLP format.
  • 401 — missing or malformed Bearer token in the Authorization header.
  • 403 — key exists but lacks ingest:write scope. Re-create the key.
  • No data in dashboard — check that obsivara.asset_id is set on the resource; otherwise the asset will appear as "unknown".

See Errors & troubleshooting → for the full error reference.