Two weeks ago we stopped publishing.
Not because we ran out of things to say. Because we found a design mistake that was serious enough to fix before we shipped anything else on top of it.
This post is the explanation.
What We Had
The original GetStackLens SDK had a simple model: call getstacklens.init(), and every LLM call you make gets captured and sent to GetStackLens via our own ingestion API.
import getstacklens
getstacklens.init(api_key="your-api-key")
# From here, every OpenAI call is traced automatically
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)That model worked. It was simple to explain, and the Python SDK is production-ready on PyPI.
The problem wasn't correctness. The problem was architecture.
The Realization
About two weeks ago, we looked at what we were actually building:
- A custom binary format for sending trace data to our ingestion endpoint
- Custom retry and batching logic in the SDK
- A proprietary schema that only we understood
- A dependency that teams had to adopt on faith — because if they adopted our SDK, their LLM trace data was tied to our format
And then we looked at what OpenTelemetry had become.
OpenTelemetry is now the standard observability protocol for production systems. Not a trend — the standard. If you're running a serious engineering organization in 2026, there's a better than even chance you already have an OTEL pipeline. Datadog, Honeycomb, Jaeger, Grafana — they all consume OTLP. Your traces, metrics, and logs might already be flowing through it.
And in 2025, OpenTelemetry published semantic conventions specifically for GenAI operations. gen_ai.system. gen_ai.request.model. gen_ai.usage.input_tokens. A standardized schema for exactly the data we were capturing — designed by the same body that designed the tracing protocol everyone is already using.
We were building a proprietary format for a problem that the industry had just solved.
What We Changed
The GetStackLens SDK is now an OpenTelemetry instrumentation library.
It does two things:
- Auto-instruments your LLM clients (OpenAI, Anthropic, and others) to emit spans using OpenTelemetry GenAI semantic conventions
- Exports those spans via OTLP to GetStackLens — your dedicated AI observability backend. Because it's standard OTLP, your existing backends (Datadog, Honeycomb, Jaeger) receive the same spans automatically alongside GetStackLens
The wire format is now OTLP over HTTP. Standard. Stable. Already trusted in production by thousands of engineering teams.
Here's what integration looks like now:
If you have no existing OTEL setup (the simple path — same as before, one init call):
import getstacklens
getstacklens.configure(
api_key="sl-...",
endpoint="https://ingest.getstacklens.ai"
)
getstacklens.instrument_openai()
# Your OpenAI calls are traced. Nothing else changes.
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)If you already have OpenTelemetry running (the best path — zero new dependencies):
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import BatchSpanProcessor
import getstacklens
# Add GetStackLens as a second exporter alongside your existing pipeline
provider = trace.get_tracer_provider()
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint="https://ingest.getstacklens.ai/v1/traces",
headers={"Authorization": "Bearer sl-..."}
)
)
)
# Register instrumentation — spans flow wherever your exporter says
getstacklens.instrument_openai()
getstacklens.instrument_anthropic()If you're already on OTEL, you're adding one BatchSpanProcessor and calling instrument_openai(). That is the full integration.
The Spans We Emit
Every LLM call now produces a span structured around the OpenTelemetry GenAI semantic conventions:
Span: gen_ai.chat
gen_ai.system = "openai"
gen_ai.request.model = "gpt-4o"
gen_ai.response.model = "gpt-4o-2024-08-06"
gen_ai.operation.name = "chat"
gen_ai.usage.input_tokens = 812
gen_ai.usage.output_tokens = 214
gen_ai.response.finish_reasons = ["stop"]
getstacklens.cost.usd = 0.0074
getstacklens.quality.score = 0.87
getstacklens.prompt.version = "v14"
getstacklens.environment = "production"
The gen_ai.* attributes are the standard OpenTelemetry GenAI namespace. Any OTEL-compatible backend can consume and query them.
The getstacklens.* attributes are our extensions — cost estimation, semantic quality scores, prompt version correlation, environment tagging. These appear alongside the standard data and are ignored gracefully by backends that don't understand them.
Why This Is the Right Architecture
Teams already on OTEL get zero-friction integration. No new dependencies, no new format to learn. If your traces go to Datadog today, your LLM spans go to Datadog and GetStackLens tomorrow — with one exporter added and two function calls.
The data is portable. Because we're emitting standard OTEL spans, teams are never locked in. Your LLM trace history is in a format any OTEL consumer can read. We earn continued use by being the best destination for this data, not by making migration painful.
Interoperability is now built in. LangChain, LlamaIndex, and other frameworks are adding native OTEL instrumentation. When they emit GenAI spans, those spans flow into GetStackLens automatically — no additional SDK work required.
The SDK layer gets thinner over time. As the ecosystem adds native instrumentation, our SDK shifts from "instrument for you" to "extend and enrich the standard data." Less to maintain, less to break, more to trust.
What We Threw Away
The honest version: we rewrote the SDK instrumentation layer and the ingestion service to accept OTLP natively.
We kept the StackTrace data model (spans, LLM enrichments, prompt version correlation). We kept the GovernAI integration — PII scanning still triggers from ingestion events, same architecture. We kept the FlowOps prompt version linking.
What we discarded was the custom encoding layer and the custom retry/backoff logic. All of that is now handled by the OTEL SDK primitives, which have been battle-tested across the entire observability ecosystem.
It took two weeks. It was the right call.
What's Next
Python SDK (getstacklens on PyPI) — updating to OTEL-native. The existing API surface is preserved; the wire format underneath changes to OTLP. Instruments OpenAI and Anthropic on release; LangChain and LlamaIndex support follows.
Stay tuned: The OTEL-native release is in progress. Subscribe to the blog or follow us on LinkedIn — we'll post the full changelog and upgrade notes the moment it ships.
TypeScript SDK (stacklens on npm) — writing the OTEL-native version from scratch. We'd rather build it right once than build it twice.
.NET SDK (StackLens on NuGet) — same. The .NET OpenTelemetry ecosystem is mature and the extension points are well-defined; this one benefits most from starting OTEL-native.
The StackLens ingestion endpoint now accepts OTLP directly. Which means if you already export traces from any source to an OTLP endpoint, you can point it at ingest.getstacklens.ai today — and your LLM spans will appear in StackTrace without any SDK at all.
A Note on the Silence
We know two weeks is a long time to go quiet when you've just announced early access. We considered publishing something shorter as a placeholder. We decided not to.
The right move when you find a design mistake this significant is to fix it — not to ship the wrong version and explain later. The teams who join the early-access waitlist deserve to instrument their systems once, correctly, against a stable and standard format. That took two weeks to get right.
We're back, and the foundation is better than it was.
If you're running OTEL in production already and want to be among the first to test the new SDK against a real ingestion endpoint — reach out or join the waitlist. We're onboarding early-access teams now.
The GetStackLens Python SDK (PyPI) is being rebuilt as OpenTelemetry-native — this is a work in progress. Join the waitlist at getstacklens.ai to be notified when it ships.