Skip to content

Commit f35e3aa

Browse files
author
R9 Fundamentals
committed
moved code to snippets
1 parent dff07e2 commit f35e3aa

File tree

9 files changed

+268
-188
lines changed

9 files changed

+268
-188
lines changed

docs/core/diagnostics/metrics-generator.md

Lines changed: 3 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,8 @@ The following example shows a class that declares two metrics. The methods are m
4343
The code generator runs at build time and provides an implementation of these methods, along with accompanying
4444
types.
4545

46-
```csharp
47-
using System.Diagnostics.Metrics;
48-
using Microsoft.Extensions.Diagnostics.Metrics;
49-
50-
internal class MetricConstants
51-
{
52-
public const string EnvironmentName = "env";
53-
public const string Region = "region";
54-
public const string RequestName = "requestName";
55-
public const string RequestStatus = "requestStatus";
56-
}
57-
58-
internal static partial class Metric
59-
{
60-
// an explicit metric name is given
61-
[Histogram<long>("requestName", "duration", Name = "MyCustomMetricName")]
62-
public static partial Latency CreateLatency(Meter meter);
63-
64-
// no explicit metric name given, it is auto-generated from the method name
65-
[Counter<int>(MetricConstants.EnvironmentName, MetricConstants.Region, MetricConstants.RequestName, MetricConstants.RequestStatus)]
66-
public static partial TotalCount CreateTotalCount(Meter meter);
67-
68-
[Counter<int>]
69-
public static partial TotalFailures CreateTotalFailures(this Meter meter);
70-
}
71-
```
46+
:::code language="csharp" source="snippets/MetricsGen/MetricConstants.cs id="snippet_metricConstants":::
47+
:::code language="csharp" source="snippets/MetricsGen/Metris.cs id="snippet_Metrics" :::
7248

7349
The previous declaration automatically returns the following:
7450

@@ -97,47 +73,7 @@ internal class Latency
9773

9874
The dimensions specified in the attributes have been turned into arguments to the `Add` and `Record` methods. You then use the generated methods to create instances of these types. With the instances created, you can call `Add` and `Record` to register metric values, as shown in the following example:
9975

100-
```csharp
101-
internal class MyClass
102-
{
103-
private readonly Latency _latencyMetric;
104-
private readonly TotalCount _totalCountMetric;
105-
private readonly TotalFailures _totalFailuresMetric;
106-
107-
public MyClass(Meter meter)
108-
{
109-
// Create metric instances using the source-generated factory methods
110-
_latencyMetric = Metric.CreateLatency(meter);
111-
_totalCountMetric = Metric.CreateTotalCount(meter);
112-
// This syntax is available since `CreateTotalFailures` is defined as an extension method
113-
_totalFailuresMetric = meter.CreateTotalFailures();
114-
}
115-
116-
public void ReportSampleRequestCount()
117-
{
118-
// method logic ...
119-
120-
// Invoke Add on the counter and pass the dimension values.
121-
_totalCountMetric.Add(1, envName, regionName, requestName, status);
122-
}
123-
124-
public void ReportSampleLatency()
125-
{
126-
// method logic ...
127-
128-
// Invoke Record on the histogram and pass the dimension values.
129-
_latencyMetric.Record(1, requestName, duration);
130-
}
131-
132-
public void ReportSampleFailuresCount()
133-
{
134-
// method logic ...
135-
136-
// Invoke Add on the counter and pass the dimension values.
137-
_totalFailuresMetric.Add(1);
138-
}
139-
}
140-
```
76+
:::code language="csharp" source="snippets/MetricsGen/MyClass.cs id ="snippet_metricCreation":::
14177

14278
## Metric methods requirements
14379

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

Lines changed: 5 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -42,90 +42,22 @@ By default, the source generator derives metric tag names from the field and pro
4242

4343
The following example demonstrates a simple counter metric with one tag. In this scenario, we want to count the number of processed requests and categorize them by a `Region` tag:
4444

45-
```csharp
46-
public struct RequestTags
47-
{
48-
public string Region { get; set; }
49-
}
50-
51-
public static partial class MyMetrics
52-
{
53-
[Counter<int>(typeof(RequestTags))]
54-
public static partial RequestCount CreateRequestCount(Meter meter);
55-
}
56-
```
45+
:::code language="csharp" source="snippets/MetricsGen/MyMetrics.cs id= "snippet_SimpleMetricTag":::
5746

5847
In the code above, `RequestTags` is a strongly-typed tag struct with a single property `Region`. The `CreateRequestCount` method is marked with <xref:Microsoft.Extensions.Diagnostics.Metrics.CounterAttribute`1> where `T` is an `int`, indicating it generates a **Counter** instrument that tracks `int` values. The attribute references `typeof(RequestTags)`, meaning the counter will use the tags defined in `RequestTags` when recording metrics. The source generator will produce a strongly-typed instrument class (named `RequestCount`) with an `Add` method that accepts integer value and `RequestTags` object.
5948

6049
To use the generated metric, create a <xref:System.Diagnostics.Metrics.Meter> and record measurements as shown below:
6150

62-
```csharp
63-
Meter meter = new Meter("MyCompany.MyApp", "1.0");
64-
RequestCount requestCountMetric = MyMetrics.CreateRequestCount(meter);
65-
66-
// Create a tag object with the relevant tag value
67-
var tags = new RequestTags { Region = "NorthAmerica" };
68-
69-
// Record a metric value with the associated tag
70-
requestCountMetric.Add(1, tags);
71-
```
51+
:::code language="csharp" source="snippets/MetricsGen/MyClass.cs id ="snippet_SimpleMetricTagUsage":::
7252

7353
In this usage example, calling `MyMetrics.CreateRequestCount(meter)` creates a counter instrument (via the `Meter`) and returns a `RequestCount` metric object. When you call `requestCountMetric.Add(1, tags)`, the metric system records a count of 1 associated with the tag `Region="NorthAmerica"`. You can reuse the `RequestTags` object or create new ones to record counts for different regions, and the tag name `Region` will consistently be applied to every measurement.
7454

7555
## Example 2: Metric with nested tag objects
7656

7757
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:
7858

79-
```csharp
80-
using System.Diagnostics.Metrics;
81-
using Microsoft.Extensions.Diagnostics.Metrics;
82-
83-
public class MetricTags : MetricParentTags
84-
{
85-
[TagName("Dim1DimensionName")]
86-
public string? Dim1; // custom tag name via attribute
87-
88-
public Operations Operation { get; set; } // tag name defaults to "Operation"
89-
90-
public MetricChildTags? ChildTagsObject { get; set; }
91-
}
92-
93-
public enum Operations
94-
{
95-
Unknown = 0,
96-
Operation1 = 1,
97-
}
98-
99-
public class MetricParentTags
100-
{
101-
[TagName("DimensionNameOfParentOperation")]
102-
public string? ParentOperationName { get; set; } // custom tag name via attribute
103-
104-
public MetricTagsStruct ChildTagsStruct { get; set; }
105-
}
106-
107-
public class MetricChildTags
108-
{
109-
public string? Dim2 { get; set; } // tag name defaults to "Dim2"
110-
}
111-
112-
public struct MetricTagsStruct
113-
{
114-
public string Dim3 { get; set; } // tag name defaults to "Dim3"
115-
}
116-
117-
public static partial class Metric
118-
{
119-
[Histogram<long>(typeof(MetricTags))]
120-
public static partial Latency CreateLatency(Meter meter);
121-
122-
[Counter<long>(typeof(MetricTags))]
123-
public static partial TotalCount CreateTotalCount(Meter meter);
124-
125-
[Counter<int>(typeof(MetricTags))]
126-
public static partial TotalFailures CreateTotalFailures(Meter meter);
127-
}
128-
```
59+
:::code language="csharp" source="snippets/MetricsGen/MetricTags.cs :::
60+
:::code language="csharp" source="snippets/MetricsGen/Metris.cs id="snippet_MetricTags" :::
12961

13062
In this example, `MetricTags` is a tag class that inherits from `MetricParentTags` and also contains a nested tag object (`MetricChildTags`) and a nested struct (`MetricTagsStruct`). The tag properties demonstrate both default and customized tag names:
13163

@@ -139,55 +71,7 @@ All three metric definitions `CreateLatency`, `CreateTotalCount`, and `CreateTot
13971

14072
The following code shows how to create and use these metrics in a class:
14173

142-
```csharp
143-
internal class MyClass
144-
{
145-
private readonly Latency _latencyMetric;
146-
private readonly TotalCount _totalCountMetric;
147-
private readonly TotalFailures _totalFailuresMetric;
148-
149-
public MyClass(Meter meter)
150-
{
151-
// Create metric instances using the source-generated factory methods
152-
_latencyMetric = Metric.CreateLatency(meter);
153-
_totalCountMetric = Metric.CreateTotalCount(meter);
154-
_totalFailuresMetric = Metric.CreateTotalFailures(meter);
155-
}
156-
157-
public void DoWork()
158-
{
159-
var stopwatch = new Stopwatch();
160-
stopwatch.Start();
161-
bool requestSuccessful = true;
162-
// ... perform some operation ...
163-
stopwatch.Stop();
164-
165-
// Create a tag object with values for all tags
166-
var tags = new MetricTags
167-
{
168-
Dim1 = "Dim1Value",
169-
Operation = Operations.Operation1,
170-
ParentOperationName = "ParentOpValue",
171-
ChildTagsObject = new MetricChildTags
172-
{
173-
Dim2 = "Dim2Value",
174-
},
175-
ChildTagsStruct = new MetricTagsStruct
176-
{
177-
Dim3 = "Dim3Value"
178-
}
179-
};
180-
181-
// Record the metric values with the associated tags
182-
_latencyMetric.Record(stopwatch.ElapsedMilliseconds, tags);
183-
_totalCountMetric.Add(1, tags);
184-
if (!requestSuccessful)
185-
{
186-
_totalFailuresMetric.Add(1, tags);
187-
}
188-
}
189-
}
190-
```
74+
:::code language="csharp" source="snippets/MetricsGen/MyClass.cs id ="snippet_strongMetricCreation":::
19175

19276
In the preceding `MyClass.DoWork` method, a `MetricTags` object is populated with values for each tag. This single `tags` object is then passed to all three instruments when recording data. The `Latency` metric (a histogram) records the elapsed time, and both counters (`TotalCount` and `TotalFailures`) record occurrence counts. Because all metrics share the same tag object type, the tags (`Dim1DimensionName`, `Operation`, `Dim2`, `Dim3`, `DimensionNameOfParentOperation`) are present on every measurement.
19377

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace MetricsGen;
2+
3+
//<snippet_metricConstants>
4+
internal class MetricConstants
5+
{
6+
public const string EnvironmentName = "env";
7+
public const string Region = "region";
8+
public const string RequestName = "requestName";
9+
public const string RequestStatus = "requestStatus";
10+
}
11+
// </snippet_metricConstants>
12+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Microsoft.Extensions.Diagnostics.Metrics;
2+
3+
namespace MetricsGen;
4+
public class MetricTags : MetricParentTags
5+
{
6+
[TagName("Dim1DimensionName")]
7+
public string? Dim1; // custom tag name via attribute
8+
public Operations Operation { get; set; } // tag name defaults to "Operation"
9+
public MetricChildTags? ChildTagsObject { get; set; }
10+
}
11+
12+
public enum Operations
13+
{
14+
Unknown = 0,
15+
Operation1 = 1,
16+
}
17+
18+
public class MetricParentTags
19+
{
20+
[TagName("DimensionNameOfParentOperation")]
21+
public string? ParentOperationName { get; set; } // custom tag name via attribute
22+
public MetricTagsStruct ChildTagsStruct { get; set; }
23+
}
24+
25+
public class MetricChildTags
26+
{
27+
public string? Dim2 { get; set; } // tag name defaults to "Dim2"
28+
}
29+
30+
public struct MetricTagsStruct
31+
{
32+
public string Dim3 { get; set; } // tag name defaults to "Dim3"
33+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#define FIRST // FIRST SECOND
2+
3+
#if FIRST
4+
//<snippet_Metrics>
5+
using System.Diagnostics.Metrics;
6+
using Microsoft.Extensions.Diagnostics.Metrics;
7+
8+
namespace MetricsGen;
9+
10+
internal static partial class Metric
11+
{
12+
// an explicit metric name is given
13+
[Histogram<long>("requestName", "duration", Name = "MyCustomMetricName")]
14+
public static partial Latency CreateLatency(Meter meter);
15+
16+
// no explicit metric name given, it is auto-generated from the method name
17+
[Counter<int>(MetricConstants.EnvironmentName, MetricConstants.Region, MetricConstants.RequestName, MetricConstants.RequestStatus)]
18+
public static partial TotalCount CreateTotalCount(Meter meter);
19+
20+
[Counter<int>]
21+
public static partial TotalFailures CreateTotalFailures(this Meter meter);
22+
internal static Latency CreateLatency(object meter) => throw new NotImplementedException();
23+
}
24+
//</snippet_Metrics>
25+
#elif SECOND
26+
27+
using MetricsGen;
28+
//<snippet_MetricTags>
29+
using System.Diagnostics.Metrics;
30+
using Microsoft.Extensions.Diagnostics.Metrics;
31+
32+
public static partial class Metric
33+
{
34+
[Histogram<long>(typeof(MetricTags))]
35+
public static partial Latency CreateLatency(Meter meter);
36+
37+
[Counter<long>(typeof(MetricTags))]
38+
public static partial TotalCount CreateTotalCount(Meter meter);
39+
40+
[Counter<int>(typeof(MetricTags))]
41+
public static partial TotalFailures CreateTotalFailures(Meter meter);
42+
}
43+
//</snippet_MetricTags>
44+
#endif
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.Extensions.Telemetry.Abstractions" Version="9.4.0" />
12+
</ItemGroup>
13+
14+
</Project>

0 commit comments

Comments
 (0)