Add README for Metrics (#4528)
This commit is contained in:
parent
a0eb6961f4
commit
64df5e3df8
|
|
@ -12,16 +12,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
.dockerignore = .dockerignore
|
||||
.editorconfig = .editorconfig
|
||||
CONTRIBUTING.md = CONTRIBUTING.md
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
test\Directory.Packages.props = test\Directory.Packages.props
|
||||
examples\Directory.Packages.props = examples\Directory.Packages.props
|
||||
docs\Directory.Packages.props = docs\Directory.Packages.props
|
||||
global.json = global.json
|
||||
LICENSE = LICENSE
|
||||
NuGet.config = NuGet.config
|
||||
OpenTelemetry.proj = OpenTelemetry.proj
|
||||
README.md = README.md
|
||||
VERSIONING.md = VERSIONING.md
|
||||
Directory.Packages.props = Directory.Packages.props
|
||||
test\Directory.Packages.props = test\Directory.Packages.props
|
||||
examples\Directory.Packages.props = examples\Directory.Packages.props
|
||||
docs\Directory.Packages.props = docs\Directory.Packages.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7CB2F02E-03FA-4FFF-89A5-C51F107623FD}"
|
||||
|
|
@ -153,6 +153,9 @@ EndProject
|
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "trace", "trace", "{5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metrics", "metrics", "{3277B1C0-BDFE-4460-9B0D-D9A661FB48DB}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
docs\metrics\README.md = docs\metrics\README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logs", "logs", "{3862190B-E2C5-418E-AFDC-DB281FB5C705}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
|
@ -553,10 +556,6 @@ Global
|
|||
{9C99621C-343E-479C-A943-332DB6129B71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C99621C-343E-479C-A943-332DB6129B71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C99621C-343E-479C-A943-332DB6129B71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FD8433F4-EDCF-475C-9B4A-625D3DE11671}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FD8433F4-EDCF-475C-9B4A-625D3DE11671}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD8433F4-EDCF-475C-9B4A-625D3DE11671}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -569,6 +568,10 @@ Global
|
|||
{D438EF9C-7959-47A0-B2A2-DEBFCDC2A8DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D438EF9C-7959-47A0-B2A2-DEBFCDC2A8DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D438EF9C-7959-47A0-B2A2-DEBFCDC2A8DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{62AF4BD3-DCAE-4D44-AA5B-991C1071166B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
# OpenTelemetry .NET Metrics
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Instruments SHOULD only be created once and reused throughout the application
|
||||
lifetime. This
|
||||
[example](../../docs/metrics/getting-started-console/Program.cs) shows how an
|
||||
instrument is created a `static` field and then used in the application. You
|
||||
could also look at this ASP .NET Core
|
||||
[example](../../examples/AspNetCore/Program.cs) which shows a more Dependency
|
||||
Injection friendly way of doing this by extracting the `Meter` and an
|
||||
instrument into a dedicated class called
|
||||
[Instrumentation](../../examples/AspNetCore/Instrumentation.cs) which is then
|
||||
added as a `Singleton` service.
|
||||
|
||||
- When emitting metrics with tags, DO NOT change the order in which you provide
|
||||
tags. Changing the order of tag keys would increase the time taken by the SDK
|
||||
to record the measurement.
|
||||
|
||||
```csharp
|
||||
|
||||
// If you emit the tag keys in this order: name -> color -> taste, stick to this order of tag keys for subsequent measurements.
|
||||
MyFruitCounter.Add(5, new("name", "apple"),new("color", "red"), new("taste", "sweet"));
|
||||
...
|
||||
...
|
||||
...
|
||||
// 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.
|
||||
MyFruitCounter.Add(7, new("color", "red"), new("name", "apple"), new("taste", "sweet")); // <--- DON'T DO THIS
|
||||
```
|
||||
|
||||
- When emitting metrics with more than three tags, use `TagList` for better
|
||||
performance. Using
|
||||
[`TagList`](https://learn.microsoft.com/dotnet/api/system.diagnostics.taglist?view=net-7.0#remarks)
|
||||
avoids allocating any memory for up to eight tags, thereby, reducing the
|
||||
pressure on GC to free up memory.
|
||||
|
||||
```csharp
|
||||
var tags = new TagList
|
||||
{
|
||||
{ "DimName1", "DimValue1" },
|
||||
{ "DimName2", "DimValue2" },
|
||||
{ "DimName3", "DimValue3" },
|
||||
{ "DimName4", "DimValue4" },
|
||||
};
|
||||
|
||||
// Uses a TagList as there are more than three tags
|
||||
counter.Add(100, tags); // <--- DO THIS
|
||||
|
||||
|
||||
// Avoid the below mentioned approaches when there are more than three tags
|
||||
var tag1 = new KeyValuePair<string, object>("DimName1", "DimValue1");
|
||||
var tag2 = new KeyValuePair<string, object>("DimName2", "DimValue2");
|
||||
var tag3 = new KeyValuePair<string, object>("DimName3", "DimValue3");
|
||||
var tag4 = new KeyValuePair<string, object>("DimName4", "DimValue4");
|
||||
|
||||
counter.Add(100, tag1, tag2, tag3, tag4); // <--- DON'T DO THIS
|
||||
|
||||
var readOnlySpanOfTags = new KeyValuePair<string, object>[4] { tag1, tag2, tag3, tag4};
|
||||
counter.Add(100, readOnlySpanOfTags); // <--- DON'T DO THIS
|
||||
```
|
||||
|
||||
- When emitting metrics with more than eight tags, the SDK allocates memory on
|
||||
the hot-path. You SHOULD try to keep the number of tags less than or equal to
|
||||
eight. Check if you can extract any shared tags such as `MachineName`,
|
||||
`Environment` etc. into `Resource` attributes. Refer to this
|
||||
[doc](../../docs/metrics/customizing-the-sdk/README.md#resource) for more
|
||||
information.
|
||||
|
||||
## Common issues that lead to missing metrics
|
||||
|
||||
- The `Meter` used to create the instruments is not added to the
|
||||
`MeterProvider`. Use `AddMeter` method to enable the processing for the
|
||||
required metrics.
|
||||
- Instrument name is invalid. When naming instruments, ensure that the name you
|
||||
choose meets the criteria defined in the
|
||||
[spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-name-syntax).
|
||||
A few notable characters that are not allowed in the instrument name: `/`
|
||||
(forward slash), `\` (backward slash), any space character in the name.
|
||||
- MetricPoint limit is reached. By default, the SDK limits the number of maximum
|
||||
MetricPoints (unique combination of keys and values for a given Metric stream)
|
||||
to `2000`. This limit can be configured using
|
||||
`SetMaxMetricPointsPerMetricStream` method. Refer to this
|
||||
[doc](../../docs/metrics/customizing-the-sdk/README.md#changing-maximum-metricpoints-per-metricstream)
|
||||
for more information. The SDK would not process any newer unique key-value
|
||||
combination that it encounters, once this limit is reached.
|
||||
- MeterProvider is disposed. You need to ensure that the `MeterProvider`
|
||||
instance is kept active for metrics to be collected. In a typical application,
|
||||
a single MeterProvider is built at application startup, and is disposed of at
|
||||
application shutdown. For an ASP.NET Core application, use `AddOpenTelemetry`
|
||||
and `WithMetrics` methods from the `OpenTelemetry.Extensions.Hosting` package
|
||||
to correctly setup `MeterProvider`. Here's a [sample ASP .NET Core
|
||||
app](../../examples/AspNetCore/Program.cs) for reference. For simpler
|
||||
applications such as Console apps, refer to this
|
||||
[example](../../docs/metrics/getting-started-console/Program.cs).
|
||||
Loading…
Reference in New Issue