Metrikák gyűjtése
Ez a cikk a következőre vonatkozik: ✔️ .NET Core 3.1 és újabb ✔️ .NET-keretrendszer 4.6.1 és újabb verziók
A rendszerezett kód képes numerikus mérések rögzítésére, de a méréseket általában összesíteni, továbbítani és tárolni kell, hogy hasznos metrikákat hozhasson létre a monitorozáshoz. Az adatok összesítésének, továbbításának és tárolásának folyamatát adatgyűjtésnek nevezzük. Ez az oktatóanyag több példát mutat be a metrikák gyűjtésére:
- Metrikák feltöltése Grafana-ban OpenTelemetry és Prometheus használatával.
- Metrikák valós idejű megtekintése
dotnet-counters
- Egyéni gyűjtési eszköz létrehozása a mögöttes .NET MeterListener API használatával.
Az egyéni metrikák rendszerezéséről és beállításairól további információt a metrika API-k összehasonlítása című témakörben talál.
Előfeltételek
- .NET Core 3.1 SDK vagy újabb
Példaalkalmazás létrehozása
A metrikák összegyűjtése előtt méréseket kell létrehozni. Ez az oktatóanyag egy olyan alkalmazást hoz létre, amely alapszintű metrika-kialakítással rendelkezik. A .NET-futtatókörnyezet különböző beépített metrikákkal is rendelkezik. Az új metrikák API-val történő System.Diagnostics.Metrics.Meter létrehozásáról a rendszerállapot-oktatóanyagban talál további információt.
dotnet new console -o metric-instr
cd metric-instr
dotnet add package System.Diagnostics.DiagnosticSource
Cserélje le a következő kód tartalmát Program.cs
:
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));
}
}
}
Az előző kód véletlenszerű időközönként és véletlenszerű időpontokban szimulálja a kalapok értékesítését.
Metrikák megtekintése dotnet-counters használatával
A dotnet-counters egy parancssori eszköz, amely igény szerint megtekintheti a .NET Core-alkalmazások élő metrikáit. Nincs szükség beállításra, így az ad-hoc vizsgálatokhoz vagy annak ellenőrzéséhez, hogy a metrika-rendszerállapot működik-e. Ez az api-k és az EventCounters használatával is System.Diagnostics.Metrics működik.
Ha a dotnet-counters eszköz nincs telepítve, futtassa a következő parancsot:
dotnet tool update -g dotnet-counters
Amíg a példaalkalmazás fut, indítsa el a dotnet-counters parancsokat. Az alábbi parancs egy példát mutat be a dotnet-counters
mérőszám összes metrikájának HatCo.HatStore
figyelésére. A mérő neve megkülönbözteti a kis- és nagybetűk nevét. A mintaalkalmazás a metric-instr.exe volt, ezt helyettesítse a mintaalkalmazás nevével.
dotnet-counters monitor -n metric-instr HatCo.HatStore
A következőhöz hasonló kimenet jelenik meg:
Press p to pause, r to resume, q to quit.
Status: Running
[HatCo.HatStore]
hats-sold (Count / 1 sec) 4
dotnet-counters
a .NET-futtatókörnyezet beépített rendszerállapotának megtekintéséhez különböző metrikákkal futtatható:
dotnet-counters monitor -n metric-instr
A következőhöz hasonló kimenet jelenik meg:
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
% Time in GC since last GC (%) 0
Allocation Rate (B / 1 sec) 8,168
CPU Usage (%) 0
Exception Count (Count / 1 sec) 0
GC Heap Size (MB) 2
Gen 0 GC Count (Count / 1 sec) 0
Gen 0 Size (B) 2,216,256
Gen 1 GC Count (Count / 1 sec) 0
Gen 1 Size (B) 423,392
Gen 2 GC Count (Count / 1 sec) 0
Gen 2 Size (B) 203,248
LOH Size (B) 933,216
Monitor Lock Contention Count (Count / 1 sec) 0
Number of Active Timers 1
Number of Assemblies Loaded 39
ThreadPool Completed Work Item Count (Count / 1 sec) 0
ThreadPool Queue Length 0
ThreadPool Thread Count 3
Working Set (MB) 30
További információ: dotnet-counters. A .NET-beli metrikákkal kapcsolatos további információkért lásd a beépített metrikákat.
Metrikák megtekintése a Grafana-ban OpenTelemetry és Prometheus használatával
Áttekintés
- A Cloud Native Computing Foundation által támogatott, szállítósemleges nyílt forráskódú projekt.
- Szabványosítja a natív felhőbeli szoftverek telemetriájának generálását és gyűjtését.
- A .NET-tel együttműködik a .NET metrika API-kkal.
- Az Azure Monitor és számos APM-gyártó támogatja.
Ez az oktatóanyag az OSS Prometheus - és Grafana-projekteket használó OpenTelemetry-metrikákhoz elérhető integrációk egyikét mutatja be. A metrikák adatfolyama:
A .NET metrika API-k rögzítik a méréseket a példaalkalmazásból.
Az alkalmazásban futó OpenTelemetry-kódtár összesíti a méréseket.
A Prometheus-exportőr kódtára elérhetővé teszi az összesített adatokat EGY HTTP-metrikák végponton keresztül. Az OpenTelemetria az "exportőr" azokat a kódtárakat hívja meg, amelyek telemetriát küldenek a szállítóspecifikus háttérrendszereknek.
Prometheus-kiszolgáló:
- A metrikák végpontjának lekérdezése
- Beolvassa az adatokat
- Az adatokat egy adatbázisban tárolja a hosszú távú megőrzése érdekében. A Prometheus arra utal, hogy az adatok olvasása és tárolása végpontok kaparásaként.
- Futtatható egy másik gépen
A Grafana-kiszolgáló:
- Lekérdezi a Prometheusban tárolt adatokat, és megjeleníti azokat egy webes monitorozási irányítópulton.
- Egy másik gépen is futtatható.
A példaalkalmazás konfigurálása az OpenTelemetry Prometheus-exportőrének használatára
Adjon hozzá egy hivatkozást az OpenTelemetry Prometheus-exportőrre a példaalkalmazáshoz:
dotnet add package OpenTelemetry.Exporter.Prometheus.HttpListener --prerelease
Megjegyzés:
Ez az oktatóanyag az OpenTelemetry Prometheus-támogatásának kiadás előtti buildjét használja, amely az írás időpontjában érhető el.
Frissítés Program.cs
OpenTelemetria-konfigurációval:
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));
}
}
}
A fenti kód a következőket végzi el:
AddMeter("HatCo.HatStore")
Az OpenTelemetry konfigurálja az alkalmazásban meghatározott mérőszám által gyűjtött összes metrikának továbbítására.AddPrometheusHttpListener
Az OpenTelemetria a következőre van konfigurálva:- Prometheus metrikavégpontjának elérhetővé helyezése a porton
9184
- Használja a HttpListenert.
- Prometheus metrikavégpontjának elérhetővé helyezése a porton
Az OpenTelemetry konfigurációs beállításairól további információt az OpenTelemetry dokumentációjában talál. Az OpenTelemetry dokumentációja ASP.NET alkalmazások üzemeltetési lehetőségeit mutatja be.
Futtassa az alkalmazást, és hagyja futni, hogy a mérések összegyűjthetők legyenek:
dotnet run
A Prometheus beállítása és konfigurálása
A Prometheus-kiszolgáló beállításához és működésének ellenőrzéséhez kövesse a Prometheus első lépéseit .
Módosítsa a prometheus.yml konfigurációs fájlt, hogy a Prometheus lekaparja a példaalkalmazás által feltárt metrikák végpontját. Adja hozzá a következő kiemelt szöveget a scrape_configs
szakaszhoz:
# 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']
A Prometheus indítása
Töltse be újra a konfigurációt, vagy indítsa újra a Prometheus-kiszolgálót.
Győződjön meg arról, hogy az OpenTelemetryTest up állapotban van a Prometheus webportál Állapotcélok> lapján.
A Prometheus webportál Gráf lapján írja be
hats
a kifejezés szövegmezőbe, és válasszahats_sold_Hats
a Gráf lapon a Prometheus a példaalkalmazás által kibocsátott "kalapok-eladott" számláló növekvő értékét.
Az előző képen a gráfidő 5 m-re van állítva, ami 5 perc.
Ha a Prometheus-kiszolgáló már régóta nem kaparja le a példaalkalmazást, előfordulhat, hogy várnia kell az adatok halmozódására.
Metrikák megjelenítése Grafana-irányítópulton
A Grafana telepítéséhez és Prometheus-adatforráshoz való csatlakoztatásához kövesse a szokásos utasításokat .
A Grafana-irányítópult létrehozásához kattintson a + bal oldali eszköztár ikonra a Grafana webportálon, majd válassza az Irányítópult lehetőséget. A megjelenő irányítópult-szerkesztőben írja be a Hat eladott/másodperc értéket a Cím beviteli mezőbe és a rate(hats_sold[5m]) kifejezést a PromQL kifejezésmezőbe:
Kattintson az Alkalmaz gombra az új irányítópult mentéséhez és megtekintéséhez.
]
Egyéni gyűjtési eszköz létrehozása a .NET MeterListener API használatával
A .NET MeterListener API lehetővé teszi egyéni folyamaton belüli logika létrehozását a rögzített mérések System.Diagnostics.Metrics.Metermegfigyeléséhez. A régebbi EventCounters-rendszerállapotokkal kompatibilis egyéni logika létrehozásával kapcsolatos útmutatásért tekintse meg az EventCounterst.
Módosítsa a használni MeterListenerkívánt kódjátProgram.cs
:
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}");
}
}
Az alábbi kimenet az alkalmazás kimenetét jeleníti meg egyéni visszahívással az egyes méréseken:
> 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
...
A mintakód ismertetése
Az ebben a szakaszban található kódrészletek az előző mintából származnak.
A következő kiemelt kódban a rendszer létrehoz egy példányt a MeterListener mérések fogadásához. A using
kulcsszó akkor Dispose
lesz meghívva, ha a meterListener
hatókör kiesik.
using MeterListener meterListener = new();
meterListener.InstrumentPublished = (instrument, listener) =>
{
if (instrument.Meter.Name is "HatCo.HatStore")
{
listener.EnableMeasurementEvents(instrument);
}
};
Az alábbi kiemelt kód azt konfigurálja, hogy a figyelő mely eszközöktől fogad méréseket. InstrumentPublished egy olyan meghatalmazott, amelyet akkor hív meg a rendszer, ha új eszköz jön létre az alkalmazásban.
using MeterListener meterListener = new();
meterListener.InstrumentPublished = (instrument, listener) =>
{
if (instrument.Meter.Name is "HatCo.HatStore")
{
listener.EnableMeasurementEvents(instrument);
}
};
A meghatalmazott megvizsgálhatja az eszközt annak eldöntéséhez, hogy feliratkozik-e. A meghatalmazott például ellenőrizheti a nevet, a mérőt vagy bármely más nyilvános tulajdonságot. EnableMeasurementEvents lehetővé teszi a mérések fogadását a megadott műszerről. Olyan kód, amely egy másik megközelítéssel szerez be egy eszközre mutató hivatkozást:
- Ez általában nem történik meg.
- A hivatkozással bármikor meghívható
EnableMeasurementEvents()
.
Az a meghatalmazott, amelyet a rendszer meghív, amikor méréseket fogad egy eszközről, a következő hívással SetMeasurementEventCallbackvan konfigurálva:
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}");
}
Az általános paraméter szabályozza, hogy a visszahívás milyen adattípusú mérést fogad. Például egy Counter<int>
mérést generál int
, Counter<double>
méréseket hoz létre double
. Az eszközök létrehozhatóak , short
, int
, long
, float
, double
és decimal
típusokkalbyte
. Javasoljuk, hogy minden adattípushoz regisztráljon visszahívást, hacsak nem rendelkezik forgatókönyvspecifikus tudással arról, hogy nem minden adattípusra van szükség. A különböző általános argumentumokkal történő ismételt hívások SetMeasurementEventCallback
kissé szokatlannak tűnhetnek. Az API-t úgy tervezték, hogy alacsony teljesítményű, általában csak néhány nanoszekundumos méréseket fogadhasson MeterListener
.
Amikor MeterListener.EnableMeasurementEvents
meghívják, egy state
objektum megadható az egyik paraméterként. Az state
objektum tetszőleges. Ha egy állapotobjektumot ad meg a hívásban, akkor a rendszer az adott eszközzel tárolja, és a visszahívás paramétereként state
adja vissza. Ez mind kényelmi, mind teljesítményoptimalizálási célokat szolgál. A figyelőknek gyakran a következőkre van szükségük:
- Hozzon létre egy objektumot minden olyan eszközhöz, amely méréseket tárol a memóriában.
- A mérésekhez kóddal kell számításokat végeznie.
Másik lehetőségként hozzon létre egy Dictionary
olyan eszközt, amely leképezi a műszert a tárolóobjektumra, és minden mérésen megkeresi. Dictionary
A használata sokkal lassabb, mint a hozzáférés.state
meterListener.Start();
Az előző kód elindítja a MeterListener
visszahívásokat engedélyező kódot. A InstrumentPublished
rendszer meghívja a meghatalmazottat a folyamat minden meglévő eszközére. Az újonnan létrehozott eszközobjektumok is aktiválva InstrumentPublished
lesznek.
using MeterListener meterListener = new MeterListener();
Ha az alkalmazás befejezte a figyeléseket, a figyelő letiltása leállítja a visszahívások folyamatát, és a figyelő objektumra mutató belső hivatkozásokat ad ki. A using
változó hatókörének kiesésekor a deklaráláskor meterListener
Dispose
használt kulcsszó. Vegye figyelembe, hogy Dispose
csak ígéretes, hogy nem kezdeményez új visszahívásokat. Mivel a visszahívások különböző szálakon fordulnak elő, előfordulhat, hogy a visszahívások a visszahívás Dispose
után is folyamatban vannak.
Annak biztosítása érdekében, hogy a visszahívásban lévő kód egy bizonyos régiója jelenleg nem fut, és a jövőben nem fog futni, hozzá kell adni a szálszinkronizálást. Dispose
alapértelmezés szerint nem tartalmazza a szinkronizálást, mert:
- A szinkronizálás minden mérési visszahívásnál többletterhelést okoz.
MeterListener
magas teljesítménytudatos API-ként lett kialakítva.