Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek se vztahuje na: ✔️ .NET 6.0 a novější ✔️ .NET Framework 4.6.1 a novější
Instrumentovaný kód může zaznamenávat číselné měření, ale měření je obvykle potřeba agregovat, přenášet a ukládat, aby se vytvořily užitečné metriky pro monitorování. Proces agregace, přenosu a ukládání dat se nazývá shromažďování. Tento kurz ukazuje několik příkladů shromažďování metrik:
- Vyplňování metrik v Grafana s využitím OpenTelemetry a Prometheus.
- Zobrazení metrik v reálném čase pomocí
dotnet-counters - Vytvoření vlastního nástroje kolekce pomocí podkladového rozhraní .NET MeterListener API
Další informace o vlastní instrumentaci a možnostech metrik viz Porovnání rozhraní API metrik.
Požadavky
- .NET 6.0 SDK nebo novější
Vytvoření ukázkové aplikace
Než je možné shromažďovat metriky, musí se vytvořit měření. Tento kurz vytvoří aplikaci, která má základní instrumentaci metrik. Modul runtime .NET má také integrované různé metriky. Další informace o vytváření nových metrik pomocí System.Diagnostics.Metrics.Meter rozhraní API najdete v kurzu instrumentace.
dotnet new console -o metric-instr
cd metric-instr
dotnet add package System.Diagnostics.DiagnosticSource
Obsah Program.cs nahraďte následujícím kódem:
using System.Diagnostics.Metrics;
class Program
{
static Meter s_meter = new("HatCo.HatStore", "1.0.0");
static Counter<int> s_hatsSold = s_meter.CreateCounter<int>("hats-sold");
static void Main(string[] args)
{
var rand = Random.Shared;
Console.WriteLine("Press any key to exit");
while (!Console.KeyAvailable)
{
//// Simulate hat selling transactions.
Thread.Sleep(rand.Next(100, 2500));
s_hatsSold.Add(rand.Next(0, 1000));
}
}
}
Předchozí kód simuluje prodej klobouků v náhodných intervalech a náhodných časech.
Zobrazení metrik pomocí dotnet-counters
dotnet-counters je nástroj příkazového řádku, který může zobrazit živé metriky pro aplikace .NET Core na vyžádání. Nevyžaduje nastavení, což je užitečné pro ad hoc šetření nebo ověření, že instrumentace metrik funguje. Funguje s rozhraními API založenými na System.Diagnostics.Metrics a EventCounters.
Pokud nástroj dotnet-counters není nainstalovaný, spusťte následující příkaz:
dotnet tool update -g dotnet-counters
Pokud vaše aplikace používá verzi .NET starší než .NET 9, bude výstupní uživatelské rozhraní čítačů dotnet-counters vypadat trochu jinak než níže. Podrobnosti najdete v čítačích dotnet. .
Zatímco je ukázková aplikace spuštěná, spusťte dotnet-counters. Následující příkaz ukazuje příklad dotnet-counters monitorování všech metrik z měřiče HatCo.HatStore . V názvu měřiče se rozlišují malá a velká písmena. Naše ukázková aplikace byla metric-instr.exe, nahraďte ji názvem vaší ukázkové aplikace.
dotnet-counters monitor -n metric-instr HatCo.HatStore
Zobrazí se výstup podobný následujícímu:
Press p to pause, r to resume, q to quit.
Status: Running
[HatCo.HatStore]
hats-sold (Count / 1 sec) 4
dotnet-counters můžete spustit s jinou sadou metrik, abyste viděli některé z integrovaných monitoračních nástrojů prostředí .NET runtime.
dotnet-counters monitor -n metric-instr
Zobrazí se výstup podobný následujícímu:
System.Runtime
Press p to pause, r to resume, q to quit.
Status: Running
Name Current Value
[System.Runtime]
dotnet.assembly.count ({assembly}) 11
dotnet.gc.collections ({collection})
gc.heap.generation
------------------
gen0 0
gen1 0
gen2 0
dotnet.gc.heap.total_allocated (By) 1,376,024
dotnet.gc.last_collection.heap.fragmentation.size (By)
gc.heap.generation
------------------
gen0 0
gen1 0
gen2 0
loh 0
poh 0
dotnet.gc.last_collection.heap.size (By)
gc.heap.generation
------------------
gen0 0
gen1 0
gen2 0
loh 0
poh 0
dotnet.gc.last_collection.memory.committed_size (By) 0
dotnet.gc.pause.time (s) 0
dotnet.jit.compilation.time (s) 0.253
dotnet.jit.compiled_il.size (By) 79,536
dotnet.jit.compiled_methods ({method}) 743
dotnet.monitor.lock_contentions ({contention}) 0
dotnet.process.cpu.count ({cpu}) 22
dotnet.process.cpu.time (s)
cpu.mode
--------
system 0.125
user 46.453
dotnet.process.memory.working_set (By) 34,447,360
dotnet.thread_pool.queue.length ({work_item}) 0
dotnet.thread_pool.thread.count ({thread}) 0
dotnet.thread_pool.work_item.count ({work_item}) 0
dotnet.timer.count ({timer}) 0
Další informace najdete v tématu dotnet-counters. Další informace o metrikách v .NET najdete v předdefinovaných metrikách.
Zobrazení metrik v Grafaně pomocí OpenTelemetry a Prometheus
Přehled
- Je dodavatelově neutrální opensourcový projekt podporovaný foundationm Cloud Native Computing Foundation.
- Standardizuje generování a shromažďování telemetrie pro nativní cloudový software.
- Pracuje s .NET pomocí rozhraní API pro metriky .NET.
- Podporují jej Azure Monitor a mnoho dodavatelů APM.
Tento kurz ukazuje jednu z integrací dostupných pro metriky OpenTelemetry pomocí projektů OSS Prometheus a Grafana . Tok dat o metrikách:
Rozhraní API pro metriky .NET zaznamenávají měření z příkladové aplikace.
Knihovna OpenTelemetry spuštěná v aplikaci agreguje měření.
Knihovna exportéru Prometheus zpřístupňuje agregovaná data prostřednictvím koncového bodu metrik HTTP. "Exportér" je termín, kterým OpenTelemetry označuje knihovny, které přenášejí telemetrii do prodejcem specifických back-endů.
Server Promethea:
- Dotazuje se na koncový bod metrik.
- Čte data.
- Ukládá data do databáze pro dlouhodobou trvalost. Prometheus označuje čtení a ukládání dat jako škrábání koncového bodu.
- Může běžet na jiném počítači.
Server Grafana:
- Dotazuje data uložená v systému Prometheus a zobrazí je na webovém řídicím panelu monitorování.
- Může běžet na jiném počítači.
Konfigurace ukázkové aplikace tak, aby používala exportér OpenTelemetry Prometheus
Do ukázkové aplikace přidejte odkaz na vývozce OpenTelemetry Prometheus:
dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener --prerelease
Poznámka:
V tomto kurzu se používá předběžné sestavení podpory OpenTelemetry pro Prometheus dostupné v době psaní tohoto textu.
Aktualizace Program.cs s využitím konfigurace OpenTelemetry:
using OpenTelemetry;
using OpenTelemetry.Metrics;
using System.Diagnostics.Metrics;
class Program
{
static Meter s_meter = new("HatCo.HatStore", "1.0.0");
static Counter<int> s_hatsSold = s_meter.CreateCounter<int>(
name: "hats-sold",
unit: "Hats",
description: "The number of hats sold in our store");
static void Main(string[] args)
{
using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter("HatCo.HatStore")
.AddPrometheusHttpListener(options => options.UriPrefixes = new string[] { "http://localhost:9184/" })
.Build();
var rand = Random.Shared;
Console.WriteLine("Press any key to exit");
while (!Console.KeyAvailable)
{
//// Simulate hat selling transactions.
Thread.Sleep(rand.Next(100, 2500));
s_hatsSold.Add(rand.Next(0,1000));
}
}
}
V předchozím kódu:
-
AddMeter("HatCo.HatStore")nakonfiguruje OpenTelemetry tak, aby přenášela všechny metriky shromážděné měřičem definovaným v aplikaci. -
AddPrometheusHttpListenerNakonfiguruje OpenTelemetry na:- Zveřejnění koncového bodu metriky Prometheus na portu
9184 - Použijte httpListener.
- Zveřejnění koncového bodu metriky Prometheus na portu
Další informace o možnostech konfigurace OpenTelemetry najdete v dokumentaci k OpenTelemetry . Dokumentace k OpenTelemetry ukazuje možnosti hostování ASP.NET aplikací.
Spusťte aplikaci a nechte ji spuštěnou, aby bylo možné shromažďovat měření:
dotnet run
Nastavení a konfigurace Prometheus
Podle prvních kroků prometheus nastavte server Prometheus a ověřte, že funguje.
Upravte konfigurační soubor prometheus.yml tak, aby Prometheus sbíral metriky z koncového bodu, který ukázková aplikace vystavuje. Do oddílu scrape_configs přidejte následující zvýrazněný text:
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ["localhost:9090"]
- job_name: 'OpenTelemetryTest'
scrape_interval: 1s # poll very quickly for a more responsive demo
static_configs:
- targets: ['localhost:9184']
Spustit Prometheus
Znovu načtěte konfiguraci nebo restartujte server Prometheus.
Ověřte, že OpenTelemetryTest je ve stavu UP na stránce Cílové stavy webového portálu Prometheus.
Na stránce Graf webového portálu Prometheus zadejte
hatsdo textového pole výrazu a v kartě grafu vybertehats_sold_Hats
. Na kartě grafu Prometheus zobrazuje rostoucí hodnotu čítače "hats-sold", který je generován ukázkovou aplikací.
Na předchozím obrázku je čas grafu nastavený na 5 min, což je 5 minut.
Pokud server Prometheus dlouho nešrotoval ukázkové aplikace, možná budete muset počkat, až se data nahromáždí.
Zobrazení metrik na řídicím panelu Grafana
Podle standardních pokynů nainstalujte Grafana a připojte ho ke zdroji dat Prometheus.
Vytvořte řídicí panel Grafana kliknutím + na ikonu na levém panelu nástrojů na webovém portálu Grafana a pak vyberte Řídicí panel. V zobrazeném editoru řídicího panelu zadejte Hats Sold/Sec do vstupního pole Nadpis a rate(hats_sold[5m]) do pole výrazu PromQL:
Kliknutím na Použít uložíte a zobrazíte nový řídicí panel.
Vytvoření vlastního nástroje pro kolekci pomocí rozhraní API meterListener .NET
Rozhraní .NET MeterListener API umožňuje vytvořit vlastní logiku v rámci procesu pro sledování měření zaznamenávaných System.Diagnostics.Metrics.Meter. Pokyny k vytvoření vlastní logiky kompatibilní se starší instrumentací EventCounters najdete v tématu EventCounters.
Upravte kód Program.cs, aby používal MeterListener.
using System.Diagnostics.Metrics;
class Program
{
static Meter s_meter = new("HatCo.HatStore", "1.0.0");
static Counter<int> s_hatsSold = s_meter.CreateCounter<int>(
name: "hats-sold",
unit: "Hats",
description: "The number of hats sold in our store");
static void Main(string[] args)
{
using MeterListener meterListener = new();
meterListener.InstrumentPublished = (instrument, listener) =>
{
if (instrument.Meter.Name is "HatCo.HatStore")
{
listener.EnableMeasurementEvents(instrument);
}
};
meterListener.SetMeasurementEventCallback<int>(OnMeasurementRecorded);
// Start the meterListener, enabling InstrumentPublished callbacks.
meterListener.Start();
var rand = Random.Shared;
Console.WriteLine("Press any key to exit");
while (!Console.KeyAvailable)
{
//// Simulate hat selling transactions.
Thread.Sleep(rand.Next(100, 2500));
s_hatsSold.Add(rand.Next(0, 1000));
}
}
static void OnMeasurementRecorded<T>(
Instrument instrument,
T measurement,
ReadOnlySpan<KeyValuePair<string, object?>> tags,
object? state)
{
Console.WriteLine($"{instrument.Name} recorded measurement {measurement}");
}
}
Následující výstup ukazuje výstup aplikace s vlastním zpětným voláním pro každé měření:
> dotnet run
Press any key to exit
hats-sold recorded measurement 978
hats-sold recorded measurement 775
hats-sold recorded measurement 666
hats-sold recorded measurement 66
hats-sold recorded measurement 914
hats-sold recorded measurement 912
...
Vysvětlení ukázkového kódu
Fragmenty kódu v této části pocházejí z předchozí ukázky.
V následujícím zvýrazněném kódu se vytvoří instance objektu MeterListener pro příjem měření. Klíčové slovo using způsobí, že Dispose bude voláno, když meterListener opustí rámec.
using MeterListener meterListener = new();
meterListener.InstrumentPublished = (instrument, listener) =>
{
if (instrument.Meter.Name is "HatCo.HatStore")
{
listener.EnableMeasurementEvents(instrument);
}
};
Následující zvýrazněný kód nastavuje, ze kterých nástrojů přijímá posluchač měření. InstrumentPublished je delegát, který se vyvolá při vytvoření nového nástroje v aplikaci.
using MeterListener meterListener = new();
meterListener.InstrumentPublished = (instrument, listener) =>
{
if (instrument.Meter.Name is "HatCo.HatStore")
{
listener.EnableMeasurementEvents(instrument);
}
};
Delegát může nástroj prozkoumat a rozhodnout, jestli se má přihlásit k odběru. Delegát může například zkontrolovat jméno, měřič nebo jakoukoli jinou veřejnou vlastnost. EnableMeasurementEvents umožňuje přijímat měření ze zadaného přístroje. Kód, který získá odkaz na nástroj jiným přístupem:
- To se obvykle nedělá.
- Lze kdykoli vyvolat
EnableMeasurementEvents()použitím odkazu.
Delegát, který je vyvolán při přijetí měření z nástroje, je nakonfigurován voláním SetMeasurementEventCallback:
meterListener.SetMeasurementEventCallback<int>(OnMeasurementRecorded);
// Start the meterListener, enabling InstrumentPublished callbacks.
meterListener.Start();
var rand = Random.Shared;
Console.WriteLine("Press any key to exit");
while (!Console.KeyAvailable)
{
//// Simulate hat selling transactions.
Thread.Sleep(rand.Next(100, 2500));
s_hatsSold.Add(rand.Next(0, 1000));
}
}
static void OnMeasurementRecorded<T>(
Instrument instrument,
T measurement,
ReadOnlySpan<KeyValuePair<string, object?>> tags,
object? state)
{
Console.WriteLine($"{instrument.Name} recorded measurement {measurement}");
}
Obecný parametr určuje, jaký datový typ měření přijímá zpětné volání. Například vygeneruje Counter<int>int měření, Counter<double> generuje double měření. Nástroje lze vytvářet pomocí byte, short, int, long, float, double a decimal typů. Doporučujeme zaregistrovat zpětné volání pro každý datový typ, pokud nemáte znalosti specifické pro konkrétní scénář, které nejsou potřeba pro všechny datové typy. Opakované volání SetMeasurementEventCallback s různými obecnými argumenty se může zdát trochu neobvyklé. Toto rozhraní API bylo navržené tak, aby umožňovalo MeterListener přijímat měření s nízkou režií na výkon, obvykle jen pár nanosekund.
Když je MeterListener.EnableMeasurementEvents zavolána, může být state objekt poskytnut jako jeden z parametrů. Objekt state je libovolný. Pokud v daném volání zadáte objekt stavu, uloží se s tímto nástrojem a vrátí se vám jako state parametr v zpětném volání. To je určeno jak jako pohodlí, tak jako optimalizace výkonu. Často posluchači potřebují:
- Vytvořte objekt pro každý nástroj, který ukládá měření do paměti.
- Kód na provádění výpočtů s těmito měřeními.
Případně vytvořte Dictionary mapu propojení z nástroje na objekt úložiště a při každém měření ji vyhledejte. Použití Dictionary je mnohem pomalejší než přístup z state.
meterListener.Start();
Předchozí kód spustí MeterListener , který umožňuje zpětné volání. Delegát InstrumentPublished je vyvolán pro každý předem existující nástroj v procesu. Nově vytvořené objekty nástroje také aktivují: spusťte InstrumentPublished.
using MeterListener meterListener = new MeterListener();
Když aplikace dokončí naslouchání, uvolněním nasloucháče se zastaví tok zpětných volání a uvolní se všechny interní odkazy na objekt nasloucháče. Klíčové using slovo použité při deklarování meterListener způsobí volání Dispose, když proměnná přejde mimo rozsah. Všimněte si, že Dispose pouze slibuje, že nespustí nová zpětná volání. Vzhledem k tomu, že zpětná volání probíhají v různých vláknech, můžou po ukončení volání stále probíhat.
Aby se zajistilo, že se v budoucnu nespustí určitá oblast kódu v zpětném volání, je potřeba přidat synchronizaci vláken.
Dispose nezahrnuje synchronizaci ve výchozím nastavení, protože:
- Synchronizace zvyšuje výkonovou režii při každém zpětném volání měření.
-
MeterListenerje navržen jako vysoce výkonné a efektivní rozhraní API.