Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Эта статья относится к пакету ✔️ SDK для .NET Core 3.0 и более поздних версий для целевых приложений . NET Standard 2.0 для использования библиотеки.
Microsoft.Diagnostics.NETCore.Client(также известная как клиентская библиотека диагностики) — это управляемая библиотека, которая позволяет взаимодействовать со средой исполнения .NET Core (CoreCLR) для различных задач диагностики, таких как трассировка через EventPipe, запрос дампа или подключение ICorProfiler. Эта библиотека является основной библиотекой для множества средств диагностики, таких как dotnet-counters, dotnet-trace, dotnet-gcdump, dotnet-dump и dotnet-monitor. С помощью этой библиотеки можно написать собственные средства диагностики, настроенные для конкретного сценария.
Вы можете получить Microsoft.Diagnostics.NETCore.Client, добавив PackageReference в проект. Пакет размещается в NuGet.org.
В примерах в следующих разделах показано, как использовать библиотеку Microsoft.Diagnostics.NETCore.Client. Некоторые из этих примеров также показывают анализ полезных данных событий с помощью библиотеки TraceEvent .
Присоединение к процессу и печать всех событий GC
В этом фрагменте показано, как запустить сеанс EventPipe с помощью поставщика среды выполнения .NET с ключевым словом GC на информационном уровне. В нем также показано, как использовать EventPipeEventSource класс, предоставляемый библиотекой TraceEvent , для анализа входящих событий и печати их имен в консоли в режиме реального времени.
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());
}
}
}
}
Создать дамп памяти
В этом примере показано, как инициировать сбор дампа памяти с помощью DiagnosticsClient.
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");
}
}
Активация дампа ядра при превышении порогового значения использования ЦП
В этом примере показано, как отслеживать cpu-usage счетчик, опубликованный средой выполнения .NET, и запрашивать дамп, когда использование ЦП превышает определенное пороговое значение.
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) {}
}
}
}
Активация трассировки ЦП для заданного количества секунд
В этом примере показано, как активировать сеанс EventPipe в течение определенного периода времени с ключевым словом трассировки CLR по умолчанию, а также примером профилировщика. Затем он считывает выходной поток и записывает байты в файл. По сути, это то, что dotnet-trace использует для создания файла трассировки.
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();
}
}
}
Печать имен процессов, опубликованных каналом диагностики
В этом примере показано, как использовать DiagnosticsClient.GetPublishedProcesses API для вывода имен процессов .NET, опубликованных диагностическим каналом IPC.
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}");
}
}
}
Анализ событий в режиме реального времени
В этом примере показано создание двух задач: одна анализирует события, поступающие в реальном времени, с EventPipeEventSource, а другая считывает ввод с консоли, предоставленный пользователем, сигнализируя программе о завершении. Если целевое приложение завершает работу, прежде чем пользователь нажимает ввод, приложение завершается благополучно. В противном случае inputTask отправит команду Stop в канал и завершит работу без ошибок.
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);
}
}
}
Присоединение профилировщика ICorProfiler
В этом примере показано, как подключить ICorProfiler к процессу через функцию присоединения профилировщика.
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);
}
}