ootlp-cGitHub

pure-C99 · OTLP/HTTP · BSD-3

OpenTelemetry,without the C++ runtime

otlp-c emits traces, metrics, and logs over OTLP/HTTP from any C application — kernel modules, firmware, language VMs, preloaded tracers. One static archive. Zero non-libc dependencies. API frozen since 1.0.

133
public symbols
52
test binaries
28
CI gates
0
non-libc deps

One library, three signals

#include <otlp-c/otlp.h>

otlp_exporter_t *exp = otlp_exporter_create(&(otlp_exporter_opts_t){
    .service_name = "my-service",
});
otlp_tracer_t *tr = otlp_tracer_create("scope", "lib", "1.0");

otlp_span_t *s = otlp_tracer_start_span(tr, "GET /users");
otlp_span_set_status(s, OTLP_STATUS_CODE_OK, NULL);
otlp_span_mark_end(s);

otlp_exporter_emit_move(exp, s);   /* queue it, batch + POST on tick */

The library never spawns a thread — you drive I/O withotlp_exporter_tick()from a thread you control.

Built for the places C++ can't go

All three signals

Traces, metrics, logs — including exemplars with trace correlation and schema_url.

Zero non-libc deps

Hand-rolled protobuf encoder + HTTP/1.1 client. No protobuf-c, no libcurl, no OpenSSL.

No library threads

Caller-driven tick(). Never calls pthread_create, never takes a mutex. Lock-free MPSC.

Hardened by construction

CWE-93 header-injection and CWE-190 overflow checks at every boundary — mutation-tested.

Wire-verified

Every schema table descriptor-audited; every payload byte-compared against the reference serialization.

89 ns/span emit

~11M spans/s through the emit pipeline (Release, null transport). Linear in attributes.

From zero to first span in minutes

CMake presets, three CI-pinned consumption paths, and a live otelcol integration suite — or your money back (it's BSD, it's free).

Read the docs