Skip to content

Commit 98f6873

Browse files
reyangCodeBlanch
andauthored
Improve metrics docs (#5279)
Co-authored-by: Mikel Blanchard <[email protected]>
1 parent 48db3e1 commit 98f6873

File tree

2 files changed

+66
-26
lines changed

2 files changed

+66
-26
lines changed

docs/logs/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
The following tutorials have demonstrated the best practices for logging with
66
OpenTelemetry .NET:
77

8-
* [Getting Started - Console Application](./getting-started-console/README.md)
98
* [Getting Started - ASP.NET Core
109
Application](./getting-started-aspnetcore/README.md)
10+
* [Getting Started - Console Application](./getting-started-console/README.md)
1111
* [Logging with Complex Objects](./complex-objects/README.md)
1212

1313
## Structured Logging

docs/metrics/README.md

+65-25
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,75 @@
22

33
## Best Practices
44

5-
### Instruments should be singleton
6-
7-
Instruments SHOULD only be created once and reused throughout the application
8-
lifetime. This [example](../../docs/metrics/getting-started-console/Program.cs)
9-
shows how an instrument is created as a `static` field and then used in the
10-
application. You could also look at this ASP.NET Core
11-
[example](../../examples/AspNetCore/Program.cs) which shows a more Dependency
12-
Injection friendly way of doing this by extracting the `Meter` and an instrument
13-
into a dedicated class called
14-
[Instrumentation](../../examples/AspNetCore/Instrumentation.cs) which is then
15-
added as a `Singleton` service.
16-
17-
### Ordering of tags
18-
19-
When emitting metrics with tags, DO NOT change the order in which you provide
20-
tags. Changing the order of tag keys would increase the time taken by the SDK to
21-
record the measurement.
5+
The following tutorials have demonstrated the best practices for while using
6+
metrics with OpenTelemetry .NET:
7+
8+
* [Getting Started - ASP.NET Core
9+
Application](./getting-started-aspnetcore/README.md)
10+
* [Getting Started - Console Application](./getting-started-console/README.md)
11+
12+
## Package Version
13+
14+
:heavy_check_mark: You should always use the
15+
[System.Diagnostics.Metrics](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics)
16+
APIs from the latest stable version of
17+
[System.Diagnostics.DiagnosticSource](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/)
18+
package, regardless of the .NET runtime version being used:
19+
20+
* If you're using the latest stable version of [OpenTelemetry .NET
21+
SDK](../../src/OpenTelemetry/README.md), you don't have to worry about the
22+
version of `System.Diagnostics.DiagnosticSource` package because it is already
23+
taken care of for you via [package
24+
dependency](../../Directory.Packages.props).
25+
* The .NET runtime team is holding a high bar for backward compatibility on
26+
`System.Diagnostics.DiagnosticSource` even during major version bumps, so
27+
compatibility is not a concern here.
28+
29+
## Metrics API
30+
31+
:heavy_check_mark: You should understand and pick the right instrument type.
32+
33+
> [!NOTE]
34+
> .NET runtime has provided several instrument types based on the [OpenTelemetry
35+
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument).
36+
Picking the right instrument type for your use case is crucial to ensure the
37+
correct semantics and performance. Check the [Instrument
38+
Selection](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/supplementary-guidelines.md#instrument-selection)
39+
section from the supplementary guidelines for more information.
40+
41+
| OpenTelemetry Specification | .NET Instrument Type |
42+
| --------------------------- | -------------------- |
43+
| [Asynchronous Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-counter) | [`ObservableCounter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.observablecounter-1) |
44+
| [Asynchronous Gauge](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-gauge) | [`ObservableGauge<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.observablegauge-1) |
45+
| [Asynchronous UpDownCounter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#asynchronous-updowncounter) | [`ObservableUpDownCounter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.observableupdowncounter-1) |
46+
| [Counter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#counter) | [`Counter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.counter-1) |
47+
| [Gauge](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#gauge) (experimental) | N/A |
48+
| [Histogram](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#histogram) | [`Histogram<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.histogram-1) |
49+
| [UpDownCounter](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#updowncounter) | [`UpDownCounter<T>`](https://learn.microsoft.com/dotnet/api/system.diagnostics.metrics.updowncounter-1) |
50+
51+
:stop_sign: You should avoid creating instruments (e.g. `Counter<T>`) too
52+
frequently. Instruments are fairly expensive and meant to be reused throughout
53+
the application. For most applications, instruments can be modeled as static
54+
readonly fields (e.g. [Program.cs](./getting-started-console/Program.cs)) or
55+
singleton via dependency injection (e.g.
56+
[Instrumentation.cs](../../examples/AspNetCore/Instrumentation.cs)).
57+
58+
:stop_sign: You should avoid changing the order of tags while reporting
59+
measurements.
60+
61+
> [!WARNING]
62+
> The last line of code has bad performance since the tags are not following
63+
the same order:
2264

2365
```csharp
24-
// If you emit the tag keys in this order: name -> color -> taste, stick to this order of tag keys for subsequent measurements.
25-
MyFruitCounter.Add(5, new("name", "apple"), new("color", "red"), new("taste", "sweet"));
26-
...
27-
...
28-
...
29-
// Same measurement with the order of tags changed: color -> name -> taste. This order of tags is different from the one that was first encountered by the SDK.
30-
MyFruitCounter.Add(7, new("color", "red"), new("name", "apple"), new("taste", "sweet")); // <--- DON'T DO THIS
66+
counter.Add(2, new("name", "apple"), new("color", "red"));
67+
counter.Add(3, new("name", "lime"), new("color", "green"));
68+
counter.Add(5, new("name", "lemon"), new("color", "yellow"));
69+
counter.Add(8, new("color", "yellow"), new("name", "lemon")); // bad perf
3170
```
3271

33-
### Use TagList accordingly
72+
:heavy_check_mark: You should use TagList properly to achieve the best
73+
performance.
3474

3575
There are two different ways of passing tags to an instrument API:
3676

0 commit comments

Comments
 (0)