Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metrics customization guide with .NET 9 Advice API details #5911

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
125 changes: 112 additions & 13 deletions docs/metrics/customizing-the-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,51 @@ default boundaries. This requires the use of
new ExplicitBucketHistogramConfiguration { Boundaries = Array.Empty<double>() })
```

#### Determining Explicit Buckets for Histograms

In OpenTelemetry .NET, histograms can be customized using both
the Advice API and the View API. The actual explicit buckets used by
the SDK are determined based on the following factors:

1. The explicit buckets provided by the instrumentation owner via the Advice API.
2. The explicit buckets defined through the View API during SDK initialization.
3. The default buckets provided by the SDK.

Here's how the SDK determines which explicit buckets to use:

1. **View API**: If custom buckets are defined via the View API, these
take precedence over any buckets provided by the Advice API or SDK defaults.
2. **Advice API**: If the View API does not specify custom buckets, the SDK
uses the explicit buckets provided by the Advice API.
3. **SDK Defaults**: If neither the View API nor the Advice API specifies
custom buckets, the SDK applies its default configuration.

Additionally, if an exponential histogram is defined using the View API,
the explicit bucket boundaries provided by the Advice API will be ignored,
as exponential histograms take precedence.
Comment on lines +246 to +248
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to make sure I understand this - if the user leveraged the View API to choose a subset of the attributes, and there are no explicit buckets provided - would the buckets provided by the Hint API take effect or not?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the buckets provided by the Advice (Hint) API would take effect in this case. Here's what I understand:

  1. Exponential Histogram with View API: If the user defines an exponential histogram via the View API, it takes full precedence, and any explicit bucket boundaries provided by the Advice API are ignored.

  2. No Explicit Buckets Provided by View API: If the View API is used but does not define explicit bucket boundaries (e.g., it only filters attributes or configures other aspects), then:

  • The SDK will fall back to the explicit buckets from the Advice (Hint) API if they are available.

  • If no buckets are defined in the Advice API either, then the SDK defaults apply.

@cijothomas Could you please verify if these are correct?


##### Example: Using Explicit Buckets via the Advice API

Here is an example of how to use the Advice API to specify explicit bucket
boundaries for a histogram:

```csharp
using OpenTelemetry.Metrics;

// Create a meter
var meter = new Meter("MyApplication");

// Define bucket boundaries
double[] bucketBoundaries = { 0.0, 10.0, 20.0, 30.0, 40.0, double.MaxValue };

// Create a histogram with explicit buckets using the Advice API
var histogram = meter.CreateHistogram<double>("request_duration", "ms", "Measures the duration of requests", new HistogramOptions { BucketBoundaries = bucketBoundaries });

// Record values
histogram.Record(15.0);
histogram.Record(25.0);
```

##### Base2 exponential bucket histogram aggregation

By default, a Histogram is configured to use the
Expand Down Expand Up @@ -335,6 +380,60 @@ by using Views.

See [Program.cs](./Program.cs) for a complete example.

### Explicit Bucket Histogram Aggregation with .NET 9 Advice API
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s misleading to call it .net 9 advice api as this api can be used in older .net runtimes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unresolved.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thus document is about sdk customization, so histogram advice is somewhat misfit here. we can mention it in the views section about custom buckets, but anything more should be elsewhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unresolved.

Annosha marked this conversation as resolved.
Show resolved Hide resolved

With the introduction of the .NET 9 Advice API, developers can
customize histogram metrics more effectively. The Advice API
allows for explicit bucket boundaries when defining histograms,
leading to more precise and informative metrics.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Customizing buckets via views offer same precision so this statement is not fully true.


#### Overview of the .NET 9 Advice API

The .NET 9 Advice API provides enhancements for metrics collection,
enabling developers to specify how histograms should behave.
This feature is particularly useful when dealing with a known
distribution of values, as it allows for tailored metrics
collection that aligns with application requirements.

#### Using Explicit Bucket Boundaries

To use explicit bucket boundaries in your histograms, follow these steps:

1. **Install Required Packages**: Ensure you have the latest version of the
OpenTelemetry .NET SDK that supports the Advice API.
2. **Define Histogram with Explicit Buckets**: When creating a histogram metric,
Annosha marked this conversation as resolved.
Show resolved Hide resolved
specify the bucket boundaries explicitly using the new API.

**Example**:

```csharp
using OpenTelemetry.Metrics;

// Create a meter
var meter = new Meter("MyApplication");

// Define bucket boundaries
double[] bucketBoundaries = { 0.0, 10.0, 20.0, 30.0, 40.0, double.MaxValue };

// Create a histogram with explicit buckets
var histogram = meter.CreateHistogram<double>("request_duration", "ms", "Measures the duration of requests", new HistogramOptions { BucketBoundaries = bucketBoundaries });

// Record values
histogram.Record(15.0);
histogram.Record(25.0);
```

#### Best Practices

- **Select Meaningful Bucket Boundaries**: When defining bucket
boundaries, consider the typical range of values that your application
processes. This helps to ensure that the histogram provides relevant
insights.
- **Monitor and Adjust**: After implementing explicit bucket
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without some concrete steps to monitor, I think it’s best to omit this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Annosha A lot of comments are marked resolved, but I don't see how. Please leave a comment about how the comment is addressed before resolving them.

boundaries, monitor the metrics collected and adjust the
boundaries as necessary to improve the accuracy and usefulness
of the histogram data.

#### Change the ExemplarReservoir

> [!NOTE]
Expand Down Expand Up @@ -473,11 +572,11 @@ recording of `Exemplar`s.
OpenTelemetry SDK comes with the following `ExemplarFilter`s (defined on
`ExemplarFilterType`):

* (Default behavior) `AlwaysOff`: Makes no measurements eligible for becoming an
- (Default behavior) `AlwaysOff`: Makes no measurements eligible for becoming an
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove all unrelated changes from this PR. We are glad to accept them as a separate PR, so as to keep each PR focused on only one aspect only.

`Exemplar`. Using this disables `Exemplar` collection and avoids all
performance costs associated with `Exemplar`s.
* `AlwaysOn`: Makes all measurements eligible for becoming an `Exemplar`.
* `TraceBased`: Makes those measurements eligible for becoming an `Exemplar`
- `AlwaysOn`: Makes all measurements eligible for becoming an `Exemplar`.
- `TraceBased`: Makes those measurements eligible for becoming an `Exemplar`
which are recorded in the context of a sampled `Activity` (span).

The `SetExemplarFilter` extension method on `MeterProviderBuilder` can be used
Expand Down Expand Up @@ -510,22 +609,22 @@ environmental variables:

Allowed values:

* `always_off`: Equivalent to `ExemplarFilterType.AlwaysOff`
* `always_on`: Equivalent to `ExemplarFilterType.AlwaysOn`
* `trace_based`: Equivalent to `ExemplarFilterType.TraceBased`
- `always_off`: Equivalent to `ExemplarFilterType.AlwaysOff`
- `always_on`: Equivalent to `ExemplarFilterType.AlwaysOn`
- `trace_based`: Equivalent to `ExemplarFilterType.TraceBased`

#### ExemplarReservoir

`ExemplarReservoir` receives the measurements sampled by the `ExemplarFilter`
and is responsible for recording `Exemplar`s. The following are the default
reservoirs:

* `AlignedHistogramBucketExemplarReservoir` is the default reservoir used for
- `AlignedHistogramBucketExemplarReservoir` is the default reservoir used for
Histograms with buckets, and it stores at most one `Exemplar` per histogram
bucket. The `Exemplar` stored is the last measurement recorded - i.e. any new
measurement overwrites the previous one in that bucket.

* `SimpleFixedSizeExemplarReservoir` is the default reservoir used for all
- `SimpleFixedSizeExemplarReservoir` is the default reservoir used for all
metrics except histograms with buckets. It has a fixed reservoir pool, and
implements the equivalent of [naive
reservoir](https://en.wikipedia.org/wiki/Reservoir_sampling). The reservoir pool
Expand Down Expand Up @@ -559,12 +658,12 @@ Though `MetricReader` can be added by using the `AddReader` method on

Refer to the individual exporter docs to learn how to use them:

* [Console](../../../src/OpenTelemetry.Exporter.Console/README.md)
* [In-memory](../../../src/OpenTelemetry.Exporter.InMemory/README.md)
* [OTLP](../../../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md)
- [Console](../../../src/OpenTelemetry.Exporter.Console/README.md)
- [In-memory](../../../src/OpenTelemetry.Exporter.InMemory/README.md)
- [OTLP](../../../src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md)
(OpenTelemetry Protocol)
* [Prometheus HttpListener](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md)
* [Prometheus AspNetCore](../../../src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md)
- [Prometheus HttpListener](../../../src/OpenTelemetry.Exporter.Prometheus.HttpListener/README.md)
- [Prometheus AspNetCore](../../../src/OpenTelemetry.Exporter.Prometheus.AspNetCore/README.md)

### Resource

Expand Down
3 changes: 1 addition & 2 deletions docs/trace/customizing-the-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,7 @@ When using the `AddOpenTelemetry` & `WithTracing` extension methods the
into an existing collection (typically the collection used is the one managed by
the application host). The `TracerProviderBuilder` will be able to access all
services registered into that collection. For lifecycle management, the
`AddOpenTelemetry` registers an [IHostedService
](https://learn.microsoft.com/dotnet/api/microsoft.extensions.hosting.ihostedservice)
`AddOpenTelemetry` registers an [IHostedService](https://learn.microsoft.com/dotnet/api/microsoft.extensions.hosting.ihostedservice)
which is used to automatically start the `TracerProvider` when the host starts
and the host will automatically shutdown and dispose the `TracerProvider` when
it is shutdown.
Expand Down