2013-09-27 30 views

risposta

1

Utilizzare un evento in più e sparare questo evento nel blocco catch e passare il messaggio di eccezione come parametro per l'evento

[Event(1, Message = "Application Falure: {0}", Level = EventLevel.Error, Keywords = Keywords.Diagnostic)] 
public void Failure(string message) 
{ 
    if (this.IsEnabled()) 
    { 
     this.WriteEvent(1, message); 
    } 
} 

giocare con il livello e la parola chiave per controllare se si desidera registrare tutto il tempo o no.

+0

perché non si può utilizzare con forza digitare eccezioni contro l'EventSource sarei meglio solo chiamare in questo modo: EventSource.Log.Failure (MyException.ToString())? – jaffa

+0

questo sarebbe ok. – magicandre1981

1

ETW non è specifico di .NET, in quanto tale non ci sarà alcuna API specifica di .NET fortemente tipizzata per registrare le eccezioni .net. Dovresti invece creare la tua API fortemente tipizzata. Questa è l'idea alla base del Semantic Logging e del Semantic Logging Application Block.

+0

quindi alla fine della giornata per utilizzare ETW possono essere usati solo tipi di dati primitivi, stringhe e numeri (sotto forma di stringhe)? La serializzazione puramente dell'eccezione in una stringa è sufficiente? O c'è qualche schema per le applicazioni non-.net per tracciare le eccezioni? – BozoJoe

+1

ETW è un carico utile binario e supporta le strutture della tua definizione. http://msdn.microsoft.com/en-us/library/windows/desktop/aa382774(v=vs.85).aspx È solo che quando si va su questa rotta è necessario scrivere un decodificatore personalizzato. Nel caso .NET, esiste una versione ben definita già fornita dal team .NET. Tuttavia, come molte cose nel codice nativo, c'è più di un modo per farlo. Eccezioni C++? SEH eccezioni? ecc. La parte più interessante di un'eccezione è il callstack (e il suo EIP, per ottenere i numeri di riga), che è standardizzato da ETW e il suo stack walker. Qualsiasi informazione oltre questa è la tua chiamata. – mjsabby

17

Tutte le eccezioni CLR (prima possibilità, e quelle che possono finire per abbattere l'applicazione) vengono registrate su ETW dal provider Runtime CLR, se abilitato.

Questo è un evento completamente "strutturato" con i callstacks (se li si desidera). In realtà, è possibile scrivere un'applicazione di monitoraggio utilizzando il pacchetto TraceEvent NuGet (install-pacchetto Microsoft.Diagnostics.Tracing.TraceEvent)

sto incollando il codice di monitoraggio Io uso spesso. Metti questo in un'app console, chiama il metodo Run e genera alcune eccezioni gestite da qualsiasi processo, stamperà le informazioni e i loro callstacks.

NOTA: è necessario il pacchetto NuGet di riferimento, quindi fare riferimento ai suoi assembly e quindi questo codice verrà compilato.

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