opentelemetryotelotlptracesdistributed-tracing

OpenTelemetry

Send distributed traces to ScryWatch using OpenTelemetry Collector or OTLP/HTTP exporters. Clear guide to what's supported today.

OpenTelemetry

ScryWatch supports the OpenTelemetry standard for distributed traces. You can send OTLP/HTTP trace data directly from your services or route it through an OpenTelemetry Collector.

What’s supported today

SignalOTLP SupportAlternative
TracesPOST /api/traces/otlpPOST /api/traces (native format)
Logs❌ Not yetPOST /v1/ingest (HTTP JSON)
Metrics❌ Not yetPOST /api/metrics (HTTP JSON)

Why be explicit? OTLP Logs is still maturing in the OpenTelemetry ecosystem — the Go SDK logs bridge is experimental as of early 2026, and the spec has seen breaking changes. We’ll add OTLP log and metric ingestion when the implementations are stable.

OTLP Traces endpoint

POST https://api.scrywatch.com/api/traces/otlp
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Accepts the OTLP/HTTP protobuf-JSON format.

Option 1: Direct OTLP exporter (no Collector)

Instrument each service and point the exporter at ScryWatch.

Node.js / TypeScript

npm install @opentelemetry/sdk-node \
            @opentelemetry/exporter-trace-otlp-http \
            @opentelemetry/resources \
            @opentelemetry/semantic-conventions
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { Resource } from '@opentelemetry/resources';
import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';

const sdk = new NodeSDK({
  resource: new Resource({
    [SEMRESATTRS_SERVICE_NAME]: 'my-service',
  }),
  traceExporter: new OTLPTraceExporter({
    url: 'https://api.scrywatch.com/api/traces/otlp',
    headers: {
      Authorization: 'Bearer YOUR_API_KEY',
    },
  }),
});

sdk.start();

Python

pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

exporter = OTLPSpanExporter(
    endpoint="https://api.scrywatch.com/api/traces/otlp",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)

Go

See the full Go integration guide for setup. The OTLP exporter config is:

otlptracehttp.WithEndpoint("api.scrywatch.com"),
otlptracehttp.WithURLPath("/api/traces/otlp"),
otlptracehttp.WithHeaders(map[string]string{
    "Authorization": "Bearer YOUR_API_KEY",
}),

Route all telemetry through a Collector. Your services export to localhost; the Collector forwards to ScryWatch. When you change observability backends, only the Collector config changes — not every service.

Collector config — traces only

# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 5s
    send_batch_size: 100
  memory_limiter:
    check_interval: 1s
    limit_mib: 256

exporters:
  otlphttp/scrywatch:
    endpoint: https://api.scrywatch.com
    headers:
      Authorization: "Bearer ${env:SCRYWATCH_API_KEY}"
    sending_queue:
      enabled: true
    retry_on_failure:
      enabled: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/scrywatch]
    # Logs pipeline omitted — OTLP log ingestion is not yet supported.
    # Use the ScryWatch SDK or POST /v1/ingest directly for logs.

Pointing services at the Collector

# Environment variables — most OTel SDKs pick these up automatically
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=my-service
OTEL_TRACES_EXPORTER=otlp

OTLP data model mapping

OTLP fieldScryWatch field
resource.attributes["service.name"]service
span.traceIdtrace_id
span.spanIdspan_id
span.parentSpanIdparent_span_id
span.namename
span.startTimeUnixNanostart_time (converted to ms)
span.endTimeUnixNanoend_time (converted to ms)
span.status.code == 2status: "error"
span.attributes["http.method"]stored in attributes JSON
span.attributes["http.url"]stored in attributes JSON
span.eventsstored as events JSON array

Test your setup

Send a minimal test trace to verify connectivity:

curl -X POST https://api.scrywatch.com/api/traces/otlp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resourceSpans": [{
      "resource": {
        "attributes": [{"key": "service.name", "value": {"stringValue": "test"}}]
      },
      "scopeSpans": [{
        "spans": [{
          "traceId": "aabbccdd00112233aabbccdd00112233",
          "spanId": "1122334455667788",
          "name": "test-span",
          "startTimeUnixNano": "1741200000000000000",
          "endTimeUnixNano": "1741200000250000000",
          "status": {"code": 1}
        }]
      }]
    }]
  }'
# Expected: {"inserted":1}

Then check the Distributed Tracing view in ScryWatch.

See also

← All guides