# opentelemetry-cpp: instrumenting C++ services for traces, metrics and logs

> The OpenTelemetry C++ client is stable across traces, metrics and logs, ships in the Bazel Central Registry, and installs through CMake. Here is what the repository actually documents, and where it stops.

**open-telemetry/opentelemetry-cpp** — The OpenTelemetry C++ Client. To use it with Bazel, add the following to your MODULE.bazel file: For the latest version, see BCR: opentelemetry-cpp.

- Repository: https://github.com/open-telemetry/opentelemetry-cpp
- Website: https://opentelemetry.io/
- Stars: 1,378 · Forks: 635
- Language: C++
- License: Apache-2.0
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/open-telemetry-opentelemetry-cpp

## What opentelemetry-cpp is for, and who ends up using it

The project is the C++ implementation of OpenTelemetry, the vendor-neutral telemetry standard. It exists so that a native service can emit spans, metric instruments and log records through one API and then send them to whichever backend the operator runs, without the application linking against a vendor SDK. The README describes it simply as "The C++ OpenTelemetry client" and marks the project Stable across all three signals: Logs, Metrics and Traces.

The audience is narrow and specific. This is for maintainers of C++ services and libraries who already have a collector or an observability backend in place and need the application side to speak OTLP or another supported protocol. It is also for library authors, because the README frames the getting started guide around instrumenting a small library, not only an executable. If you write C, this is not your client: the README states that supporting the C programming language is not a goal of the current project. If you write managed code, you are on the wrong repository entirely.

## Signals, API and SDK split, and the exporters that ship in the tree

The repository separates api/, sdk/, exporters/, resource_detectors/, ext/ and opentracing-shim/ as top-level directories. That layout reflects the standard OpenTelemetry split: the API is the surface an instrumented library compiles against, the SDK is the implementation an application installs and configures, and exporters translate the SDK's output into a wire format. Keeping them apart means a library can depend on the API alone and stay free of any particular backend.

The exporters directory is where the concrete protocols live, and the examples directory mirrors them: examples/otlp, examples/zipkin, examples/prometheus, examples/grpc and examples/http are all present, alongside examples/logs_simple and examples/metrics_simple. Configuration is a first-class concern rather than an afterthought, visible in examples/configuration, examples/logger_configurator, examples/tracer_configurator and examples/environment_carrier. Processors, which decide how spans are batched or forwarded before export, appear in examples/batch, examples/multi_processor and examples/simple. The README points at examples/simple as "a minimal program demonstrating how to instrument a small library using a simple processor and console exporter, along with build files for CMake and Bazel".

What the README does not do is describe the runtime data flow in prose. There is no architecture narrative in it. The mechanism has to be read out of the directory names, the examples and the linked documentation, and the README itself defers specification coverage to the external spec compliance matrix rather than summarising it.

## Installing opentelemetry-cpp with CMake or Bazel

The README's installation section is one line: it refers the reader to INSTALL.md. The repository also carries a MODULE.bazel at the top level and a .bcr/ directory, which matches the README's statement that the project is published in the Bazel Central Registry. If your project already builds with Bazel, that is the shortest path, and the README gives the exact snippet to add to MODULE.bazel:

```python
bazel_dep(name = "opentelemetry-cpp", version = "x.y.z")
```

The placeholder x.y.z is the README's own; it directs you to the BCR module page for the current version rather than naming one. For CMake users there is no equivalent inline snippet in the README, so the first real step is to open INSTALL.md and follow it there. The CMakeLists.txt at the repository root is the build entry point the CI pipeline exercises.

For a first real use, the README's own recommendation is the example rather than a hand-written program. Build examples/simple, which the README says demonstrates instrumenting a small library with a simple processor and a console exporter and carries build files for both CMake and Bazel. Running it should print telemetry to the console, which is the cheapest way to confirm the SDK initialises, a processor is attached and an exporter is wired before you point anything at a real backend. After that, the examples/otlp directory is the relevant next stop if your destination is an OpenTelemetry collector.

## Where opentelemetry-cpp is the wrong tool

The clearest boundary is the language boundary. The README is explicit that C is out of scope for the current project, so a C codebase cannot treat this as its client and should look at the OpenTelemetry C implementation instead. That is a design decision, not a gap waiting to be filled.

The second boundary is documentation depth in the repository itself. The README does not document the API, the SDK configuration keys or the exporter options; it routes readers to opentelemetry-cpp.readthedocs.io and to INSTALL.md. Anyone expecting a self-contained reference in the repository will be disappointed, and anyone working offline or in an air-gapped build environment should plan for that.

The third is platform support. The CI table lists Ubuntu 22.04 and 24.04 on x86-64, macOS 14 and 15 on arm64, and Windows Server 2022 and 2025 on x86-64. The README hedges by saying the code should generally build on any platform with a compiler supporting the listed C++ standards, but that is an expectation, not a tested claim. If you ship on an architecture outside that table, you are on your own for build and runtime verification.

Finally, specification coverage is not uniform. The README points to the spec compliance matrix to see which portions of the specification are implemented, which implies that not all of it is. Before committing to a signal or a feature, check that matrix rather than assuming parity with other OpenTelemetry language SDKs.

## How it compares with the OpenTracing shim and a vendor SDK

Two comparisons matter in practice. The first is against the opentracing-shim/ directory that ships in this repository. OpenTracing is the predecessor API; the shim exists so that code already instrumented against OpenTracing can be bridged into OpenTelemetry rather than rewritten in one step. The difference in approach is migration versus adoption: the shim keeps an existing instrumentation surface alive, while the OpenTelemetry API is the surface new code should target. If you are starting fresh, the shim adds a translation layer you do not need. If you have a large OpenTracing-instrumented codebase, it is the reason a staged migration is possible at all.

The second is against a vendor SDK. A vendor SDK typically gives you one exporter, tuned for that vendor, with configuration that assumes their endpoint. opentelemetry-cpp inverts that: the API is backend-agnostic, the SDK is configured separately, and the exporter is a swappable component, which is why the tree contains OTLP, Zipkin and Prometheus examples side by side. The cost of that inversion is setup work. You choose and configure an exporter, you decide on a processor, and you are responsible for the resource attributes that identify your service. A vendor SDK makes those choices for you; this one does not.

## Release cadence, licence and the cost of staying current

The project is not archived, and the last push was on 2026-07-16, which is also the date of the v1.28.0 release. Before that, v1.27.0 landed on 2026-05-13 and v1.26.0 on 2026-03-20. That is roughly a two-month cadence across the three most recent releases, and the README says release notes live on the GitHub releases page while upcoming work is tracked in project milestones, with the caveat that "the dates and features described in issues and milestones are estimates, and subject to change".

Upgrade cost depends on how you consume the project. If you build from source against a pinned tag, the cost is the rebuild plus whatever the changelog flags as breaking. The repository carries a Versioning.md and a DEPRECATED.md, which is where the project states its compatibility policy and what has been retired; those two files are the ones to read before bumping a pinned version, because the README does not summarise either. If you consume it through the Bazel Central Registry, the version is pinned in MODULE.bazel and upgrading means editing that one line and resolving whatever the build reports.

The licence is Apache-2.0, a permissive licence that carries an explicit patent grant. That is the whole of what can be said here; the repository also points to docs/dependencies.md for OSS dependency and licence requirements, and that file is the place to look if your organisation audits transitive licences, since the project depends on third-party code under third_party/. Nothing in this article is legal advice, and the dependency list is the artefact your review process should actually read.

## Conclusion

Adopt opentelemetry-cpp if you maintain a C++ service and want vendor-neutral traces, metrics and logs behind one API, and if your toolchain is one of the platforms the CI table lists. Do not adopt it if you need a C API, since the README states that supporting the C programming language is not a goal of the current project, or if you expect the repository itself to hold the full getting started guide rather than pointing at readthedocs. Before writing code, open INSTALL.md and the examples/simple directory, confirm the build path your project already uses (CMake or Bazel), and check the spec compliance matrix to see which parts of the specification are implemented for the signals you plan to emit.

## FAQ

### What is opentelemetry-cpp?

It is the C++ client for OpenTelemetry, described in the README as "The C++ OpenTelemetry client". The project status is Stable across all three signals: Logs, Metrics and Traces.

### Is opentelemetry-cpp free to use?

Yes. The repository is licensed under Apache-2.0, which is a permissive open source licence. The README also points to docs/dependencies.md for OSS dependency and licence requirements.

### Which C++ standards does opentelemetry-cpp support?

The README lists C++14, C++17, C++20 and C++23 as the standards the shipped code generally supports, with any exceptions noted in individual README files. Supporting the C programming language is stated not to be a goal of the current project.

### How do I install opentelemetry-cpp with Bazel?

The README says the project is available in the Bazel Central Registry and gives a bazel_dep line for MODULE.bazel with a version placeholder, directing readers to the BCR module page for the latest version. For CMake, the README refers to INSTALL.md.

### Where can I find opentelemetry-cpp examples?

The examples directory holds them, and the README singles out examples/simple as a minimal program that instruments a small library with a simple processor and a console exporter, with build files for CMake and Bazel. Other directories cover OTLP, Zipkin, Prometheus, gRPC and HTTP.

## Sources

- [Official documentation](https://opentelemetry.io/)
- [Official README](https://github.com/open-telemetry/opentelemetry-cpp#readme)
- [Project repository](https://github.com/open-telemetry/opentelemetry-cpp)
- [Release notes](https://github.com/open-telemetry/opentelemetry-cpp/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/open-telemetry-opentelemetry-cpp
