Aracılığıyla paylaş


Tanılama istemci kitaplığı

Bu makale şunlar için geçerlidir: ✔️ Hedef uygulamalar için .NET Core 3.0 SDK ve sonraki sürümleri, kitaplığı kullanmak için .NET Standard 2.0.

Microsoft.Diagnostics.NETCore.Client (Tanılama İstemci Kitaplığı olarak da bilinen), EventPipe aracılığıyla izleme yapma, döküm talep etme veya bir ICorProfiler ekleme gibi tanılamayla ilgili çeşitli görevler için .NET Core çalışma zamanı (CoreCLR) ile etkileşim kurmanızı sağlayan yönetilen bir kitaplıktır. Bu kitaplık dotnet-counters, dotnet-trace, dotnet-gcdump, dotnet-dump ve dotnet-monitor gibi birçok tanılama aracının arkasındaki destekleyici kitaplıktır. Bu kitaplığı kullanarak, kendi senaryonuz için özelleştirilmiş tanılama araçlarınızı yazabilirsiniz.

Projenize bir ekleyerek PackageReference alabilirsiniz. Paket NuGet.org'de barındırılır.

Aşağıdaki bölümlerdeki örneklerde Microsoft.Diagnostics.NETCore.Client kitaplığının nasıl kullanılacağı gösterilmektedir. Bu örneklerden bazıları TraceEvent kitaplığını kullanarak olay yüklerini ayrıştırma işlemini de gösterir.

Bir işleme bağlan ve tüm GC olaylarını yazdır

Bu kod parçacığı, .NET çalışma zamanı sağlayıcısı ile bilgilendirici düzeyde GC anahtarını kullanarak bir EventPipe oturumu başlatmanın nasıl yapıldığını gösterir. Ayrıca gelen olayları ayrıştırmak ve adlarını konsola gerçek zamanlı olarak yazdırmak için EventPipeEventSource tarafından sağlanan sınıfın nasıl kullanılacağını gösterir.

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());
            }
        }
    }
}

Çekirdek dökümünü yazma

Bu örnek, kullanarak bir DiagnosticsClient koleksiyonunun nasıl tetikleneceğini gösterir.

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 kullanımı eşiğin üzerine çıktığında çekirdek dökümü tetikleme

Bu örnek, .NET çalışma zamanı tarafından yayımlanan cpu-usage sayacını izlemeyi ve CPU kullanımı belirli bir eşiğin ötesine geçtiğinde bir döküm talep etmeyi nasıl gerçekleştireceğinizi gösterir.

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) {}
        }
    }
}

Belirtilen süre boyunca CPU takibini başlatma

Bu örnek, varsayılan CLR izleme anahtar sözcüğü ve örnek profil oluşturucu ile belirli bir süre için EventPipe oturumunu tetikleme işlemini gösterir. Daha sonra çıkış akışını okur ve baytları bir dosyaya yazar. Temelde bir izleme dosyası yazmak için dahili olarak kullanılan dotnet-trace budur.

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();
        }
    }
}

Bu örnek, tanılama IPC kanalını yayımlayan .NET işlemlerinin adlarını yazdırmak için API'nin nasıl kullanılacağını DiagnosticsClient.GetPublishedProcesses gösterir.

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}");
        }
    }
}

Olayları gerçek zamanlı olarak ayrıştırma

Bu örnek, iki görev oluşturduğumuz bir durumu gösterir: biri EventPipeEventSource ile canlı olarak gelen olayları ayrıştıran ve diğeri programın bitmesi için sinyal veren bir kullanıcı girdisini konsol girişinden okuyan. Kullanıcı Enter tuşuna basmadan önce hedef uygulamadan çıkarsa, uygulama düzgün bir şekilde çıkar. Aksi takdirde, inputTask Durdur komutunu boruya gönderir ve sorunsuz bir şekilde çıkar.

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 profilini ekle

Bu örnek, bir işleme profiler attach yoluyla ICorProfiler eklemeyi gösterir.

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);
    }
}