Skip to content

Commit

Permalink
[Dotnet Monitor Experimental] Add getting started for metrics usage u…
Browse files Browse the repository at this point in the history
…sing dotnet-monitor (open-telemetry#3318)

* getting-started-dotnet-monitor-metrics

* fix markdownlint

* Raname NextGen.AutoInstrumentation to just next-gen

* Remove logger code.
  • Loading branch information
rajkumar-rangaraj authored Mar 16, 2024
1 parent 90f347f commit 0a3cb6e
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 0 deletions.
21 changes: 21 additions & 0 deletions OpenTelemetry.AutoInstrumentation.sln
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "TestApplication.ContinuousP
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.ContinuousProfiler.ContextTracking", "test\test-applications\integrations\TestApplication.ContinuousProfiler.ContextTracking\TestApplication.ContinuousProfiler.ContextTracking.csproj", "{B74CB036-10F5-449D-8CBA-44F77E68D042}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "next-gen", "next-gen", "{3F051815-8E0D-4356-BC36-55CA642DDF18}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started-dotnet-monitor-metrics", "next-gen\docs\getting-started-dotnet-monitor-metrics\getting-started-dotnet-monitor-metrics.csproj", "{022A03CE-DD7A-4326-847E-3B750E660845}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1377,6 +1381,22 @@ Global
{B74CB036-10F5-449D-8CBA-44F77E68D042}.Release|x64.Build.0 = Release|x64
{B74CB036-10F5-449D-8CBA-44F77E68D042}.Release|x86.ActiveCfg = Release|x86
{B74CB036-10F5-449D-8CBA-44F77E68D042}.Release|x86.Build.0 = Release|x86
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|Any CPU.Build.0 = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|ARM64.Build.0 = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|x64.ActiveCfg = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|x64.Build.0 = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|x86.ActiveCfg = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Debug|x86.Build.0 = Debug|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|Any CPU.ActiveCfg = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|Any CPU.Build.0 = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|ARM64.ActiveCfg = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|ARM64.Build.0 = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|x64.ActiveCfg = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|x64.Build.0 = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|x86.ActiveCfg = Release|Any CPU
{022A03CE-DD7A-4326-847E-3B750E660845}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1459,6 +1479,7 @@ Global
{6D35660B-8EFD-4DB6-BE13-46F98BFB626E} = {82A3CE96-0935-45E5-A9AA-A93A5B63500B}
{F10D863B-397D-410E-96AF-D9A749876616} = {82A3CE96-0935-45E5-A9AA-A93A5B63500B}
{B74CB036-10F5-449D-8CBA-44F77E68D042} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
{022A03CE-DD7A-4326-847E-3B750E660845} = {3F051815-8E0D-4356-BC36-55CA642DDF18}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
Expand Down
2 changes: 2 additions & 0 deletions next-gen/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<Project>
</Project>
27 changes: 27 additions & 0 deletions next-gen/docs/getting-started-dotnet-monitor-metrics/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using System.Diagnostics.Metrics;

public class Program
{
private static readonly Meter MyMeter = new("MyCompany.MyProduct.MyLibrary", "1.0");
private static readonly Counter<long> MyFruitCounter = MyMeter.CreateCounter<long>("MyFruitCounter");

public static void Main()
{
Console.WriteLine("Press any key to exit");

while (!Console.KeyAvailable)
{
MyFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
MyFruitCounter.Add(2, new("name", "lemon"), new("color", "yellow"));
MyFruitCounter.Add(1, new("name", "lemon"), new("color", "yellow"));
MyFruitCounter.Add(2, new("name", "apple"), new("color", "green"));
MyFruitCounter.Add(5, new("name", "apple"), new("color", "red"));
MyFruitCounter.Add(4, new("name", "lemon"), new("color", "yellow"));

Thread.Sleep(300);
}
}
}
221 changes: 221 additions & 0 deletions next-gen/docs/getting-started-dotnet-monitor-metrics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# Getting Started with dotnet-monitor, Prometheus and Grafana

- [Produce metrics from the application](#produce-metrics-from-the-application)
- [Collect metrics using dotnet-monitor](#collect-metrics-using-dotnet-monitor)
- [Configuration](#configuration)
- [Running dotnet-monitor](#running-dotnet-monitor)
- [Access and validate the metrics](#access-and-validate-the-metrics)
- [Collect metrics using Prometheus](#collect-metrics-using-prometheus)
- [Prometheus Configuration](#prometheus-configuration)
- [Start Prometheus](#start-prometheus)
- [View results in Prometheus](#view-results-in-prometheus)
- [Explore metrics using Grafana](#explore-metrics-using-grafana)

## Produce metrics from the application

Create a new console application and run it:

```sh
dotnet new console --output getting-started-dotnet-monitor-metrics
cd getting-started-dotnet-monitor-metrics
dotnet run
```

Now copy the code from [Program.cs](./Program.cs) and run the application again.

For our learning purpose, use a while-loop to keep increasing the counter value
until any key is pressed.

```csharp
Console.WriteLine("Press any key to exit");
while (!Console.KeyAvailable)
{
Thread.Sleep(1000);
MyFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
MyFruitCounter.Add(2, new("name", "lemon"), new("color", "yellow"));
MyFruitCounter.Add(1, new("name", "lemon"), new("color", "yellow"));
...
...
...
}
```

## Collect metrics using dotnet-monitor

Follow the [install
steps](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-monitor#install)
to download the dotnet-monitor.

### Configuration

1. **Configure dotnet-monitor API key**: To secure access to the dotnet-monitor
endpoints, you can set up an API key authentication by following the steps
outlined in [Configuring API Key
Authentication](https://github.com/dotnet/dotnet-monitor/blob/main/documentation/api-key-setup.md#configuring-api-key-authentication).
If your use case is limited to a test environment, you might opt to bypass API
key configuration by using the `--no-auth` switch when running dotnet-monitor.
Learn more about dotnet-monitor authentication
[here](https://github.com/dotnet/dotnet-monitor/blob/1beca4d497da1e60985394fe7d1195c0663f7095/documentation/authentication.md?plain=1#L115).

2. **Set a default process and customize metrics collection**: To monitor a
specific local process and capture custom metrics, use a settings.json file.
This file defines both the default process to monitor and the specific meters
to collect metrics. For instance, to monitor a
`getting-started-dotnet-monitor-metrics` process and collect metrics from the
"MyCompany.MyProduct.MyLibrary" meter, create a settings.json file with the
following content:

```json
{
"$schema": "https://aka.ms/dotnet-monitor-schema",
"DefaultProcess": {
"Filters": [{
"Key": "ProcessName",
"Value": "getting-started-dotnet-monitor-metrics"
}]
},
"Metrics": {
"Meters": [
{
"MeterName": "MyCompany.MyProduct.MyLibrary"
}
]
}
}
```

When starting dotnet-monitor, specify the path to this settings.json file using
the `--configuration-file-path` switch.

### Running dotnet-monitor

Run dotnet-monitor in a command prompt or terminal. If you have configured an
API key, ensure to use it. If you are running in a test environment and prefer
not to use authentication, you can start dotnet-monitor with the `--no-auth`
switch:

```bash
dotnet-monitor collect --no-auth --configuration-file-path path/to/settings.json
```

Or, if you have set up an API key:

```bash
dotnet-monitor collect --configuration-file-path path/to/settings.json
```

This command starts the collection process. By default, dotnet-monitor listens
on [http://localhost:52325/](http://localhost:52325/).

### Access and validate the metrics

Access the metrics endpoint. Once dotnet-monitor is running, you can access the
metrics endpoint using a web browser or a tool like curl. The default URL for
metrics is [http://localhost:52325/metrics](http://localhost:52325/metrics). If
you are using authentication, include the API key in your request header. For
example, using curl with an API key:

```bash
curl -H "Authorization: Bearer <Your-API-Key>" http://localhost:52325/metrics
```

Without authentication (in test environments):

```bash
curl http://localhost:52325/metrics
```

![Browser UI](images/dotnet-monitor-metrics.jpg)

Now, we understand how we can configure dotnet-monitor to collect metrics. Next,
we are going to learn about how to use Prometheus to capture metrics from
dotnet-monitor.

## Collect metrics using Prometheus

Follow the [first steps](https://prometheus.io/docs/introduction/first_steps/)
to download the [latest release](https://prometheus.io/download/) of Prometheus.

### Prometheus Configuration

After finished downloading, extract it to a local location that's easy to
access. We will find the default Prometheus configuration YAML file in the
folder, named `prometheus.yml`.

Let's create a new file in the same location as where `prometheus.yml` locates,
and named the new file as `otel.yml` for this exercise. Then, copy and paste the
entire content below into the `otel.yml` file we have created just now.

```yaml
global:
scrape_interval: 10s
evaluation_interval: 10s
scrape_configs:
- job_name: "otel"
static_configs:
- targets: ["localhost:52325"]
```
### Start Prometheus
Follow the instructions from
[starting-prometheus](https://prometheus.io/docs/introduction/first_steps/#starting-prometheus)
to start the Prometheus server and verify it has been started successfully.
Please note that we will need pass in `otel.yml` file as the argument:

```console
./prometheus --config.file=otel.yml
```

### View results in Prometheus

To use the graphical interface for viewing our metrics with Prometheus, navigate
to [http://localhost:9090/graph](http://localhost:9090/graph), and type
`mycompanymyproductmylibrary_MyFruitCounter` in the expression bar of the UI;
finally, click the execute button.

We should be able to see the following chart from the browser:

![Prometheus UI](images/prometheus.jpg)

From the legend, we can see that the `instance` name and the `job` name are the
values we have set in `otel.yml`.

Congratulations!

Now we know how to configure Prometheus server and collect our metrics using
dotnet-monitor. Next, we are going to explore a tool called Grafana, which has
powerful visualizations for the metrics.

### Explore metrics using Grafana

[Install Grafana](https://grafana.com/docs/grafana/latest/installation/).

Start the standalone Grafana server (`grafana-server.exe` or
`./bin/grafana-server`, depending on the operating system). Then, use the
browser to navigate to [http://localhost:3000/](http://localhost:3000/).

Follow the instructions in the Grafana getting started
[doc](https://grafana.com/docs/grafana/latest/getting-started/getting-started/#step-2-log-in)
to log in.

After successfully logging in, click on the explore option on the left panel of
the website - we should be able to write some queries to explore our metrics
now!

Feel free to find some handy PromQL
[here](https://promlabs.com/promql-cheat-sheet/).

In the below example, the query targets to find out what is the per-second rate
of increase of myFruitCounter over the past 5 minutes:

![Grafana UI](images/grafana.jpg)

## Learn more

- [What is Prometheus?](https://prometheus.io/docs/introduction/overview/)
- [Prometheus now supports OpenTelemetry
Metrics](https://horovits.medium.com/prometheus-now-supports-opentelemetry-metrics-83f85878e46a)
- [Grafana support for
Prometheus](https://prometheus.io/docs/visualization/grafana/#creating-a-prometheus-graph)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>getting_started_dotnet_monitor_metrics</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0a3cb6e

Please sign in to comment.