diff --git a/examples/metrics_simple/README.md b/examples/metrics_simple/README.md index b2c5dc0a74..855d2ae611 100644 --- a/examples/metrics_simple/README.md +++ b/examples/metrics_simple/README.md @@ -1,86 +1,116 @@ # Simple Metrics Example -This example initializes the metrics pipeline with 2 different instrument types. -Here are more detailed explanations of each part. +This example initializes the metrics pipeline with 3 different instrument types: -1: 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 collector and exports them. +- [Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#counter) +- [Histogram](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#histogram) +- [Asynchronous/Observable Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-counter) -```cpp -std::unique_ptr exporter{new exportermetrics::OStreamMetricExporter}; -std::unique_ptr reader{ - new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), options)}; -``` + Here are more detailed steps with explanation. Note that the steps 4, 6, and 8 + are done in Instrumentation library for creating and recording Instruments, + and rest of the steps are done in application to configure SDK. -2: Initialize a MeterProvider and add the reader. -We will use this to obtain Meter objects in the future. + Namespace alias used in below steps -```cpp -auto provider = std::shared_ptr(new opentelemetry::metrics::MeterProvider()); -auto p = std::static_pointer_cast(provider); -p->AddMetricReader(std::move(reader)); -``` - -3: Create and add a view to the provider. - -```cpp -std::unique_ptr instrument_selector{ - new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, "name_counter")}; -std::unique_ptr meter_selector{ - new metric_sdk::MeterSelector(name, version, schema)}; -std::unique_ptr sum_view{ - new metric_sdk::View{name, "description", metric_sdk::AggregationType::kSum}}; -p->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(sum_view)); -``` - -4: Then create a -[Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#counter) -instrument from it. 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 -nostd::shared_ptr 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); -``` - -5: To use histogram instrument, a view with proper `InstrumentType` and `AggregationType` -has to be added to the provider. - -```cpp -std::unique_ptr histogram_instrument_selector{ - new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kHistogram, "histogram_name")}; -std::unique_ptr histogram_meter_selector{ - new metric_sdk::MeterSelector(name, version, schema)}; -std::unique_ptr histogram_view{ - new metric_sdk::View{name, "description", metric_sdk::AggregationType::kHistogram}}; -p->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector), - std::move(histogram_view)); - -auto histogram_counter = meter->CreateDoubleHistogram("histogram_name"); -auto context = opentelemetry::context::Context{}; -histogram_counter->Record(val, labelkv, context); -``` - -See [CONTRIBUTING.md](../../CONTRIBUTING.md) for instructions on building and -running the example. + ```cpp +using namespace metrics_api = opentelemetry::metrics; +using namespace metric_sdk = opentelemetry::sdk::metrics; +using namespace exportermetrics = opentelemetry::exporters; -## Additional Documentation + ``` -[API -Design](https://github.com/open-o11y/docs/blob/master/cpp-metrics/api-design.md) +1. 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. -[SDK -Design](https://github.com/open-o11y/docs/blob/master/cpp-metrics/sdk-design.md) + ```cpp + std::unique_ptr exporter{new exportermetrics::OStreamMetricExporter}; + std::unique_ptr reader{ + new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), options)}; + ``` -[OStreamExporters -Design](https://github.com/open-o11y/docs/blob/master/cpp-ostream/ostream-exporter-design.md) +2. Initialize a MeterProvider and add the reader. +We will use this to obtain Meter objects in the future. -[OpenTelemetry C++ Metrics -Overview](https://github.com/open-o11y/docs/blob/master/cpp-metrics/README.md) + ```cpp + auto provider = std::shared_ptr(new metric_sdk::MeterProvider()); + auto p = std::static_pointer_cast(provider); + p->AddMetricReader(std::move(reader)); + ``` + +3. Optional: 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 metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, "counter_name")}; + std::unique_ptr meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr sum_view{ + new metric_sdk::View{name, "description", metric_sdk::AggregationType::kSum}}; + p->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(sum_view)); + ``` + +4. 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); + ``` + +5. Optional: Create a view to map the Histogram Instrument to Histogram Aggregation. + + ```cpp + std::unique_ptr histogram_instrument_selector{ + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kHistogram, "histogram_name")}; + std::unique_ptr histogram_meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr histogram_view{ + new metric_sdk::View{name, "description", metric_sdk::AggregationType::kHistogram}}; + p->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector), + std::move(histogram_view)); + ``` + +6. 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); + ``` + +7. Optional: Create a view to map the Observable Counter Instrument to Sum Aggregation + + ```cpp + std::unique_ptr observable_instrument_selector{ + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kObservableCounter, + "observable_counter_name")}; + std::unique_ptr observable_meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr observable_sum_view{ + new metric_sdk::View{name, "description", metric_sdk::AggregationType::kSum}}; + p->AddView(std::move(observable_instrument_selector), std::move(observable_meter_selector), + std::move(observable_sum_view)); + ``` + +8. Create a Observable Counter Instrument from the Meter, and add a callback. +The callbackwould 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); + ``` + +See [INSTALL.md](../../INSTALL.md) for instructions on building and +running the example.