Technology

OpenTelemetry in. Open Parquet out.

OTel solved vendor lock-in at the collection layer and stopped there — most backends still take open telemetry and put it into a proprietary index. CtrlB keeps the whole path open, from the collector to the files in your bucket.

Logs
Metrics
Traces
OTLP
OpenTelemetry
OpenTelemetry Collector
the one you already run
New exporter
CtrlB
Parquet in your bucket
Unchanged
Current backend
keep it as long as useful
zero code changes · zero re-instrumentation
3 signals
Logs, metrics, traces
No agent
Your collector, unchanged
Open Parquet
Open on both ends
Fan out
Run in parallel with today's backend

Schema-less ingest

The attributes survive the trip

OpenTelemetry's value is in the attributes your services attach. A backend with a fixed schema keeps the ones it declared in advance and silently discards the rest — including the one the next incident turns on.

Span · checkout.PlaceOrder34 attributes emitted
Fixed-schema backend9 / 34
service.name"checkout"
http.status_code"200"
duration3068
service.cloud.regiondropped
service.container_iddropped
deployment.environmentdropped
feature_flag.variantdropped
tenant.iddropped

not in the schema, so not stored — and not recoverable later

CtrlB0 / 34
service.name"checkout"
http.status_code"200"
duration3068
service.cloud.region"asia-south1"
service.container_id"55902bf63c45…"
deployment.environment"prod"
feature_flag.variant"checkout_v3"
tenant.id"acme-4471"

schema-less ingest · every attribute queryable

The attribute you did not think to declare is the one the incident turns on. Here that is feature_flag.variant — the difference between “checkout is slow” and “checkout is slow on v3”.

Open on both ends

Instrumentation stays portable. Storage should too.

OTel solved vendor lock-in at collection — most backends still take open telemetry and bury it in a proprietary index. The open path should run all the way to the files in your bucket.

telemetry path · where openness ends
otlp/grpc · same collector
Instrumentation
OTel SDK · portable
Transport
Collector · OTLP
Storage
proprietary index
OTel SDK
your instrumentation
Collector
no vendor agent
Proprietary index

OTel in → vendor schema → history you cannot export

Logs
Metrics
Traces
Parquet lake

logs + metrics + traces → s3://telemetry/lake/

service.namek8s.pod.namehttp.routeexception.type
vendor path · schema flattening
service.namek8s.pod.namehttp.routeexception.type→ dropped
open path · schema-less ingestion
service.namek8s.pod.namehttp.routeexception.type✓ preserved
current backend+otlp/ctrlb
fan-out · no cutover date

Where the open path stops

  • You instrumented with OTel to stay portable, then sent it to a backend whose storage format you cannot read.
  • Switching backends means re-pointing collectors and abandoning the history the old one holds.
  • Semantic conventions get flattened into whatever the vendor's schema expects, and the fidelity is not recoverable.
  • Three signals arrive over one protocol and then land in three separate stores anyway.

What changes

  • Collectors point at CtrlB with no vendor agent in the path and no instrumentation changes.
  • All three signals land in one lake as open Parquet, in a bucket you own, readable by any Parquet engine.
  • Schema-less ingestion preserves attributes as sent, including the ones your backend would have dropped.
  • Because collectors fan out, you can run CtrlB beside your current backend for as long as the comparison is useful.

How it works

Add CtrlB as a second exporter, run in parallel with your current backend, and compare the same investigation against both — no cutover date required.

Step 01
OTel Collector

your config · your instrumentation

current backend

kept during evaluation

otlp/ctrlb

second exporter · fan-out

parallel run · no cutover date

1

Add an exporter

Add CtrlB as a destination in your existing collector config. Keep the current backend as a second exporter during evaluation.

Step 02
Logs
Metrics
Traces
one Parquet lake
service.namek8s.pod.namehttp.routeexception.type
attributes intact · schema-less
2

Land all three signals

Logs, metrics, and traces write into one Parquet lake with their attributes intact, rather than into three stores with three schemas.

Step 03
s3://telemetry/lake/
logs/metrics/traces/
Full-textservice:"checkout" error
SQLSELECT * FROM logs
PromQLhistogram_quantile(0.99, …)
traceJOINlog line

same files · no tool switch

3

Query one layer

Full-text search, SQL, and PromQL read the same files, so trace-to-log and metric-to-log are joins rather than tool switches.

The collector

One line in the pipeline you already run

Receivers and processors stay exactly as they are. CtrlB is an exporter, which is why adopting it is a config change rather than a project — and why nothing has to be switched off on day one.

ApplicationsSDK or zero-codeKubernetespods, nodes, eventsCloud serviceslogs and metricsOTLPOpenTelemetry Collectorthe one you already runRECEIVERSotlpprometheusfilelogPROCESSORSbatchresourcetail_samplingEXPORTERSctrlbexistingParquet inyour own bucketExisting backenduntouchedkeep or retire later

The whole change, in six lines

Add the exporter, add it to the pipelines you want mirrored. Your existing exporter stays in the list, so both backends receive the same data and you can compare them on your own timeline.

otel-collector.yaml
exporters:
  otlphttp/ctrlb:
    endpoint: https://ingest.ctrlb.ai

service:
  pipelines:
    traces:
      exporters: [existing, otlphttp/ctrlb]
Instrumentation

Whatever your services are written in

CtrlB takes OTLP, so the instrumentation story is OpenTelemetry’s, not ours. Anything that can export OTLP already works.

Java
zero-code
Python
zero-code
Node.js
zero-code
.NET
zero-code
Go
SDK
PHP
zero-code
Ruby
zero-code
Rust
SDK
Kotlin
zero-code
C++
SDK
Swift
SDK
Elixir
SDK
Erlang
SDK
Collector
config

What you get

OTLP native

Semantic conventions kept

Collector fleet control

Parallel running

Vector and Fluent Bit

Portable history

In production on OTel
Blitz · GoComet
Hours → seconds

“Tracing in CtrlB has completely changed how we debug issues at Blitz. We can follow requests across services in seconds instead of hours — it’s cut down our RCA time massively.” — Gaurav Piyush, CTO. GoComet runs the same OTel-native stack across its logistics systems.

See both OTel stacks

Questions

No. If you already emit OTLP, adding CtrlB is a collector configuration change.

Yes, and that is the recommended way to evaluate. Configure two exporters and compare the same investigation against both.

Yes. Ingestion is schema-less, so attributes land as sent and new ones index the moment they appear.

Vector, Fluent Bit, and direct HTTP ingestion are supported for sources that have not moved to OTel.

Put it on your own bucket and see.

Point a source at CtrlB, keep everything else where it is, and compare the same investigation side by side.