Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten artykuł dotyczy: ✔️ pakietu .NET Core 3.0 SDK i nowszych wersji dla aplikacji docelowych, .NET Standard 2.0 do użycia biblioteki.
Microsoft.Diagnostics.NETCore.Client (znana również jako biblioteka klienta diagnostyki) to zarządzana biblioteka, która umożliwia interakcję ze środowiskiem wykonawczym .NET Core (CoreCLR) na potrzeby różnych zadań związanych z diagnostyką, takich jak śledzenie poprzez EventPipe, żądanie zrzutu lub dołączanie ICorProfiler. Ta biblioteka jest biblioteką zapasową wielu narzędzi diagnostycznych, takich jak dotnet-counters, dotnet-trace, dotnet-gcdump, dotnet-dump i dotnet-monitor. Korzystając z tej biblioteki, możesz napisać własne narzędzia diagnostyczne dostosowane do konkretnego scenariusza.
Możesz uzyskać Microsoft.Diagnostics.NETCore.Client, dodając komponent PackageReference do projektu. Pakiet jest hostowany w systemie NuGet.org.
Przykłady w poniższych sekcjach pokazują, jak używać biblioteki Microsoft.Diagnostics.NETCore.Client. Niektóre z tych przykładów pokazują również analizowanie ładunków zdarzeń przy użyciu biblioteki TraceEvent .
Dołącz do procesu i wydrukuj wszystkie zdarzenia GC
Ten fragment kodu pokazuje, jak uruchomić sesję EventPipe przy użyciu dostawcy środowiska uruchomieniowego platformy .NET ze słowem kluczowym GC na poziomie informacyjnym. Pokazano również, jak używać klasy dostarczonej EventPipeEventSource przez bibliotekę TraceEvent do analizowania zdarzeń przychodzących i drukowania ich nazw w konsoli w czasie rzeczywistym.
using Microsoft.Diagnostics.NETCore.Client;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.EventPipe;
using Microsoft.Diagnostics.Tracing.Parsers;
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
public class RuntimeGCEventsPrinter
{
public static void PrintRuntimeGCEvents(int processId)
{
var providers = new List<EventPipeProvider>()
{
new EventPipeProvider("Microsoft-Windows-DotNETRuntime",
EventLevel.Informational, (long)ClrTraceEventParser.Keywords.GC)
};
var client = new DiagnosticsClient(processId);
using (EventPipeSession session = client.StartEventPipeSession(providers, false))
{
var source = new EventPipeEventSource(session.EventStream);
source.Clr.All += (TraceEvent obj) => Console.WriteLine(obj.ToString());
try
{
source.Process();
}
catch (Exception e)
{
Console.WriteLine("Error encountered while processing events");
Console.WriteLine(e.ToString());
}
}
}
}
Tworzenie zrzutu pamięci
W tym przykładzie pokazano, jak uruchomić zrzut rdzenia przy użyciu .
using Microsoft.Diagnostics.NETCore.Client;
public partial class Dumper
{
public static void TriggerCoreDump(int processId)
{
var client = new DiagnosticsClient(processId);
client.WriteDump(DumpType.Normal, "/tmp/minidump.dmp");
}
}
Wyzwalaj zrzut rdzenia, gdy użycie procesora przekracza próg
W tym przykładzie pokazano, jak monitorować licznik cpu-usage opublikowany przez środowisko uruchomieniowe platformy .NET i żądać zrzutu, gdy użycie procesora przekroczy określony próg.
using Microsoft.Diagnostics.NETCore.Client;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.EventPipe;
using Microsoft.Diagnostics.Tracing.Parsers;
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
public partial class Dumper
{
public static void TriggerDumpOnCpuUsage(int processId, int threshold)
{
var providers = new List<EventPipeProvider>()
{
new EventPipeProvider(
"System.Runtime",
EventLevel.Informational,
(long)ClrTraceEventParser.Keywords.None,
new Dictionary<string, string>
{
["EventCounterIntervalSec"] = "1"
}
)
};
var client = new DiagnosticsClient(processId);
using (var session = client.StartEventPipeSession(providers))
{
var source = new EventPipeEventSource(session.EventStream);
source.Dynamic.All += (TraceEvent obj) =>
{
if (obj.EventName.Equals("EventCounters"))
{
var payloadVal = (IDictionary<string, object>)(obj.PayloadValue(0));
var payloadFields = (IDictionary<string, object>)(payloadVal["Payload"]);
if (payloadFields["Name"].ToString().Equals("cpu-usage"))
{
double cpuUsage = Double.Parse(payloadFields["Mean"].ToString());
if (cpuUsage > (double)threshold)
{
client.WriteDump(DumpType.Normal, "/tmp/minidump.dmp");
}
}
}
};
try
{
source.Process();
}
catch (Exception) {}
}
}
}
Uruchom śledzenie procesora CPU przez określoną liczbę sekund
W tym przykładzie pokazano, jak wyzwolić sesję EventPipe na określony czas z domyślnym słowem kluczowym śledzenia CLR, a także za pomocą przykładowego profilera. Następnie odczytuje strumień wyjściowy i zapisuje bajty w pliku. Zasadniczo jest to to, co dotnet-trace używa wewnętrznie do zapisu pliku śledzenia.
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.NETCore.Client;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.IO;
using System.Threading.Tasks;
public partial class Tracer
{
public void TraceProcessForDuration(int processId, int duration, string traceName)
{
var cpuProviders = new List<EventPipeProvider>()
{
new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, (long)ClrTraceEventParser.Keywords.Default),
new EventPipeProvider("Microsoft-DotNETCore-SampleProfiler", EventLevel.Informational, (long)ClrTraceEventParser.Keywords.None)
};
var client = new DiagnosticsClient(processId);
using (var traceSession = client.StartEventPipeSession(cpuProviders))
{
Task copyTask = Task.Run(async () =>
{
using (FileStream fs = new FileStream(traceName, FileMode.Create, FileAccess.Write))
{
await traceSession.EventStream.CopyToAsync(fs);
}
});
Task.WhenAny(copyTask, Task.Delay(TimeSpan.FromMilliseconds(duration * 1000)));
traceSession.Stop();
}
}
}
Wyświetl nazwy procesów, które opublikowały kanał diagnostyczny
W tym przykładzie pokazano, jak używać DiagnosticsClient.GetPublishedProcesses API do wyświetlania nazw procesów platformy .NET, które opublikowały kanał IPC dla diagnostyki.
using Microsoft.Diagnostics.NETCore.Client;
using System;
using System.Diagnostics;
using System.Linq;
public class ProcessTracker
{
public static void PrintProcessStatus()
{
var processes = DiagnosticsClient.GetPublishedProcesses()
.Select(Process.GetProcessById)
.Where(process => process != null);
foreach (var process in processes)
{
Console.WriteLine($"{process.ProcessName}");
}
}
}
Analizowanie zdarzeń w czasie rzeczywistym
W tym przykładzie tworzymy dwa zadania: jedno analizuje zdarzenia nadchodzące na żywo z EventPipeEventSource, a drugie odczytuje dane wejściowe z konsoli, sygnalizując użytkownikowi zakończenie programu. Jeśli aplikacja docelowa zakończy działanie przed naciśnięciem Enter przez użytkownika, aplikacja zostanie bezpiecznie zakończona. W przeciwnym razie inputTask wyśle polecenie Stop do potoku i zakończy działanie bezpiecznie.
using Microsoft.Diagnostics.NETCore.Client;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.EventPipe;
using Microsoft.Diagnostics.Tracing.Parsers;
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Threading.Tasks;
public partial class Tracer
{
public static void PrintEventsLive(int processId)
{
var providers = new List<EventPipeProvider>()
{
new EventPipeProvider("Microsoft-Windows-DotNETRuntime",
EventLevel.Informational, (long)ClrTraceEventParser.Keywords.Default)
};
var client = new DiagnosticsClient(processId);
using (var session = client.StartEventPipeSession(providers, false))
{
Task streamTask = Task.Run(() =>
{
var source = new EventPipeEventSource(session.EventStream);
source.Clr.All += (TraceEvent obj) => Console.WriteLine(obj.EventName);
try
{
source.Process();
}
// NOTE: This exception does not currently exist. It is something that needs to be added to TraceEvent.
catch (Exception e)
{
Console.WriteLine("Error encountered while processing events");
Console.WriteLine(e.ToString());
}
});
Task inputTask = Task.Run(() =>
{
Console.WriteLine("Press Enter to exit");
while (Console.ReadKey().Key != ConsoleKey.Enter)
{
Task.Delay(TimeSpan.FromMilliseconds(100));
}
session.Stop();
});
Task.WaitAny(streamTask, inputTask);
}
}
}
Dołącz profilera ICorProfiler
W tym przykładzie pokazano, jak dołączyć element ICorProfiler do procesu za pośrednictwem dołączania profilera.
using System;
using Microsoft.Diagnostics.NETCore.Client;
public class Profiler
{
public static void AttachProfiler(int processId, Guid profilerGuid, string profilerPath)
{
var client = new DiagnosticsClient(processId);
client.AttachProfiler(TimeSpan.FromSeconds(10), profilerGuid, profilerPath);
}
}