gpt4 book ai didi

.net - 使用 ETW 记录异常的最佳方法是什么?

转载 作者:行者123 更新时间:2023-12-03 23:23:16 26 4
gpt4 key购买 nike

是否有使用 ETW 记录异常的标准方法?

据我所知,这样做的唯一方法是记录消息和可能的内部异常消息,因为异常类型没有强类型参数。

最佳答案

启用时,所有 CLR 异常(第一次机会,以及可能最终导致应用程序崩溃的异常)都由 CLR 运行时提供程序记录到 ETW。

这是一个带有调用堆栈的完全“结构化”事件(如果你想要的话)。实际上,您可以使用 TraceEvent NuGet 包(Install-Package Microsoft.Diagnostics.Tracing.TraceEvent )编写监控应用程序

我正在粘贴我经常使用的监控代码。将它放在控制台应用程序中,调用 Run 方法,并从任何进程中抛出一些托管异常,它将打印信息及其调用堆栈。

注意:您需要引用的 NuGet 包,然后引用其程序集,然后将编译此代码。

class TraceLogMonitor
{
static TextWriter Out = AllSamples.Out;

public static void Run()
{
var monitoringTimeSec = 10;
TraceEventSession session = null;

Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) =>
{
if (session != null)
session.Dispose();
cancelArgs.Cancel = true;
};

var exceptionGeneationTask = Task.Factory.StartNew(delegate
{
Thread.Sleep(3000);
ThrowException();
});

Timer timer = null;

using (session = new TraceEventSession("TraceLogSession"))
{
Out.WriteLine("Enabling Image load, Process and Thread events. These are needed to look up native method names.");
session.EnableKernelProvider(

KernelTraceEventParser.Keywords.ImageLoad |
KernelTraceEventParser.Keywords.Process,
KernelTraceEventParser.Keywords.None
);

Out.WriteLine("Enabling CLR Exception and Load events (and stack for those events)");

session.EnableProvider(
ClrTraceEventParser.ProviderGuid,
TraceEventLevel.Informational,
(ulong)(ClrTraceEventParser.Keywords.Jit |
ClrTraceEventParser.Keywords.JittedMethodILToNativeMap |
ClrTraceEventParser.Keywords.Loader |
ClrTraceEventParser.Keywords.Exception |
ClrTraceEventParser.Keywords.Stack));

Out.WriteLine("Enabling CLR Events to 'catch up' on JIT compiled code in running processes.");
session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Informational,
(ulong)(ClrTraceEventParser.Keywords.Jit |
ClrTraceEventParser.Keywords.JittedMethodILToNativeMap |
ClrTraceEventParser.Keywords.Loader |
ClrTraceEventParser.Keywords.StartEnumeration));

TextWriter SymbolLookupMessages = new StringWriter();

var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath);
SymbolReader symbolReader = new SymbolReader(SymbolLookupMessages, symbolPath.ToString());

Out.WriteLine("Open a real time TraceLog session (which understands how to decode stacks).");
using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session))
{
Action<TraceEvent> PrintEvent = ((TraceEvent data) => Print(data, symbolReader));

traceLogSource.Clr.ExceptionStart += PrintEvent;
traceLogSource.Clr.LoaderModuleLoad += PrintEvent;

traceLogSource.Kernel.PerfInfoSample += ((SampledProfileTraceData data) => Print(data, symbolReader));

Out.WriteLine("Waiting {0} sec for Events. Run managed code to see data. ", monitoringTimeSec);
Out.WriteLine("Keep in mind there is a several second buffering delay");

timer = new Timer(delegate(object state)
{
Out.WriteLine("Stopped Monitoring after {0} sec", monitoringTimeSec);
if (session != null)
session.Dispose();
session = null;
}, null, monitoringTimeSec * 1000, Timeout.Infinite);

traceLogSource.Process();
}
}
Out.WriteLine("Finished");
if (timer != null)
timer.Dispose();
}

static void Print(TraceEvent data, SymbolReader symbolReader)
{
if (data.Opcode == TraceEventOpcode.DataCollectionStart)
return;

if (data is ExceptionTraceData && ((ExceptionTraceData) data).ExceptionType.Length == 0)
return;

Out.WriteLine("EVENT: {0}", data.ToString());
var callStack = data.CallStack();
if (callStack != null)
{
ResolveNativeCode(callStack, symbolReader);
Out.WriteLine("CALLSTACK: {0}", callStack.ToString());
}
}

static private void ResolveNativeCode(TraceCallStack callStack, SymbolReader symbolReader)
{
while (callStack != null)
{
var codeAddress = callStack.CodeAddress;
if (codeAddress.Method == null)
{
var moduleFile = codeAddress.ModuleFile;
if (moduleFile == null)
Trace.WriteLine(string.Format("Could not find module for Address 0x{0:x}", codeAddress.Address));
else
codeAddress.CodeAddresses.LookupSymbolsForModule(symbolReader, moduleFile);
}
callStack = callStack.Caller;
}
}

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private static void ThrowException()
{
ThrowException1();
}

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private static void ThrowException1()
{
Out.WriteLine("Causing an exception to happen so a CLR Exception Start event will be generated.");
try
{
throw new Exception("This is a test exception thrown to generate a CLR event");
}
catch (Exception) { }
}
}

关于.net - 使用 ETW 记录异常的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19053307/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com