OpenTelemetry (OTLP) Endpoint
GoodLogs exposes a native OTLP/HTTP trace receiver, so any OpenTelemetry SDK or Collector can ship spans to GoodLogs without code changes — just an exporter config.
Protocol support today
Signal HTTP/JSON HTTP/Proto gRPC Traces ✅ ✅ ⏳ deferred Logs ✅ ✅ ⏳ deferred Metrics — — — Pick
http/jsonorhttp/protobuf— both go to the same endpoint. gRPC OTLP (:4317) is not supported; switch your Collector exporter tootlphttpfor now.
Endpoint
POST https://api.goodlogs.io/v1/traces
Authorization: Bearer <PROJECT_SECRET_KEY>
Content-Type: application/json
- Region routing: hit your project's regional host (e.g.
https://eu.api.goodlogs.io/v1/traces) for lowest latency. The globalapi.goodlogs.iohost transparently forwards. - Auth: any project API key with the
ingest:writescope. Same keys you already use for the native envelope endpoint — find them in Project Settings → API Keys. - Body cap: 10 MB per request. Batch and retry in your Collector.
The response is JSON:
{ "accepted_spans": 42, "rejected_spans": 0 }
Spans missing traceId or spanId are counted in rejected_spans but never
fail the whole batch — this matches Collector retry semantics.
OpenTelemetry Collector
Add a goodlogs exporter under exporters: in your Collector config:
exporters:
otlphttp/goodlogs:
endpoint: https://eu.api.goodlogs.io
encoding: json
headers:
Authorization: "Bearer ${env:GOODLOGS_SECRET_KEY}"
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlphttp/goodlogs]
The Collector appends /v1/traces to the endpoint automatically.
SDK (no Collector)
If you're exporting straight from an OTel SDK, point it at the same endpoint:
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
export OTEL_EXPORTER_OTLP_ENDPOINT=https://eu.api.goodlogs.io
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer $GOODLOGS_SECRET_KEY"
export OTEL_SERVICE_NAME=checkout-api
export OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production,service.version=v3.1.0
That's it — every span you emit becomes queryable in the explorer:
from:spans op:http.server status:error | groupby http.route
How OTLP maps to the GoodLogs span model
| OTLP field | GoodLogs column / behaviour |
|---|---|
resource.attributes["service.name"] | service |
resource.attributes["deployment.environment"] | environment |
resource.attributes["service.version"] | release |
span.kind = SERVER + http.* attrs | op = http.server |
span.kind = CLIENT + http.* attrs | op = http.client |
db.system present | op = db.query + typed db_system |
messaging.system + kind=CONSUMER | op = queue.consume |
attributes["http.method"] | http_method |
attributes["http.route"] | http_route |
attributes["http.status_code"] | http_status_code |
status.code = OK (1) | status = ok |
status.code = ERROR (2) | status = error |
status.code = UNSET (0) | status = ok |
events[] | events[] with ts / name / attributes |
| Everything else | attributes JSON blob |
startTimeUnixNano / endTimeUnixNano are accepted as either strings (per
the OTLP spec) or numbers — most SDKs send strings.
See also
- Tracing & Performance — the dashboards your OTLP spans light up
- GoodLogs Query Language — filter / aggregate
from:spans … - API Keys & scopes