Skip to content

Commit b849816

Browse files
author
R9 Fundamentals
committed
adding source generated metrics docs
1 parent 4450e54 commit b849816

File tree

4 files changed

+190
-1
lines changed

4 files changed

+190
-1
lines changed

docs/core/diagnostics/metrics-strongly-typed.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ Modern .NET applications can capture metrics using the <xref:System.Diagnostics.
1111
> [!NOTE]
1212
> In the context of metrics, a tag is sometimes also called a "dimension." This article uses "tag" for clarity and consistency with .NET metrics terminology.
1313
14+
## Install the package
15+
16+
To get started, install the [📦 Microsoft.Extensions.Telemetry.Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.Telemetry.Abstractions) NuGet package:
17+
18+
### [.NET CLI](#tab/dotnet-cli)
19+
20+
```dotnetcli
21+
dotnet add package Microsoft.Extensions.Telemetry.Abstractions
22+
```
23+
24+
### [PackageReference](#tab/package-reference)
25+
26+
```xml
27+
<ItemGroup>
28+
<PackageReference Include="Microsoft.Extensions.Telemetry.Abstractions"
29+
Version="*" />
30+
</ItemGroup>
31+
```
32+
33+
---
34+
1435
## Tag name defaults and customization
1536

1637
By default, the source generator derives metric tag names from the field and property names of your tag class. In other words, each public field or property in the strongly-typed tag object becomes a tag name by default. You can override this by using the <xref:Microsoft.Extensions.Diagnostics.Metrics.TagNameAttribute> on a field or property to specify a custom tag name. In the examples below, you’ll see both approaches in action.
@@ -54,6 +75,9 @@ In this usage example, calling `MyMetrics.CreateRequestCount(meter)` creates a c
5475
For more complex scenarios, you can define tag classes that include multiple tags, nested objects, or even inherited properties. This allows a group of related metrics to share a common set of tags easily. In the next example, we define a set of tag classes and use them for three different metrics:
5576

5677
```csharp
78+
using System.Diagnostics.Metrics;
79+
using Microsoft.Extensions.Diagnostics.Metrics;
80+
5781
public class MetricTags : MetricParentTags
5882
{
5983
[TagName("Dim1DimensionName")]
@@ -184,6 +208,7 @@ Adhering to these requirements ensures that the source generator can successfull
184208

185209
## See also
186210

211+
- [Source generated metrics in .NET](source-generated-metrics.md)
187212
- [Creating metrics in .NET (Instrumentation tutorial)](metrics-instrumentation.md)
188213
- [Collecting metrics in .NET (Using MeterListener and exporters)](metrics-collection.md)
189214
- [Logging source generation in .NET](../extensions/logger-message-generator.md) (for a similar source-generation approach applied to logging)

docs/core/diagnostics/metrics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ There are two parts to using metrics in a .NET app:
2828

2929
- [Instrumentation tutorial](metrics-instrumentation.md) - How to create new metrics in code
3030
- [Collection tutorial](metrics-collection.md) - How to store and view metric data for your app
31+
- [Source generated metrics](source-generated-metrics.md) - How to use source generator to create metrics
3132
- [Source-generated metrics with strongly-typed tags](metrics-strongly-typed.md) - How to use source-generated metrics with strongly-typed tags
3233
- [Built-in metrics](built-in-metrics.md) - Discover metrics that are ready for use in .NET runtime libraries
3334
- [Compare metric APIs](compare-metric-apis.md)
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
title: Source-generated metrics
3+
description: Learn how to use a source generator to create metrics in .NET
4+
ms.date: 04/11/2025
5+
---
6+
7+
# Source generated metering
8+
9+
.NET's metering infrastructure is designed to deliver a highly-usable and high-performance metering solution
10+
for modern .NET applications.
11+
12+
To use source generated metering, you first create a class that defines the names and dimensions of the metrics your code can produce.
13+
Then you need to create the class with partial methods signatures.
14+
15+
Then, the .NET's code generator automatically generates the code, which exposes strongly-typed metering types and
16+
methods that you can invoke to record metric values. The generated methods are implemented in a highly efficient
17+
form, which reduces computation overhead as compared to traditional metering solutions.
18+
19+
## Install the package
20+
21+
To get started, install the [📦 Microsoft.Extensions.Telemetry.Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.Telemetry.Abstractions) NuGet package:
22+
23+
### [.NET CLI](#tab/dotnet-cli)
24+
25+
```dotnetcli
26+
dotnet add package Microsoft.Extensions.Telemetry.Abstractions
27+
```
28+
29+
### [PackageReference](#tab/package-reference)
30+
31+
```xml
32+
<ItemGroup>
33+
<PackageReference Include="Microsoft.Extensions.Telemetry.Abstractions"
34+
Version="*" />
35+
</ItemGroup>
36+
```
37+
38+
---
39+
40+
## Generic attributes
41+
42+
Generic attributes are only supported in C# 11 or later, so if you are using generic attributes then please enable C# 11 or later.
43+
Please use non generic attributes if you are using C# 10 or earlier.
44+
45+
## Usage
46+
47+
The following example shows a class that declares two metrics. The methods are marked with an attribute and are declared as `static` and `partial`.
48+
The code generator runs at build time and provides an implementation of these methods, along with accompanying
49+
types.
50+
51+
```csharp
52+
using System.Diagnostics.Metrics;
53+
using Microsoft.Extensions.Diagnostics.Metrics;
54+
55+
internal class MetricConstants
56+
{
57+
public const string EnvironmentName = "env";
58+
public const string Region = "region";
59+
public const string RequestName = "requestName";
60+
public const string RequestStatus = "requestStatus";
61+
}
62+
63+
internal static partial class Metric
64+
{
65+
// an explicit metric name is given
66+
[Histogram<long>("requestName", "duration", Name = "MyCustomMetricName")]
67+
public static partial Latency CreateLatency(Meter meter);
68+
69+
// no explicit metric name given, it is auto-generated from the method name
70+
[Counter<int>(MetricConstants.EnvironmentName, MetricConstants.Region, MetricConstants.RequestName, MetricConstants.RequestStatus)]
71+
public static partial TotalCount CreateTotalCount(Meter meter);
72+
73+
[Counter<int>]
74+
public static partial TotalFailures CreateTotalFailures(Meter meter);
75+
}
76+
```
77+
78+
The previous declaration automatically returns the following:
79+
80+
- `Latency` class with a `Record` method
81+
- `TotalCount` class with an `Add` method
82+
- `TotalFailures` class with a `Add` method.
83+
84+
The attributes indicate the set of dimensions that each metric uses. The signature for the generated types looks like this:
85+
86+
```csharp
87+
internal class TotalCount
88+
{
89+
public void Add(int value, object? env, object? region, object? requestName, object? requestStatus)
90+
}
91+
92+
internal TotalFailures
93+
{
94+
public void Add(int value)
95+
}
96+
97+
internal class Latency
98+
{
99+
public void Record(long value, object? requestName, object? duration);
100+
}
101+
```
102+
103+
The dimensions specified in the attributes have been turned into arguments to the `Add` and `Record` methods.
104+
You then use the generated methods to create instances of these types. With the instances created,
105+
you can call `Add` and `Record` to register metric values, like this:
106+
107+
```csharp
108+
internal class MyClass
109+
{
110+
private readonly Latency _latencyMetric;
111+
private readonly TotalCount _totalCountMetric;
112+
private readonly TotalFailures _totalFailuresMetric;
113+
114+
public MyClass(Meter meter)
115+
{
116+
// Create metric instances using the source-generated factory methods
117+
_latencyMetric = Metric.CreateLatency(meter);
118+
_totalCountMetric = Metric.CreateTotalCount(meter);
119+
_totalFailuresMetric = Metric.CreateTotalFailures(meter);
120+
}
121+
122+
public void ReportSampleRequestCount()
123+
{
124+
// method logic ...
125+
126+
// Invoke Add on the counter and pass the dimension values.
127+
_totalCountMetric.Add(1, envName, regionName, requestName, status);
128+
}
129+
130+
public void ReportSampleLatency()
131+
{
132+
// method logic ...
133+
134+
// Invoke Record on the histogram and pass the dimension values.
135+
_latencyMetric.Record(1, requestName, duration);
136+
}
137+
138+
public void ReportSampleFailuresCount()
139+
{
140+
// method logic ...
141+
142+
// Invoke Add on the counter and pass the dimension values.
143+
_totalFailuresMetric.Add(1);
144+
}
145+
}
146+
```
147+
148+
## Metric methods requirements
149+
150+
Metric methods have some constraints that you must follow:
151+
152+
- They must be static, partial, and public.
153+
- The return type must be unique.
154+
- Their names must not start with an underscore.
155+
- Their parameter names must not start with an underscore.
156+
- Their first parameter must be `Meter`.
157+
- They can't be generic or accept any generic parameters.
158+
159+
## Supported metrics
160+
161+
Please refer to the .NET [`Types of instruments`](https://learn.microsoft.com/dotnet/core/diagnostics/metrics-instrumentation#types-of-instruments) to learn about all the supported instruments and description on how to choose which instrument to use in different situations.

docs/navigate/tools-diagnostics/toc.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,9 @@ items:
391391
displayName: exception summarization,exception summary,exception summarizer,ExceptionSummary
392392
- name: Collection
393393
href: ../../core/diagnostics/metrics-collection.md
394-
- name: Source-generated metrics
394+
- name: Source generated metrics
395+
href: ../../core/diagnostics/source-generated-metrics.md
396+
- name: Strongly typed source-generated metrics
395397
displayName: strongly-typed tags,dimensions
396398
href: ../../core/diagnostics/metrics-strongly-typed.md
397399
- name: Built-in metrics

0 commit comments

Comments
 (0)