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
|
.dockerignore = .dockerignore
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
CONTRIBUTING.md = CONTRIBUTING.md
|
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
|
global.json = global.json
|
||||||
LICENSE = LICENSE
|
LICENSE = LICENSE
|
||||||
NuGet.config = NuGet.config
|
NuGet.config = NuGet.config
|
||||||
OpenTelemetry.proj = OpenTelemetry.proj
|
OpenTelemetry.proj = OpenTelemetry.proj
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
VERSIONING.md = VERSIONING.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
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{7CB2F02E-03FA-4FFF-89A5-C51F107623FD}"
|
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}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "trace", "trace", "{5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "metrics", "metrics", "{3277B1C0-BDFE-4460-9B0D-D9A661FB48DB}"
|
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
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logs", "logs", "{3862190B-E2C5-418E-AFDC-DB281FB5C705}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logs", "logs", "{3862190B-E2C5-418E-AFDC-DB281FB5C705}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
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}.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.ActiveCfg = Release|Any CPU
|
||||||
{9C99621C-343E-479C-A943-332DB6129B71}.Release|Any CPU.Build.0 = 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.ActiveCfg = Debug|Any CPU
|
||||||
{FD8433F4-EDCF-475C-9B4A-625D3DE11671}.Debug|Any CPU.Build.0 = 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
|
{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}.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.ActiveCfg = Release|Any CPU
|
||||||
{D438EF9C-7959-47A0-B2A2-DEBFCDC2A8DC}.Release|Any CPU.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
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