Skip to content

Commit f6f10ba

Browse files
Merge branch 'main' into feature/resource-attribute-tags
2 parents 0a0ef68 + 28ead76 commit f6f10ba

File tree

25 files changed

+787
-523
lines changed

25 files changed

+787
-523
lines changed

docs/logs/README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,21 @@ Here is the rule of thumb:
107107
Minutes - Console Application](./getting-started-console/README.md) tutorial
108108
to learn more.
109109

110+
:heavy_check_mark: You should use dot-separated
111+
[UpperCamelCase](https://en.wikipedia.org/wiki/Camel_case) as the log category
112+
name, which makes it convenient to [filter logs](#log-filtering). A common
113+
practice is to use fully qualified class name, and if further categorization is
114+
desired, append a subcategory name. Refer to the [.NET official
115+
document](https://learn.microsoft.com/dotnet/core/extensions/logging#log-category)
116+
to learn more.
117+
118+
```csharp
119+
loggerFactory.CreateLogger<MyClass>(); // this is equivalent to CreateLogger("MyProduct.MyLibrary.MyClass")
120+
loggerFactory.CreateLogger("MyProduct.MyLibrary.MyClass"); // use the fully qualified class name
121+
loggerFactory.CreateLogger("MyProduct.MyLibrary.MyClass.DatabaseOperations"); // append a subcategory name
122+
loggerFactory.CreateLogger("MyProduct.MyLibrary.MyClass.FileOperations"); // append another subcategory name
123+
```
124+
110125
:stop_sign: You should avoid creating loggers too frequently. Although loggers
111126
are not super expensive, they still come with CPU and memory cost, and are meant
112127
to be reused throughout the application. Refer to the [logging performance
@@ -186,11 +201,6 @@ instances if they are created by you.
186201
API invocation associated with the logger factory could become no-op (i.e. no
187202
logs will be emitted).
188203

189-
:heavy_check_mark: You should use the fully qualified class name as the log
190-
category name. Refer to the [.NET official
191-
document](https://learn.microsoft.com/dotnet/core/extensions/logging#log-category)
192-
to learn more.
193-
194204
## Log Correlation
195205

196206
In OpenTelemetry, logs are automatically correlated to

docs/metrics/customizing-the-sdk/README.md

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -412,58 +412,38 @@ exemplars.
412412

413413
#### ExemplarFilter
414414

415-
`ExemplarFilter` determines which measurements are eligible to become an
416-
Exemplar. i.e. `ExemplarFilter` determines which measurements are offered to
417-
`ExemplarReservoir`, which makes the final decision about whether the offered
418-
measurement gets stored as an exemplar. They can be used to control the noise
419-
and overhead associated with Exemplar collection.
415+
`ExemplarFilter` determines which measurements are offered to the configured
416+
`ExemplarReservoir`, which makes the final decision about whether or not the
417+
offered measurement gets recorded as an `Exemplar`. Generally `ExemplarFilter`
418+
is a mechanism to control the overhead associated with `Exemplar` offering.
420419

421-
OpenTelemetry SDK comes with the following Filters:
420+
OpenTelemetry SDK comes with the following `ExemplarFilters` (defined on
421+
`ExemplarFilterType`):
422422

423-
* `AlwaysOnExemplarFilter` - makes all measurements eligible for being an Exemplar.
424-
* `AlwaysOffExemplarFilter` - makes no measurements eligible for being an
425-
Exemplar. Using this is as good as turning off Exemplar feature, and is the current
423+
* `AlwaysOff`: Makes no measurements eligible for becoming an `Exemplar`. Using
424+
this is as good as turning off the `Exemplar` feature and is the current
426425
default.
427-
* `TraceBasedExemplarFilter` - makes those measurements eligible for being an
428-
Exemplar, which are recorded in the context of a sampled parent `Activity`
429-
(span).
426+
* `AlwaysOn`: Makes all measurements eligible for becoming an `Exemplar`.
427+
* `TraceBased`: Makes those measurements eligible for becoming an `Exemplar`
428+
which are recorded in the context of a sampled `Activity` (span).
430429

431-
`SetExemplarFilter` method on `MeterProviderBuilder` can be used to set the
432-
desired `ExemplarFilter`.
433-
434-
The snippet below shows how to set `ExemplarFilter`.
430+
The `SetExemplarFilter` extension method on `MeterProviderBuilder` can be used
431+
to set the desired `ExemplarFilterType` and enable `Exemplar` collection:
435432

436433
```csharp
437434
using OpenTelemetry;
438435
using OpenTelemetry.Metrics;
439436

440437
using var meterProvider = Sdk.CreateMeterProviderBuilder()
441438
// rest of config not shown
442-
.SetExemplarFilter(new TraceBasedExemplarFilter())
439+
.SetExemplarFilter(ExemplarFilterType.TraceBased)
443440
.Build();
444441
```
445442

446-
> [!NOTE]
447-
> As of today, there is no separate toggle for enable/disable Exemplar feature.
448-
Exemplars can be disabled by setting filter as `AlwaysOffExemplarFilter`, which
449-
is also the default (i.e Exemplar feature is disabled by default). Users can
450-
enable the feature by setting filter to anything other than
451-
`AlwaysOffExemplarFilter`. For example: `.SetExemplarFilter(new TraceBasedExemplarFilter())`.
452-
453-
If the built-in `ExemplarFilter`s are not meeting the needs, one may author
454-
custom `ExemplarFilter` as shown
455-
[here](../extending-the-sdk/README.md#exemplarfilter). A custom filter, which
456-
eliminates all un-interesting measurements from becoming Exemplar is a
457-
recommended way to control performance overhead associated with collecting
458-
Exemplars. See
459-
[benchmark](../../../test/Benchmarks/Metrics/ExemplarBenchmarks.cs) to see how
460-
much impact can `ExemplarFilter` have on performance.
461-
462443
#### ExemplarReservoir
463444

464-
`ExemplarReservoir` receives the measurements sampled in by the `ExemplarFilter`
465-
and is responsible for storing Exemplars. `ExemplarReservoir` ultimately decides
466-
which measurements get stored as exemplars. The following are the default
445+
`ExemplarReservoir` receives the measurements sampled by the `ExemplarFilter`
446+
and is responsible for recording `Exemplar`s. The following are the default
467447
reservoirs:
468448

469449
* `AlignedHistogramBucketExemplarReservoir` is the default reservoir used for
@@ -479,7 +459,7 @@ size (currently defaulting to 1) determines the maximum number of exemplars
479459
stored.
480460

481461
> [!NOTE]
482-
> Currently there is no ability to change or configure Reservoir.
462+
> Currently there is no ability to change or configure `ExemplarReservoir`.
483463
484464
### Instrumentation
485465

docs/metrics/extending-the-sdk/README.md

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,44 +74,7 @@ Not supported.
7474

7575
## ExemplarFilter
7676

77-
OpenTelemetry .NET SDK has provided the following built-in `ExemplarFilter`s:
78-
79-
* [AlwaysOnExemplarFilter](../../../src/OpenTelemetry/Metrics/Exemplar/AlwaysOnExemplarFilter.cs)
80-
* [AlwaysOffExemplarFilter](../../../src/OpenTelemetry/Metrics/Exemplar/AlwaysOffExemplarFilter.cs)
81-
* [TraceBasedExemplarFilter](../../../src/OpenTelemetry/Metrics/Exemplar/TraceBasedExemplarFilter.cs)
82-
83-
Custom exemplar filters can be implemented to achieve filtering based on other criterion:
84-
85-
* `ExemplarFilter` should derive from `OpenTelemetry.ExemplarFilter` (which
86-
belongs to the [OpenTelemetry](../../../src/OpenTelemetry/README.md) package)
87-
and implement the `ShouldSample` method.
88-
89-
One example is a filter, which filters all measurements of value lower
90-
than given threshold is given below. Such a filter prevents any measurements
91-
below the given threshold from ever becoming a `Exemplar`. Such filters could
92-
also incorporate the `TraceBasedExemplarFilter` condition as well, as storing
93-
exemplars for non-sampled traces may be undesired.
94-
95-
```csharp
96-
public sealed class HighValueFilter : ExemplarFilter
97-
{
98-
private readonly double maxValue;
99-
100-
public HighValueFilter(double maxValue)
101-
{
102-
this.maxValue = maxValue;
103-
}
104-
public override bool ShouldSample(long value, ReadOnlySpan<KeyValuePair<string, object>> tags)
105-
{
106-
return Activity.Current?.Recorded && value > this.maxValue;
107-
}
108-
109-
public override bool ShouldSample(double value, ReadOnlySpan<KeyValuePair<string, object>> tags)
110-
{
111-
return Activity.Current?.Recorded && value > this.maxValue;
112-
}
113-
}
114-
```
77+
Not supported.
11578

11679
## ExemplarReservoir
11780

examples/AspNetCore/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
builder
8686
.AddMeter(Instrumentation.MeterName)
8787
#if EXPOSE_EXPERIMENTAL_FEATURES
88-
.SetExemplarFilter(new TraceBasedExemplarFilter())
88+
.SetExemplarFilter(ExemplarFilterType.TraceBased)
8989
#endif
9090
.AddRuntimeInstrumentation()
9191
.AddHttpClientInstrumentation()

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
as it is mandated by the specification.
3131
([#5316](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5268))
3232

33+
* **Experimental (pre-release builds only):** Add support in
34+
`OtlpMetricExporter` for emitting exemplars supplied on Counters, Gauges, and
35+
ExponentialHistograms.
36+
([#5397](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5397))
37+
3338
## 1.7.0
3439

3540
Released 2023-Dec-08

src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/MetricItemExtensions.cs

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
158158
AddAttributes(metricPoint.Tags, dataPoint.Attributes);
159159

160160
dataPoint.AsInt = metricPoint.GetSumLong();
161+
162+
if (metricPoint.TryGetExemplars(out var exemplars))
163+
{
164+
foreach (ref readonly var exemplar in exemplars)
165+
{
166+
dataPoint.Exemplars.Add(
167+
ToOtlpExemplar(exemplar.LongValue, in exemplar));
168+
}
169+
}
170+
161171
sum.DataPoints.Add(dataPoint);
162172
}
163173

@@ -185,6 +195,16 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
185195
AddAttributes(metricPoint.Tags, dataPoint.Attributes);
186196

187197
dataPoint.AsDouble = metricPoint.GetSumDouble();
198+
199+
if (metricPoint.TryGetExemplars(out var exemplars))
200+
{
201+
foreach (ref readonly var exemplar in exemplars)
202+
{
203+
dataPoint.Exemplars.Add(
204+
ToOtlpExemplar(exemplar.DoubleValue, in exemplar));
205+
}
206+
}
207+
188208
sum.DataPoints.Add(dataPoint);
189209
}
190210

@@ -206,6 +226,16 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
206226
AddAttributes(metricPoint.Tags, dataPoint.Attributes);
207227

208228
dataPoint.AsInt = metricPoint.GetGaugeLastValueLong();
229+
230+
if (metricPoint.TryGetExemplars(out var exemplars))
231+
{
232+
foreach (ref readonly var exemplar in exemplars)
233+
{
234+
dataPoint.Exemplars.Add(
235+
ToOtlpExemplar(exemplar.LongValue, in exemplar));
236+
}
237+
}
238+
209239
gauge.DataPoints.Add(dataPoint);
210240
}
211241

@@ -227,6 +257,16 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
227257
AddAttributes(metricPoint.Tags, dataPoint.Attributes);
228258

229259
dataPoint.AsDouble = metricPoint.GetGaugeLastValueDouble();
260+
261+
if (metricPoint.TryGetExemplars(out var exemplars))
262+
{
263+
foreach (ref readonly var exemplar in exemplars)
264+
{
265+
dataPoint.Exemplars.Add(
266+
ToOtlpExemplar(exemplar.DoubleValue, in exemplar));
267+
}
268+
}
269+
230270
gauge.DataPoints.Add(dataPoint);
231271
}
232272

@@ -320,7 +360,14 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
320360
dataPoint.Positive.BucketCounts.Add((ulong)bucketCount);
321361
}
322362

323-
// TODO: exemplars.
363+
if (metricPoint.TryGetExemplars(out var exemplars))
364+
{
365+
foreach (ref readonly var exemplar in exemplars)
366+
{
367+
dataPoint.Exemplars.Add(
368+
ToOtlpExemplar(exemplar.DoubleValue, in exemplar));
369+
}
370+
}
324371

325372
histogram.DataPoints.Add(dataPoint);
326373
}
@@ -333,29 +380,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
333380
return otlpMetric;
334381
}
335382

336-
private static void AddAttributes(ReadOnlyTagCollection tags, RepeatedField<OtlpCommon.KeyValue> attributes)
337-
{
338-
foreach (var tag in tags)
339-
{
340-
if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var result))
341-
{
342-
attributes.Add(result);
343-
}
344-
}
345-
}
346-
347-
private static void AddScopeAttributes(IEnumerable<KeyValuePair<string, object>> meterTags, RepeatedField<OtlpCommon.KeyValue> attributes)
348-
{
349-
foreach (var tag in meterTags)
350-
{
351-
if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var result))
352-
{
353-
attributes.Add(result);
354-
}
355-
}
356-
}
357-
358-
private static OtlpMetrics.Exemplar ToOtlpExemplar<T>(T value, in Metrics.Exemplar exemplar)
383+
internal static OtlpMetrics.Exemplar ToOtlpExemplar<T>(T value, in Metrics.Exemplar exemplar)
359384
where T : struct
360385
{
361386
var otlpExemplar = new OtlpMetrics.Exemplar
@@ -399,4 +424,26 @@ private static OtlpMetrics.Exemplar ToOtlpExemplar<T>(T value, in Metrics.Exempl
399424

400425
return otlpExemplar;
401426
}
427+
428+
private static void AddAttributes(ReadOnlyTagCollection tags, RepeatedField<OtlpCommon.KeyValue> attributes)
429+
{
430+
foreach (var tag in tags)
431+
{
432+
if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var result))
433+
{
434+
attributes.Add(result);
435+
}
436+
}
437+
}
438+
439+
private static void AddScopeAttributes(IEnumerable<KeyValuePair<string, object>> meterTags, RepeatedField<OtlpCommon.KeyValue> attributes)
440+
{
441+
foreach (var tag in meterTags)
442+
{
443+
if (OtlpKeyValueTransformer.Instance.TryTransformTag(tag, out var result))
444+
{
445+
attributes.Add(result);
446+
}
447+
}
448+
}
402449
}

0 commit comments

Comments
 (0)