OpenTelemetry
Schift emits OpenTelemetry traces for retrieval and search operations. You can route these traces to any OTLP-compatible backend—such as Datadog, Honeycomb, Grafana Tempo, Jaeger, or LangSmith—by setting a few environment variables. When telemetry is not configured, the instrumentation is a no-op and adds zero overhead.
What is emitted
Section titled “What is emitted”The Schift API initializes an OTLP trace exporter at boot when OTEL_EXPORTER_OTLP_ENDPOINT is set. The following traces are emitted today:
schift.bucket.search— the top-level bucket search span, created for everyPOST /v1/buckets/{bucket_id}/searchrequest that runs the local retrieval pipeline.
Each schift.bucket.search span carries attributes that describe the request, the retrieval strategy, and the result quality.
Enable telemetry
Section titled “Enable telemetry”Set these environment variables before starting the Schift API:
export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io"export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=<your-api-key>"Restart the server. Spans are batched and exported asynchronously.
Note:
OTEL_EXPORTER_OTLP_HEADERScontains credentials. Load it from a secret manager or your deployment platform’s secret storage, not from a checked-in.envfile.
Configuration reference
Section titled “Configuration reference”| Variable | Required | Default | Description |
|---|---|---|---|
OTEL_EXPORTER_OTLP_ENDPOINT | Yes | — | The OTLP endpoint URL. |
OTEL_EXPORTER_OTLP_HEADERS | Usually | — | Comma-separated key=value headers for authentication. |
OTEL_EXPORTER_OTLP_PROTOCOL | No | auto | grpc or http/protobuf. |
OTEL_SERVICE_NAME | No | schift-api | The service name attached to every span. |
OTEL_TRACES_SAMPLER | No | always_on | Sampler name, e.g. parentbased_traceidratio. |
OTEL_TRACES_SAMPLER_ARG | No | — | Sampler argument, e.g. 0.1 for 10%. |
If OTEL_EXPORTER_OTLP_ENDPOINT is unset, init_telemetry() returns immediately and no exporter, tracer provider, or FastAPI instrumentation is installed.
Protocol selection
Section titled “Protocol selection”Schift auto-detects the transport protocol so HTTPS endpoints work without extra configuration:
- If
OTEL_EXPORTER_OTLP_PROTOCOLis set togrpcorhttp/protobuf, that value is used. - Otherwise, HTTPS endpoints use
http/protobuf. - Otherwise, plain HTTP or
grpc://endpoints usegrpc.
Most managed vendors require http/protobuf. Set the variable explicitly only if the auto-detection does not match your collector.
Span attributes
Section titled “Span attributes”The schift.bucket.search span includes these attributes:
| Attribute | Type | Description |
|---|---|---|
schift.bucket.id | string | The bucket ID from the request path. |
schift.search.top_k | int | The requested number of results. |
schift.search.mode | string | The search mode, such as vector or hybrid. |
schift.search.rerank | bool | Whether reranking was requested. |
schift.search.model | string | The embedding model used for the query, if overridden. |
schift.expand_neighbors.enabled | bool | Whether neighbor expansion was enabled. |
schift.filter.keys | string[] | Metadata filter keys that were applied. |
schift.filter.ops | string[] | Filter operators that were applied, such as eq or like. |
schift.schiftql.plan_digest | string | A digest of the executed SchiftQL plan, when applicable. |
schift.search.method | string | The actual retrieval method that ran. |
schift.search.results.count | int | The number of results returned. |
schift.search.scores.top | float | The score of the top result. |
schift.search.scores.avg | float | The average score across results. |
schift.timing.total_ms | int | Total search latency in milliseconds. |
schift.search_id | string | The internal search correlation ID. |
schift.search.error | string | The error type when the search fails. |
These attributes let you build dashboards and alerts by bucket, search method, filter shape, result count, or latency without parsing unstructured logs.
FastAPI instrumentation
Section titled “FastAPI instrumentation”When telemetry is enabled, Schift also calls FastAPIInstrumentor.instrument_app(app). This creates spans for incoming HTTP requests and propagates W3C trace context, so spans emitted by the Schift API are correlated with upstream callers.
To correlate a client request with a Schift trace, propagate the traceparent header:
from schift import Client
client = Client( api_key="...", headers={"traceparent": current_traceparent()},)import { WorkspaceClient } from "@schift-io/sdk";
const client = new WorkspaceClient({ apiKey: "...", headers: { traceparent: currentTraceparent() },});Sampling for high traffic
Section titled “Sampling for high traffic”By default, all traces are sampled. For high-volume deployments, reduce the sample rate:
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"export OTEL_TRACES_SAMPLER_ARG="0.1"This samples 10% of traces while keeping parent-child correlation intact.
Vendor examples
Section titled “Vendor examples”Datadog Agent
Section titled “Datadog Agent”export OTEL_EXPORTER_OTLP_ENDPOINT="http://datadog-agent:4318"export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"Honeycomb
Section titled “Honeycomb”export OTEL_EXPORTER_OTLP_ENDPOINT="https://api.honeycomb.io"export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=<your-api-key>,x-honeycomb-dataset=schift"Grafana Tempo or Jaeger
Section titled “Grafana Tempo or Jaeger”export OTEL_EXPORTER_OTLP_ENDPOINT="http://tempo:4318"export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"For LangSmith-specific instructions, see LangSmith integration.
Troubleshooting
Section titled “Troubleshooting”- No spans appear. Verify that
OTEL_EXPORTER_OTLP_ENDPOINTis set before the app starts and that the endpoint is reachable from the server.init_telemetry()is called once during app creation; runtime changes after boot are not picked up. - Spans rejected by the collector. Check that
OTEL_EXPORTER_OTLP_PROTOCOLmatches the collector’s receiver. Most HTTPS vendors requirehttp/protobuf. - High cardinality. Avoid unbounded values in
schift.filter.keys. Some vendors charge by unique attribute combinations.