[Dotnet Monitor Experimental] Add getting started for metrics usage using dotnet-monitor (#3318)
* getting-started-dotnet-monitor-metrics * fix markdownlint * Raname NextGen.AutoInstrumentation to just next-gen * Remove logger code.
This commit is contained in:
		
							parent
							
								
									90f347f38e
								
							
						
					
					
						commit
						0a3cb6e8b0
					
				| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
<Project>
 | 
			
		||||
</Project>
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||

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

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

 | 
			
		||||
 | 
			
		||||
## 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)
 | 
			
		||||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 68 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 197 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 244 KiB  | 
		Loading…
	
		Reference in New Issue