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 istemci kitaplığı olarak da bilinir), EventPipe aracılığıyla izleme, döküm isteme veya 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 ICorProfilerkitaplı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 yedekleme kitaplığıdır. Bu kitaplığı kullanarak, kendi senaryonuz için özelleştirilmiş tanılama araçlarınızı yazabilirsiniz.

Projenize bir PackageReference ekleyerek Microsoft.Diagnostics.NETCore.Client alabilirsiniz. Paket üzerinde NuGet.orgbarı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 ekleme ve tüm GC olaylarını yazdırma

Bu kod parçacığı, bilgi düzeyinde GC anahtar sözcüğü ile .NET çalışma zamanı sağlayıcısını kullanarak EventPipe oturumu başlatmayı gösterir. Ayrıca gelen olayları ayrıştırmak ve adlarını konsola gerçek zamanlı olarak yazdırmak için TraceEvent kitaplığı tarafından sağlanan sınıfın nasıl kullanılacağını EventPipeEventSource 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ü yazma

Bu örnek, kullanarak DiagnosticsClientçekirdek dökümü koleksiyonunun nasıl tetiklendiğinde gösterilir.

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 sayacın nasıl izleneceğini cpu-usage ve CPU kullanımı belirli bir eşiğin ötesine geçtiğinde döküm isteğinde bulunmayı 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) {}
        }
    }
}

Belirli bir saniye sayısı için CPU izlemesi tetikleme

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, biri ile EventPipeEventSource canlı olarak gelen olayları ayrıştıran iki görev, diğeri de programın bitmesi için sinyal veren bir kullanıcı girişi için konsol girişini okuyan iki görev oluşturduğumuz bir örneği gösterir. Kullanıcı Enter tuşuna basmadan önce hedef uygulamadan çıkarsa, uygulama düzgün bir şekilde çıkar. Aksi takdirde, inputTask Durdur komutunu kanala gönderir ve düzgün 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 profil oluşturucu ekleme

Bu örnek, profil oluşturucu ekleme yoluyla bir işleme 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);
    }
}