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

Add basic docs for Metrics api and sdk #2452

Merged
merged 9 commits into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 54 additions & 12 deletions docs/metrics/customizing-the-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@
As shown in the [getting-started](../getting-started/README.md) doc, a valid
[`MeterProvider`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#meterprovider)
must be configured and built to collect metrics with OpenTelemetry .NET Sdk.
`MeterProvider` holds all the configuration for tracing like metricreaders,
`MeterProvider` holds all the configuration for metrics like metricreaders,
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
views, etc. Naturally, almost all the customizations must be done on the
`MeterProvider`.

## Building a MeterProvider

Building a `MeterProvider` is done using `MeterProviderBuilder` which must be
obtained by calling `Sdk.CreateMeterProviderBuilder()`. `MeterProviderBuilder`
exposes various methods which configures the provider it is going to build. These
includes methods like `AddSource`, `AddView` etc, and are explained in
exposes various methods which configures the provider it is going to build.
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
These includes methods like `AddSource`, `AddView` etc, and are explained in
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
subsequent sections of this document. Once configuration is done, calling
`Build()` on the `MeterProviderBuilder` builds the `MeterProvider` instance.
Once built, changes to its configuration is not allowed. In most cases,
a single `MeterProvider` is created at the application startup,
and is disposed when application shuts down.
Once built, changes to its configuration is not allowed. In most cases, a single
`MeterProvider` is created at the application startup, and is disposed when
application shuts down.

The snippet below shows how to build a basic `MeterProvider`. This will create
a provider with default configuration, and is not particularly useful. The
subsequent sections shows how to build a more useful provider.
The snippet below shows how to build a basic `MeterProvider`. This will create a
provider with default configuration, and is not particularly useful. The
subsequent sections show how to build a more useful provider.

```csharp
using OpenTelemetry;
Expand All @@ -36,9 +36,10 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder().Build();

`MeterProvider` holds the metrics configuration, which includes the following:

1. The list of `Meter`s from which measurements are collected.
1. The list of `Meter`s from which instruments are created to report
measurements.
2. The list of instrumentations enabled via
[InstrumentationLibrary](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library).
[Instrumentation Library](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library).
3. The list of
[MetricReaders](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#metricreader),
including exporting readers which exports metrics to
Expand All @@ -52,7 +53,48 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder().Build();

### Meter

// TODO
[`Meter`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#meter)
is used for creating
[`Instruments`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument),
which are then used to report
[Measurements](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#measurement).
The SDK follows an explicit opt-in model for listening to meters. i.e, by
default, it listens to no meters. Every meter which is used to create
instruments must be explicitly added to the meter provider.

`AddSource` method on `MeterProviderBuilder` can be used to add a `Meter` to the
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
provider. The name of the `Meter` (case-insensitive) must be the argument to
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
this method. Multiple `AddSource` can be called to add more than one meter. It
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
also supports wild-card subscription model as well.
cijothomas marked this conversation as resolved.
Show resolved Hide resolved

It is not possible to add meters *after* the provider is built, by calling the
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
`Build()` method on the `MeterProviderBuilder`.

The snippet below shows how to add meters to the provider.

```csharp
using OpenTelemetry;
using OpenTelemetry.Metrics;

using var meterProvider = Sdk.CreateMeterProviderBuilder()
// The following enables instruments from Meter
// named "MyCompany.MyProduct.MyLibrary" only.
.AddSource("MyCompany.MyProduct.MyLibrary")
// The following enables instruments from all Meters
// whose name starts with "AbcCompany.XyzProduct.".
.AddSource("AbcCompany.XyzProduct.*")
.Build();
```

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

**Note**
Copy link
Contributor

Choose a reason for hiding this comment

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

Add colon after "Note".

A common mistake while configuring `MeterProvider` is forgetting to add all
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
`Meter`s to the provider. It is recommended to leverage the wild card
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
subscription model where it makes sense. For example, if your application is
expecting to enable instruments from a number of libraries from a company "Abc",
the you can use `AddSource("Abc.*")` to enable all meters whose name starts
with "Abc.".

### View

Expand Down
69 changes: 69 additions & 0 deletions src/OpenTelemetry.Api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,75 @@ and
[extract](../../examples/MicroserviceExample/Utils/Messaging/MessageReceiver.cs)
context.

## Introduction to OpenTelemetry .NET Metrics API

Metrics in OpenTelemetry .NET is a somewhat unique implementation of the
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
OpenTelemetry project, as the Metrics API are incorporated directly into the
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
.NET runtime itself, as part of the
[`System.Diagnostics.DiagnosticSource`](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/6.0.0-rc.1.21451.13)
package. This means, users can instrument their applications/libraries to emit
metrics by simply using the `System.Diagnostics.DiagnosticSource` package. This
package can be used in applications targetting any of the officially supported
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
versions of [.NET Core](https://dotnet.microsoft.com/download/dotnet-core), and
[.NET Framework](https://dotnet.microsoft.com/download/dotnet-framework) except
for versions lower than `.NET Framework 4.6.1`.

## Instrumenting a library/application with .NET Metrics API

### Basic metric usage

1. Install the `System.Diagnostics.DiagnosticSource` package version
Copy link
Member

Choose a reason for hiding this comment

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

Is this going to be the only way to instrument applications, or is it still possible to include the OpenTelemetry.Api package?

Copy link
Member Author

Choose a reason for hiding this comment

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

the only way. There are no plans to add shim/wrapper around this in the API package.

Copy link
Member

@joaopgrassi joaopgrassi Oct 6, 2021

Choose a reason for hiding this comment

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

So that means that if I want to add metrics to my library, I need to take a dep on the DiagnosticSource package and not OTel? I can see why since this is "built-in", but I feel it would be also good to have a wrapper. For example, people coming from other languages have to learn, yet this new thing which is not so obvious. 🤔

Copy link
Member Author

Choose a reason for hiding this comment

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

If you take a dependency on Otel.API, then it automatically brings in DS package.
This is the same model we use for tracing (and logging) as well.
We added wrapper for tracing, because the Activity API had lot of naming differences (because Activity existed before OTel came into existence.), and many folks felt the need for a wrapper.

Metric API in .NET was built ground up, closely following OTel spec, so there are not many differences, warranting the cost of maintaining another wrapper. Having said that, if there is any strong reason to have a wrapper - please create an issue and we can discuss more.

`6.0.0-rc.1.21451.13` or above to your application or library.

```xml
<ItemGroup>
<PackageReference
Include="System.Diagnostics.DiagnosticSource"
Version="6.0.0-rc.1.21451.13"
/>
</ItemGroup>
```

2. Create a `Meter`, providing the name and version of the library/application
doing the instrumentation. `Meter` instance is typically created once and is
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
reused throughout the application/library.

```csharp
static Meter meter = new Meter(
"companyname.product.instrumentationlibrary",
"semver1.0.0");
```

The above requires import of the `System.Diagnostics.Metrics` namespace.

**Note**
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
It is important to note that `Meter` instances are created by using its
constructor, and *not* by calling a `GetMeter` method on the
`MeterProvider`. This is an important distinction from the [OpenTelemetry
specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#get-a-meter),
where `Meter`s are obtained from `MeterProvider`.

3. Use the `Meter` instance from above to create instruments, which can be used
to report measurements. Just like meter instances, the instrument instances
are to be created once and reused throughout the application/library.

```csharp
Counter<long> counter = meter.CreateCounter<long>("MyFruitCounter");
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
```

4. Use the instruments to report measurements, along with the attributes.

```csharp
counter.Add(1, new("name", "apple"), new("color", "red"));
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
```

The above showed the usage of a `Counter` instrument. The following sections
describes more kinds of instruments.

### Instrument types

// TODO - add all instruments.

## References

* [OpenTelemetry Project](https://opentelemetry.io/)