--- title: Instrumentation linkTitle: Instrumentation aliases: [manual] weight: 30 description: Instrumentation for OpenTelemetry C++ cSpell:ignore: decltype labelkv nostd nullptr --- {{% docs/languages/instrumentation-intro %}} ## Setup Follow the instructions in the [Getting Started Guide](/docs/languages/cpp/getting-started/) to build OpenTelemetry C++. ## Traces ### Initializing tracing ```cpp auto provider = opentelemetry::trace::Provider::GetTracerProvider(); auto tracer = provider->GetTracer("foo_library", "1.0.0"); ``` The `TracerProvider` acquired in the first step is a singleton object that is usually provided by the OpenTelemetry C++ SDK. It is used to provide specific implementations for API interfaces. In case no SDK is used, the API provides a default no-op implementation of a `TracerProvider`. The `Tracer` acquired in the second step is needed to create and start Spans. ### Start a span ```cpp auto span = tracer->StartSpan("HandleRequest"); ``` This creates a span, sets its name to `"HandleRequest"`, and sets its start time to the current time. Refer to the API documentation for other operations that are available to enrich spans with additional data. ### Mark a span as active ```cpp auto scope = tracer->WithActiveSpan(span); ``` This marks a span as active and returns a `Scope` object. The scope object controls how long a span is active. The span remains active for the lifetime of the scope object. The concept of an active span is important, as any span that is created without explicitly specifying a parent is parented to the currently active span. A span without a parent is called root span. ### Create nested Spans ```cpp auto outer_span = tracer->StartSpan("Outer operation"); auto outer_scope = tracer->WithActiveSpan(outer_span); { auto inner_span = tracer->StartSpan("Inner operation"); auto inner_scope = tracer->WithActiveSpan(inner_span); // ... perform inner operation inner_span->End(); } // ... perform outer operation outer_span->End(); ``` Spans can be nested, and have a parent-child relationship with other spans. When a given span is active, the newly created span inherits the active span’s trace ID, and other context attributes. ### Context Propagation ```cpp // set global propagator opentelemetry::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator( nostd::shared_ptr( new opentelemetry::trace::propagation::HttpTraceContext())); // get global propagator HttpTextMapCarrier carrier; auto propagator = opentelemetry::context::propagation::GlobalTextMapPropagator::GetGlobalPropagator(); //inject context to headers auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); propagator->Inject(carrier, current_ctx); //Extract headers to context auto current_ctx = opentelemetry::context::RuntimeContext::GetCurrent(); auto new_context = propagator->Extract(carrier, current_ctx); auto remote_span = opentelemetry::trace::propagation::GetSpan(new_context); ``` `Context` contains the metadata of the currently active Span including Span ID, Trace ID, and flags. Context Propagation is an important mechanism in distributed tracing to transfer this Context across service boundary often through HTTP headers. OpenTelemetry provides a text-based approach to propagate context to remote services using the W3C Trace Context HTTP headers. ### Further Reading - [Traces API](https://opentelemetry-cpp.readthedocs.io/en/latest/otel_docs/namespace_opentelemetry__trace.html) - [Traces SDK](https://opentelemetry-cpp.readthedocs.io/en/latest/otel_docs/namespace_opentelemetry__sdk__trace.html) - [Simple Metrics Example](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/examples/metrics_simple) ## Metrics ### Initialize Exporter and Reader Initialize an exporter and a reader. In this case, we initialize an OStream Exporter which will print to stdout by default. The reader periodically collects metrics from the Aggregation Store and exports them. ```cpp std::unique_ptr exporter{new opentelemetry::exporters::OStreamMetricExporter}; std::unique_ptr reader{ new opentelemetry::sdk::metrics::PeriodicExportingMetricReader(std::move(exporter), options)}; ``` ### Initialize Meter Provider Initialize a MeterProvider and add the reader. We will use this to obtain Meter objects in the future. ```cpp auto provider = std::shared_ptr(new opentelemetry::sdk::metrics::MeterProvider()); auto p = std::static_pointer_cast(provider); p->AddMetricReader(std::move(reader)); ``` ### Create a Counter Create a Counter instrument from the Meter, and record the measurement. Every Meter pointer returned by the MeterProvider points to the same Meter. This means that the Meter will be able to combine metrics captured from different functions without having to constantly pass the Meter around the library. ```cpp auto meter = provider->GetMeter(name, "1.2.0"); auto double_counter = meter->CreateDoubleCounter(counter_name); // Create a label set which annotates metric values std::map labels = {{"key", "value"}}; auto labelkv = common::KeyValueIterableView{labels}; double_counter->Add(val, labelkv); ``` ### Create a Histogram Create a Histogram instrument from the Meter, and record the measurement. ```cpp auto meter = provider->GetMeter(name, "1.2.0"); auto histogram_counter = meter->CreateDoubleHistogram("histogram_name"); histogram_counter->Record(val, labelkv); ``` ### Create Observable Counter Create a Observable Counter Instrument from the Meter, and add a callback. The callback would be used to record the measurement during metrics collection. Ensure to keep the Instrument object active for the lifetime of collection. ```cpp auto meter = provider->GetMeter(name, "1.2.0"); auto counter = meter->CreateDoubleObservableCounter(counter_name); counter->AddCallback(MeasurementFetcher::Fetcher, nullptr); ``` ### Create Views #### Map the Counter Instrument to Sum Aggregation Create a view to map the Counter Instrument to Sum Aggregation. Add this view to provider. View creation is optional unless we want to add custom aggregation config, and attribute processor. Metrics SDK will implicitly create a missing view with default mapping between Instrument and Aggregation. ```cpp std::unique_ptr instrument_selector{ new opentelemetry::sdk::metrics::InstrumentSelector(opentelemetry::sdk::metrics::InstrumentType::kCounter, "counter_name")}; std::unique_ptr meter_selector{ new opentelemetry::sdk::metrics::MeterSelector(name, version, schema)}; std::unique_ptr sum_view{ new opentelemetry::sdk::metrics::View{name, "description", opentelemetry::sdk::metrics::AggregationType::kSum}}; p->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(sum_view)); ``` #### Map the Histogram Instrument to Histogram Aggregation ```cpp std::unique_ptr histogram_instrument_selector{ new opentelemetry::sdk::metrics::InstrumentSelector(opentelemetry::sdk::metrics::InstrumentType::kHistogram, "histogram_name")}; std::unique_ptr histogram_meter_selector{ new opentelemetry::sdk::metrics::MeterSelector(name, version, schema)}; std::unique_ptr histogram_view{ new opentelemetry::sdk::metrics::View{name, "description", opentelemetry::sdk::metrics::AggregationType::kHistogram}}; p->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector), std::move(histogram_view)); ``` #### Map the Observable Counter Instrument to Sum Aggregation ```cpp std::unique_ptr observable_instrument_selector{ new opentelemetry::sdk::metrics::InstrumentSelector(opentelemetry::sdk::metrics::InstrumentType::kObservableCounter, "observable_counter_name")}; std::unique_ptr observable_meter_selector{ new opentelemetry::sdk::metrics::MeterSelector(name, version, schema)}; std::unique_ptr observable_sum_view{ new opentelemetry::sdk::metrics::View{name, "description", opentelemetry::sdk::metrics::AggregationType::kSum}}; p->AddView(std::move(observable_instrument_selector), std::move(observable_meter_selector), std::move(observable_sum_view)); ``` ### Further Reading - [Metrics API](https://opentelemetry-cpp.readthedocs.io/en/latest/otel_docs/namespace_opentelemetry__metrics.html#) - [Metrics SDK](https://opentelemetry-cpp.readthedocs.io/en/latest/otel_docs/namespace_opentelemetry__sdk__metrics.html) - [Simple Metrics Example](https://github.com/open-telemetry/opentelemetry-cpp/tree/main/examples/metrics_simple) ## Logs The documentation for the logs API & SDK is missing, you can help make it available by [editing this page](https://github.com/open-telemetry/opentelemetry.io/edit/main/content/en/docs/languages/cpp/instrumentation.md). ## Next Steps You’ll also want to configure an appropriate exporter to [export your telemetry data](/docs/languages/cpp/exporters) to one or more telemetry backends.