@@ -27,7 +27,8 @@ Status: **Work-In-Progress**
2727 * [ Memory Preallocation] ( #memory-preallocation )
2828* [ Metrics Correlation] ( #metrics-correlation )
2929* [ Modelling Metric Attributes] ( #modelling-metric-attributes )
30- * [ Common Issues Leading to Missing Metrics] ( #common-issues-that-lead-to-missing-metrics )
30+ * [ Common Issues Leading to Missing
31+ Metrics] ( #common-issues-that-lead-to-missing-metrics )
3132
3233</details >
3334
@@ -61,8 +62,8 @@ instances with the same name. `Meter` is fairly expensive and meant to be reused
6162throughout the application. For most applications, a ` Meter ` should be obtained
6263from ` global ` and saved for re-use.
6364
64- > [ !IMPORTANT]
65- > Create your ` Meter ` instance once at initialization time and store it for reuse throughout your application's lifecycle.
65+ > [ !IMPORTANT] Create your ` Meter ` instance once at initialization time and
66+ > store it for reuse throughout your application's lifecycle.
6667
6768The fully qualified module name might be a good option for the Meter name.
6869Optionally, one may create a meter with version, schema_url, and additional
@@ -95,13 +96,12 @@ instruments to their corresponding Rust SDK types.
9596
9697:heavy_check_mark : You should understand and pick the right instrument type.
9798
98- > [ !NOTE]
99- > Picking the right instrument type for your use case is crucial to ensure the
100- correct semantics and performance. Check the [ Instrument
99+ > [ !NOTE] Picking the right instrument type for your use case is crucial to
100+ > ensure the correct semantics and performance. Check the [ Instrument
101101 Selection] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/supplementary-guidelines.md#instrument-selection )
102102section from the supplementary guidelines for more information.
103103
104- | OpenTelemetry Specification | OTel Rust Instrument Type |
104+ | OpenTelemetry Specification | OpenTelemetry Rust Instrument Type |
105105| --------------------------- | -------------------- |
106106| [ Asynchronous Counter] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-counter ) | [ ` ObservableCounter ` ] ( https://docs.rs/opentelemetry/latest/opentelemetry/metrics/struct.ObservableCounter.html ) |
107107| [ Asynchronous Gauge] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-gauge ) | [ ` ObservableGauge ` ] ( https://docs.rs/opentelemetry/latest/opentelemetry/metrics/struct.ObservableGauge.html ) |
@@ -128,8 +128,7 @@ path. Instead, the cloned instance should be stored and reused.
128128:stop_sign : You should avoid changing the order of attributes while reporting
129129measurements.
130130
131- > [ !WARNING]
132- > The last line of code has bad performance since the attributes are
131+ > [ !WARNING] The last line of code has bad performance since the attributes are
133132> not following the same order as before:
134133
135134``` rust
@@ -141,7 +140,9 @@ counter.add(8, &[KeyValue::new("name", "lemon"), KeyValue::new("color", "yellow"
141140```
142141
143142:heavy_check_mark : If feasible, provide the attributes sorted by ` Key ` s in
144- ascending order to minimize memory usage within the Metrics SDK. Using consistent attribute ordering allows the SDK to efficiently reuse internal data structures.
143+ ascending order to minimize memory usage within the Metrics SDK. Using
144+ consistent attribute ordering allows the SDK to efficiently reuse internal data
145+ structures.
145146
146147``` rust
147148// Good practice: Consistent attribute ordering
@@ -236,8 +237,7 @@ fn setup_metrics(meter: &opentelemetry::metrics::Meter) {
236237}
237238```
238239
239- > [ !NOTE]
240- > The callbacks in the Observable instruments are invoked by the SDK
240+ > [ !NOTE] The callbacks in the Observable instruments are invoked by the SDK
241241> during each export cycle.
242242
243243## MeterProvider Management
@@ -290,44 +290,44 @@ follows while implementing the metrics aggregation logic:
2902902 . [ ** Cardinality Limits** ] ( #cardinality-limits ) : the aggregation logic respects
291291 [ cardinality
292292 limits] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#cardinality-limits ) ,
293- so the SDK does not use an indefinite amount of memory in the event of a cardinality
294- explosion.
293+ so the SDK does not use an indefinite amount of memory in the event of a
294+ cardinality explosion.
2952953 . [ ** Memory Preallocation** ] ( #memory-preallocation ) : SDK tries to pre-allocate
296296 the memory it needs at each instrument creation time.
297297
298298### Example
299299
300- Let us take the following example of OTel Rust metrics being used to track the
301- number of fruits sold:
300+ Let us take the following example of OpenTelemetry Rust metrics being used to
301+ track the number of fruits sold:
302302
303303* During the time range (T0, T1] :
304- * value = 1, name = ` apple ` , color = ` red `
305- * value = 2, name = ` lemon ` , color = ` yellow `
304+ * value = 1, color = ` red ` , name = ` apple `
305+ * value = 2, color = ` yellow ` , name = ` lemon `
306306* During the time range (T1, T2] :
307307 * no fruit has been sold
308308* During the time range (T2, T3] :
309- * value = 5, name = ` apple ` , color = ` red `
310- * value = 2, name = ` apple ` , color = ` green `
311- * value = 4, name = ` lemon ` , color = ` yellow `
312- * value = 2, name = ` lemon ` , color = ` yellow `
313- * value = 1, name = ` lemon ` , color = ` yellow `
314- * value = 3, name = ` lemon ` , color = ` yellow `
309+ * value = 5, color = ` red ` , name = ` apple `
310+ * value = 2, color = ` green ` , name = ` apple `
311+ * value = 4, color = ` yellow ` , name = ` lemon `
312+ * value = 2, color = ` yellow ` , name = ` lemon `
313+ * value = 1, color = ` yellow ` , name = ` lemon `
314+ * value = 3, color = ` yellow ` , name = ` lemon `
315315
316316### Example - Cumulative Aggregation Temporality
317317
318318If we aggregate and export the metrics using [ Cumulative Aggregation
319319Temporality] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#temporality ) :
320320
321321* (T0, T1]
322- * attributes: {name = ` apple ` , color = ` red ` }, count: ` 1 `
323- * attributes: {name = ` lemon ` , color = ` yellow ` }, count: ` 2 `
322+ * attributes: {color = ` red ` , name = ` apple ` }, count: ` 1 `
323+ * attributes: {color = ` yellow ` , name = ` lemon ` }, count: ` 2 `
324324* (T0, T2]
325- * attributes: {name = ` apple ` , color = ` red ` }, count: ` 1 `
326- * attributes: {name = ` lemon ` , color = ` yellow ` }, count: ` 2 `
325+ * attributes: {color = ` red ` , name = ` apple ` }, count: ` 1 `
326+ * attributes: {color = ` yellow ` , name = ` lemon ` }, count: ` 2 `
327327* (T0, T3]
328- * attributes: {name = ` apple ` , color = ` red ` }, count: ` 6 `
329- * attributes: {name = ` apple ` , color = ` green ` }, count: ` 2 `
330- * attributes: {name = ` lemon ` , color = ` yellow ` }, count: ` 12 `
328+ * attributes: {color = ` red ` , name = ` apple ` }, count: ` 6 `
329+ * attributes: {color = ` green ` , name = ` apple ` }, count: ` 2 `
330+ * attributes: {color = ` yellow ` , name = ` lemon ` }, count: ` 12 `
331331
332332Note that the start time is not advanced, and the exported values are the
333333cumulative total of what happened since the beginning.
@@ -338,14 +338,14 @@ If we aggregate and export the metrics using [Delta Aggregation
338338Temporality] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#temporality ) :
339339
340340* (T0, T1]
341- * attributes: {name = ` apple ` , color = ` red ` }, count: ` 1 `
342- * attributes: {name = ` lemon ` , color = ` yellow ` }, count: ` 2 `
341+ * attributes: {color = ` red ` , name = ` apple ` }, count: ` 1 `
342+ * attributes: {color = ` yellow ` , name = ` lemon ` }, count: ` 2 `
343343* (T1, T2]
344344 * nothing since we do not have any measurement received
345345* (T2, T3]
346- * attributes: {name = ` apple ` , color = ` red ` }, count: ` 5 `
347- * attributes: {name = ` apple ` , color = ` green ` }, count: ` 2 `
348- * attributes: {name = ` lemon ` , color = ` yellow ` }, count: ` 10 `
346+ * attributes: {color = ` red ` , name = ` apple ` }, count: ` 5 `
347+ * attributes: {color = ` green ` , name = ` apple ` }, count: ` 2 `
348+ * attributes: {color = ` yellow ` , name = ` lemon ` }, count: ` 10 `
349349
350350Note that the start time is advanced after each export, and only the delta since
351351last export is exported, allowing the SDK to "forget" previous state.
@@ -358,7 +358,8 @@ Rust aggregates data locally and only exports the aggregated metrics.
358358Using the [ fruit example] ( #example ) , there are six measurements reported during
359359the time range ` (T2, T3] ` . Instead of exporting each individual measurement
360360event, the SDK aggregates them and exports only the summarized results. This
361- summarization process, illustrated in the following diagram, is known as pre-aggregation:
361+ summarization process, illustrated in the following diagram, is known as
362+ pre-aggregation:
362363
363364``` mermaid
364365graph LR
@@ -395,26 +396,26 @@ Pre-aggregation offers several advantages:
395396 computational load on downstream systems, enabling them to focus on analysis
396397 and storage.
397398
398- > [ !NOTE]
399- > There is no ability to opt out of pre-aggregation in OpenTelemetry.
399+ > [ !NOTE] There is no ability to opt out of pre-aggregation in OpenTelemetry.
400400
401401### Cardinality Limits
402402
403403The number of distinct combinations of attributes for a given metric is referred
404404to as the cardinality of that metric. Taking the [ fruit example] ( #example ) , if
405405we know that we can only have apple/lemon as the name, red/yellow/green as the
406- color, then we can say the cardinality is 6 (i.e., 2 names × 3 colors = 6 combinations). No matter how many
407- fruits we sell, we can always use the following table to summarize the total
408- number of fruits based on the name and color.
409-
410- | Name | Color | Count |
411- | ----- | ------ | ----- |
412- | apple | red | 6 |
413- | apple | yellow | 0 |
414- | apple | green | 2 |
415- | lemon | red | 0 |
416- | lemon | yellow | 12 |
417- | lemon | green | 0 |
406+ color, then we can say the cardinality is 6 (i.e., 2 names × 3 colors = 6
407+ combinations). No matter how many fruits we sell, we can always use the
408+ following table to summarize the total number of fruits based on the name and
409+ color.
410+
411+ | Color | Name | Count |
412+ | ------ | ----- | ----- |
413+ | red | apple | 6 |
414+ | yellow | apple | 0 |
415+ | green | apple | 2 |
416+ | red | lemon | 0 |
417+ | yellow | lemon | 12 |
418+ | green | lemon | 0 |
418419
419420In other words, we know how much memory and network are needed to collect and
420421transmit these metrics, regardless of the traffic pattern or volume.
@@ -429,7 +430,8 @@ example, it can cause:
429430* Surprisingly high costs in the observability system
430431* Excessive memory consumption in your application
431432* Poor query performance in your metrics backend
432- * Potential denial-of-service vulnerability that could be exploited by bad actors
433+ * Potential denial-of-service vulnerability that could be exploited by bad
434+ actors
433435
434436[ Cardinality
435437limit] ( https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#cardinality-limits )
@@ -460,8 +462,8 @@ see much higher cardinality due to:
460462 (This is only applicable to Delta temporality)
461463
462464Therefore, the actual cardinality in your metrics backend can be orders of
463- magnitude higher than what any single OTel SDK process handles in an export
464- cycle.
465+ magnitude higher than what any single OpenTelemetry SDK process handles in an
466+ export cycle.
465467
466468#### Cardinality Limits - Implications
467469
@@ -533,13 +535,14 @@ During a busy sales period at time (T3, T4], we record:
533535
534536The exported metrics would be:
535537
536- * attributes: {name = ` apple ` , color = ` red ` , store_location = ` Downtown ` },
538+ * attributes: {color = ` red ` , name = ` apple ` , store_location = ` Downtown ` },
537539 count: ` 10 `
538- * attributes: {name = ` lemon ` , color = ` yellow ` , store_location = ` Uptown ` },
540+ * attributes: {color = ` yellow ` , name = ` lemon ` , store_location = ` Uptown ` },
539541 count: ` 5 `
540- * attributes: {name = ` apple ` , color = ` green ` , store_location = ` Downtown ` },
542+ * attributes: {color = ` green ` , name = ` apple ` , store_location = ` Downtown ` },
541543 count: ` 8 `
542- * attributes: {` otel.metric.overflow ` = ` true ` }, count: ` 3 ` ← Notice this special overflow attribute
544+ * attributes: {` otel.metric.overflow ` = ` true ` }, count: ` 3 ` ← Notice this
545+ special overflow attribute
543546
544547 If we later query "How many red apples were sold?" the answer would be 10, not
545548 13, because the Midtown sales were folded into the overflow bucket. Similarly,
@@ -577,8 +580,8 @@ A better alternative is to use a concept in OpenTelemetry called
577580Exemplars provide a mechanism to correlate metrics with traces by sampling
578581specific measurements and attaching trace context to them.
579582
580- > [ !NOTE]
581- > Currently, exemplars are not yet implemented in the OpenTelemetry Rust SDK.
583+ > [ !NOTE] Currently, exemplars are not yet implemented in the OpenTelemetry Rust
584+ > SDK.
582585
583586## Modelling Metric Attributes
584587
@@ -604,8 +607,9 @@ attributes can come from different sources:
604607Follow these guidelines when deciding where to attach metric attributes:
605608
606609* ** For static attributes** (constant throughout the process lifetime):
607- * ** Resource-level attributes** : If the dimension applies to all metrics (e.g., hostname, datacenter),
608- model it as a Resource attribute, or better yet, let the collector add these automatically.
610+ * ** Resource-level attributes** : If the dimension applies to all metrics
611+ (e.g., hostname, datacenter), model it as a Resource attribute, or better
612+ yet, let the collector add these automatically.
609613
610614 ``` rust
611615 // Example: Setting resource-level attributes
@@ -615,8 +619,9 @@ Follow these guidelines when deciding where to attach metric attributes:
615619 ]);
616620 ```
617621
618- * * * Meter - level attributes ** : If the dimension applies only to a subset of metrics (e . g. , library version ),
619- model it as meter - level attributes via `meter_with_scope `.
622+ * * * Meter - level attributes ** : If the dimension applies only to a subset of
623+ metrics (e . g. , library version ), model it as meter - level attributes via
624+ `meter_with_scope `.
620625
621626 ```rust
622627 // Example: Setting meter-level attributes
@@ -629,7 +634,8 @@ Follow these guidelines when deciding where to attach metric attributes:
629634
630635* * * For dynamic attributes ** (values that change during execution ):
631636 * Report these via the Metrics API with each measurement .
632- * Be mindful that [cardinality limits ](#cardinality - limits ) apply to these attributes .
637+ * Be mindful that [cardinality limits ](#cardinality - limits ) apply to these
638+ attributes .
633639
634640 ```rust
635641 // Example: Using dynamic attributes with each measurement
@@ -643,10 +649,14 @@ Follow these guidelines when deciding where to attach metric attributes:
643649
644650Common pitfalls that can result in missing metrics include :
645651
646- 1 . * * Invalid instrument names ** - OpenTelemetry will not collect metrics from instruments using invalid names . See the [specification for valid syntax ](https : // github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-name-syntax).
652+ 1 . * * Invalid instrument names ** - OpenTelemetry will not collect metrics from
653+ instruments using invalid names . See the [specification for valid
654+ syntax ](https : // github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-name-syntax).
647655
648- 2 . * * Not calling `shutdown ` on the MeterProvider ** - Ensure you properly call `shutdown ` at application termination to flush any pending metrics .
656+ 2 . * * Not calling `shutdown ` on the MeterProvider ** - Ensure you properly call
657+ `shutdown ` at application termination to flush any pending metrics .
649658
650- 3 . * * Cardinality explosion ** - When too many unique attribute combinations are used , some metrics may be placed in the overflow bucket .
659+ 3 . * * Cardinality explosion ** - When too many unique attribute combinations are
660+ used , some metrics may be placed in the overflow bucket .
651661
652662// TODO: Add more specific examples
0 commit comments