2013-09-27 31 views

Odpowiedz

1

Użyj dodatkowego zdarzenia i ogień to wydarzenie w bloku catch i przekazać komunikat wyjątku jako parametr do zdarzenia

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

grać z poziomu i słów kluczowych, aby kontrolować, czy chcesz go zalogować wszystkich czas lub nie.

+0

Ponieważ nie można używać silnie typ wyjątków wobec EventSource byłoby najlepiej po prostu nazywając go tak: EventSource.Log.Failure (MyException.ToString())? – jaffa

+0

to byłoby w porządku. – magicandre1981

1

ETW nie jest typem .NET, dlatego nie będzie żadnego silnie wpisanego interfejsu API .NET do logowania się do wyjątków .net. Zamiast tego możesz stworzyć swój własny, mocno napisany interfejs API. Jest to idea Semantic Logging i bloku aplikacji do rejestracji semantycznej.

+0

, więc na koniec dnia, aby korzystać z ETW, można używać tylko pierwotnych typów danych, łańcuchów i liczb (w postaci ciągów znaków)? Czy czysto serializujący wyjątek w łańcuch wystarczająco dobry? Czy istnieje jakiś wzór dla aplikacji poza -.net do śledzenia wyjątków? – BozoJoe

+1

ETW to binarny ładunek danych i obsługuje struktury definicji. http://msdn.microsoft.com/en-us/library/windows/desktop/aa382774(v=vs.85).aspx Chodzi o to, że kiedy jedziesz tą trasą, musisz napisać własny dekoder. W przypadku platformy .NET jest już dobrze zdefiniowana przez zespół .NET. Jednak, podobnie jak wiele innych rzeczy w natywnym kodzie, istnieje więcej niż jeden sposób na zrobienie tego. Wyjątki C++? Wyjątki SEH? itp. Najbardziej interesującą częścią wyjątku jest callstack (i jego EIP, aby uzyskać numery linii), który jest standaryzowany przez ETW i jego walker stosu. Wszelkie informacje poza tym są twoją rozmową. – mjsabby

17

Wszystkie wyjątki CLR (pierwsza szansa i te, które mogą zakończyć się zrywaniem aplikacji) są rejestrowane w ETW przez dostawcę środowiska wykonawczego CLR, gdy są włączone.

To jest zdarzenie "w pełni zorganizowane" Z WYSZUKIWANIEM (jeśli chcesz). W rzeczywistości, można napisać aplikację monitoringu przy użyciu pakietu TraceEvent Nuget (Instaluj-Pakiet Microsoft.Diagnostics.Tracing.TraceEvent)

jestem wklejając kod monitoringu często używam. Umieść to w aplikacji konsoli, wywołaj metodę Run i wyrzuć niektóre zarządzane wyjątki z dowolnego procesu, wydrukuje informacje i ich stacje.

UWAGA: Musisz odwołać się do pakietu NuGet, a następnie odwołać się do jego złożeń, a następnie ten kod zostanie skompilowany.

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