|
1 | 1 | # Simple Metrics Example |
2 | 2 |
|
3 | | -In this example, the application in `main.cc` initializes the metrics pipeline |
4 | | -and shows 3 different ways of updating instrument values. Here are more detailed |
5 | | -explanations of each part. |
| 3 | +This example initializes the metrics pipeline with 2 different instrument types. |
| 4 | +Here are more detailed explanations of each part. |
6 | 5 |
|
7 | | -1: Initialize a MeterProvider. We will use this to obtain Meter objects in the |
8 | | -future. |
9 | | - |
10 | | -`auto provider = shared_ptr<MeterProvider>(new MeterProvider);` |
11 | | - |
12 | | -2: Set the MeterProvider as the default instance for the library. This ensures |
13 | | -that we will have access to the same MeterProvider across our application. |
14 | | - |
15 | | -`Provider::SetMeterProvider(provider);` |
16 | | - |
17 | | -3: Obtain a meter from this meter provider. Every Meter pointer returned by the |
18 | | -MeterProvider points to the same Meter. This means that the Meter will be able |
19 | | -to combine metrics captured from different functions without having to |
20 | | -constantly pass the Meter around the library. |
21 | | - |
22 | | -`shared_ptr<Meter> meter = provider→GetMeter("Test");` |
23 | | - |
24 | | -4: Initialize an exporter and processor. In this case, we initialize an OStream |
25 | | -Exporter which will print to stdout by default. The Processor is an |
26 | | -UngroupedProcessor which doesn’t filter or group captured metrics in any way. |
27 | | -The false parameter indicates that this processor will send metric deltas rather |
28 | | -than metric cumulatives. |
| 6 | +1: Initialize an exporter and a reader. In this case, we initialize an OStream |
| 7 | +Exporter which will print to stdout by default. |
| 8 | +The reader periodically collects metrics from the collector and exports them. |
29 | 9 |
|
30 | 10 | ```cpp |
31 | | -unique_ptr<MetricsExporter> exporter = unique_ptr<MetricsExporter>(new OStreamMetricsExporter); |
32 | | -shared_ptr<MetricsProcessor> processor = shared_ptr<MetricsProcessor>(new UngroupedMetricsProcessor(false)); |
| 11 | +std::unique_ptr<metric_sdk::MetricExporter> exporter{new exportermetrics::OStreamMetricExporter}; |
| 12 | +std::unique_ptr<metric_sdk::MetricReader> reader{ |
| 13 | + new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), options)}; |
33 | 14 | ``` |
34 | 15 |
|
35 | | -5: Pass the meter, exporter, and processor into the controller. Since this is a |
36 | | -push controller, a collection interval parameter (in seconds) is also taken. At |
37 | | -each collection interval, the controller will request data from all of the |
38 | | -instruments in the code and export them. Start the controller to begin the |
39 | | -metrics pipeline. |
| 16 | +2: Initialize a MeterProvider and add the reader. |
| 17 | +We will use this to obtain Meter objects in the future. |
40 | 18 |
|
41 | | -`metrics_sdk::PushController controller(meter, std::move(exporter), processor, |
42 | | -5);` `controller.start();` |
| 19 | +```cpp |
| 20 | +auto provider = std::shared_ptr<metrics_api::MeterProvider>(new opentelemetry::metrics::MeterProvider()); |
| 21 | +auto p = std::static_pointer_cast<metric_sdk::MeterProvider>(provider); |
| 22 | +p->AddMetricReader(std::move(reader)); |
| 23 | +``` |
43 | 24 |
|
44 | | -6: Instrument code with synchronous and asynchronous instrument. These |
45 | | -instruments can be placed in areas of interest to collect metrics and are |
46 | | -created by the meter. Synchronous instruments are updated whenever the user |
47 | | -desires with a value and label set. Calling add on a counter instrument for |
48 | | -example will increase its value. Asynchronous instruments can be updated the |
49 | | -same way, but are intended to receive updates from a callback function. The |
50 | | -callback below observes a value of 1. The user never has to call this function |
51 | | -as it is automatically called by the controller. |
| 25 | +3: Create and add a view to the provider. |
52 | 26 |
|
53 | 27 | ```cpp |
54 | | -// Observer callback function |
55 | | -void SumObserverCallback(metrics_api::ObserverResult<int> result){ |
56 | | - std::map<std::string, std::string> labels = {{"key", "value"}}; |
57 | | - auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels}; |
58 | | - result.observe(1,labelkv); |
59 | | -} |
| 28 | +std::unique_ptr<metric_sdk::InstrumentSelector> instrument_selector{ |
| 29 | + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, "name_counter")}; |
| 30 | +std::unique_ptr<metric_sdk::MeterSelector> meter_selector{ |
| 31 | + new metric_sdk::MeterSelector(name, version, schema)}; |
| 32 | +std::unique_ptr<metric_sdk::View> sum_view{ |
| 33 | + new metric_sdk::View{name, "description", metric_sdk::AggregationType::kSum}}; |
| 34 | +p->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(sum_view)); |
| 35 | +``` |
60 | 36 |
|
61 | | -// Create new instruments |
62 | | -auto ctr= meter->NewIntCounter("Counter","none", "none", true); |
63 | | -auto obs= meter->NewIntSumObserver("Counter","none", "none", true, &SumObserverCallback); |
| 37 | +4: Then create a |
| 38 | +[Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#counter) |
| 39 | +instrument from it. Every Meter pointer returned by the |
| 40 | +MeterProvider points to the same Meter. This means that the Meter will be able |
| 41 | +to combine metrics captured from different functions without having to |
| 42 | +constantly pass the Meter around the library. |
64 | 43 |
|
| 44 | +```cpp |
| 45 | +nostd::shared_ptr<metrics_api::Meter> meter = provider->GetMeter(name, "1.2.0"); |
| 46 | +auto double_counter = meter->CreateDoubleCounter(counter_name); |
65 | 47 | // Create a label set which annotates metric values |
66 | 48 | std::map<std::string, std::string> labels = {{"key", "value"}}; |
67 | 49 | auto labelkv = common::KeyValueIterableView<decltype(labels)>{labels}; |
68 | | - |
69 | | -// Capture data from instruments. Note that the asynchronous instrument is updates |
70 | | -// automatically though its callback at the collection interval. Additional measurments |
71 | | -// can be made through calls to its observe function. |
72 | | -ctr->add(5, labelkv); |
73 | | - |
| 50 | +double_counter->Add(val, labelkv); |
74 | 51 | ``` |
75 | 52 |
|
76 | | -7: Stop the controller once the program finished. This ensures that any metrics |
77 | | -inside the pipeline are properly exported. Otherwise, some metrics may be |
78 | | -destroyed in cleanup. |
| 53 | +5: To use histogram instrument, a view with proper `InstrumentType` and `AggregationType` |
| 54 | +has to be added to the provider. |
79 | 55 |
|
80 | | -`controller.stop();` |
| 56 | +```cpp |
| 57 | +std::unique_ptr<metric_sdk::InstrumentSelector> histogram_instrument_selector{ |
| 58 | + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kHistogram, "histogram_name")}; |
| 59 | +std::unique_ptr<metric_sdk::MeterSelector> histogram_meter_selector{ |
| 60 | + new metric_sdk::MeterSelector(name, version, schema)}; |
| 61 | +std::unique_ptr<metric_sdk::View> histogram_view{ |
| 62 | + new metric_sdk::View{name, "description", metric_sdk::AggregationType::kHistogram}}; |
| 63 | +p->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector), |
| 64 | + std::move(histogram_view)); |
| 65 | + |
| 66 | +auto histogram_counter = meter->CreateDoubleHistogram("histogram_name"); |
| 67 | +auto context = opentelemetry::context::Context{}; |
| 68 | +histogram_counter->Record(val, labelkv, context); |
| 69 | +``` |
81 | 70 |
|
82 | 71 | See [CONTRIBUTING.md](../../CONTRIBUTING.md) for instructions on building and |
83 | 72 | running the example. |
|
0 commit comments