void ProcessData() { try { using (myRealtimeSession = new TraceEventSession("WMIWatcher_Realtime")) { myRealtimeSession.EnableKernelProvider(KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process, KernelTraceEventParser.Keywords.None); myRealtimeSession.EnableProvider(WMIProviderDefinitions.WMI_Activity_Provider_Name, TraceEventLevel.Verbose, WMIProviderDefinitions.Keyword_WMI_Activity_Trace); using (myTraceLogSource = TraceLog.CreateFromTraceEventSession(myRealtimeSession)) { WMIEventParser parser = new WMIEventParser(myTraceLogSource, "WmiWatcher", AutoLoggerFileName); myTraceLogSource.Dynamic.All += parser.Parse; parser.OnWMIOperationStart += Parser_OnWMIOperationStart; //parser.OnWMIOperationStop += Parser_OnWMIOperationStop; parser.OnWMIExecAsync += Parser_OnWMIExecAsync; parser.OnProcessEndedWithDuration += Parser_OnProcessEndedWithDuration; myTraceLogSource.Process(); } } } catch (Exception ex) { FileLogger.Logger.Log($"Error: Got Exception while leaving ProcessData: {ex}"); throw; } }
public async Task StartAsync() { if (Interlocked.CompareExchange(ref _started, 1, 0) == 1) { throw new InvalidOperationException("Impossible to start profiling more than once."); } await Task.Factory.StartNew(() => { using (_session) { SetupProviders(_session); using (TraceLogEventSource source = TraceLog.CreateFromTraceEventSession(_session)) { SetupListeners(source); source.Process(); } } // dump the symbol related error messages if required if (_verbose) { Console.WriteLine(_symbolLookupMessages.ToString()); } }); }
protected override void Capture(TraceEventSession session) { session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP, KernelTraceEventParser.Keywords.NetworkTCPIP); //TraceLogEventSource is required on win 7 //see: https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Tracing/TraceEvent/TraceEvent/41_TraceLogMonitor.cs using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session)) { //two events in a row for same process and IP/port means failure. //It could be a firewall intervention, silently droping packets to that destination //or the end service is down. traceLogSource.Kernel.TcpIpReconnect += (TcpIpTraceData data) => { try { _sender.Send(data.ProcessID, data.daddr + ":" + data.dport, TCP_RECONNECT); } catch (Exception) { //TODO: log it //TODO: check all Exceptions that can be thrown by the _sender instance. throw; } }; traceLogSource.Kernel.TcpIpConnect += (TcpIpConnectTraceData data) => { try { _sender.Send(data.ProcessID, data.ToXml(new System.Text.StringBuilder()).ToString(), TCP_CONNECT); } catch (Exception) { //TODO: log it //TODO: check all Exceptions that can be thrown by the _sender instance. throw; } }; traceLogSource.Kernel.TcpIpDisconnect += (TcpIpTraceData data) => { try { _sender.Send(data.ProcessID, data.ToXml(new System.Text.StringBuilder()).ToString(), TCP_CONNECT); } catch (Exception) { //TODO: log it //TODO: check all Exceptions that can be thrown by the _sender instance. throw; } }; traceLogSource.Process(); } }
static void Main(string[] args) { using (var session = new TraceEventSession("MonitorKernelAndClrEventsSession")) { Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) => { session.Dispose(); cancelArgs.Cancel = true; }; //session.EnableKernelProvider(KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread); var optionsWithStacks = new TraceEventProviderOptions() { StacksEnabled = true }; //session.EnableProvider(ClrTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)ClrTraceEventParser.Keywords.Default); //session.EnableProvider(ClrTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)ClrTraceEventParser.Keywords.Exception, optionsWithStacks); //session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)ClrRundownTraceEventParser.Keywords.Default); session.EnableProvider("Microsoft-Windows-TCPIP", TraceEventLevel.Verbose); #if TRACELOG using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session)) { traceLogSource.Clr.ExceptionStart += ClrOnExceptionStart; traceLogSource.Process(); } #else session.Source.Clr.GCStart += ClrOnGcStart; session.Source.Clr.GCStop += ClrOnGcStop; session.Source.Clr.GCHeapStats += ClrOnGcHeapStats; session.Source.Dynamic.All += delegate(Microsoft.Diagnostics.Tracing.TraceEvent data) { // ETW buffers events and only delivers them after buffering up for some amount of time. Thus // there is a small delay of about 2-4 seconds between the timestamp on the event (which is very // accurate), and the time we actually get the event. We measure that delay here. var delay = (DateTime.Now - data.TimeStamp).TotalSeconds; //Console.WriteLine("GOT Event Delay={0:f1}sec: {1}/{2} ", delay, data.ProviderName, data.EventName); }; session.Source.Dynamic.AddCallbackForProviderEvent("Microsoft-Windows-TCPIP", "TcpSendTransmitted", data => Console.WriteLine($"PID {data.ProcessID} sent {data.PayloadByName("NumBytes")} B")); //session.Source.Kernel.ProcessStart += KernelOnProcessStart; //session.Source.Kernel.ProcessStop += KernelOnProcessStop; session.Source.Process(); #endif } }
protected override bool OnStart() { if (_session != null) { throw new InvalidOperationException("Profiling session already started..."); } string sessionName = "LiveCpu_Profiling_Session+" + Guid.NewGuid().ToString(); _session = new TraceEventSession(sessionName, TraceEventSessionOptions.Create); if (!EnableProviders(_session)) { _session.Dispose(); _session = null; return(false); } _profilingTask = Task.Factory.StartNew(() => { using (TraceLogEventSource source = TraceLog.CreateFromTraceEventSession(_session)) { // CPU sampling kernel events source.Kernel.PerfInfoSample += (SampledProfileTraceData data) => { if (data.ProcessID != Pid) { return; } var callstack = data.CallStack(); if (callstack == null) { return; } MergeCallStack(callstack, Reader); }; // this call exits when the session is stopped source.Process(); } }); return(true); }
public async Task StartAsync() { if (Interlocked.CompareExchange(ref _started, 1, 0) == 1) { throw new InvalidOperationException("Impossible to start profiling more than once."); } await Task.Factory.StartNew(() => { using (_session) { SetupProviders(_session); using (TraceLogEventSource source = TraceLog.CreateFromTraceEventSession(_session)) { SetupListeners(source); source.Process(); } } }); }
public static void Run() { var monitoringTimeSec = 10; Out.WriteLine("******************** RealTimeTraceLog DEMO (win8) ********************"); Out.WriteLine("This program Shows how to use the real-time support in TraceLog"); Out.WriteLine("We do this by showing how to monitor exceptions in real time "); Out.WriteLine(); Out.WriteLine("This code depends on a Feature of Windows 8.1 (combined user and kernel sessions)"); Out.WriteLine(); Out.WriteLine("Note that this support is currently experimental and subject to change"); Out.WriteLine(); Out.WriteLine("Monitoring .NET Module load and Exception events (with stacks)."); Out.WriteLine("Run some managed code (ideally that has exceptions) while the monitor is running."); Out.WriteLine(); if (Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor < 62) { Out.WriteLine("This demo only works on Win8 / Win 2012 an above)"); return; } TraceEventSession session = null; // Set up Ctrl-C to stop both user mode and kernel mode sessions Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) => { if (session != null) { session.Dispose(); } cancelArgs.Cancel = true; }; // Cause an exception to be thrown a few seconds in (so we have something interesting to look at) var exceptionGeneationTask = Task.Factory.StartNew(delegate { Thread.Sleep(3000); ThrowException(); }); Timer timer = null; // Create the new session to receive the events. // Because we are on Win 8 this single session can handle both kernel and non-kernel providers. using (session = new TraceEventSession("TraceLogSession")) { // Enable the events we care about for the kernel // For this instant the session will buffer any incoming events. // Enabling kernel events must be done before anything else. // This will fail on Win7. // // Note that if you turn on the KernelTraceEventParser.Keywords.Profile, you can also get stacks for CPU sampling // (every millisecond). (You can use the traceLogSource.Kernel.PerfInfoSample callback). Out.WriteLine("Enabling Image load, Process and Thread events. These are needed to look up native method names."); session.EnableKernelProvider( // KernelTraceEventParser.Keywords.Profile | // If you want CPU sampling events // KernelTraceEventParser.Keywords.ContextSwitch | // If you want context switch events // KernelTraceEventParser.Keywords.Thread | // If you want context switch events you also need thread start events. KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process, /****** The second parameter indicates which kernel events should have stacks *****/ // KernelTraceEventParser.Keywords.ImageLoad | // If you want Stacks image load (load library) events // KernelTraceEventParser.Keywords.Profile | // If you want Stacks for CPU sampling events // KernelTraceEventParser.Keywords.ContextSwitch | // If you want Stacks for context switch events KernelTraceEventParser.Keywords.None ); Out.WriteLine("Enabling CLR Exception and Load events (and stack for those events)"); // We are monitoring exception events (with stacks) and module load events (with stacks) session.EnableProvider( ClrTraceEventParser.ProviderGuid, TraceEventLevel.Informational, (ulong)(ClrTraceEventParser.Keywords.Jit | // Turning on JIT events is necessary to resolve JIT compiled code ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks ClrTraceEventParser.Keywords.Loader | // You must include loader events as well to resolve JIT compiled code. ClrTraceEventParser.Keywords.Exception | // We want to see the exception events. ClrTraceEventParser.Keywords.Stack)); // And stacks on all CLR events where it makes sense. // The CLR events turned on above will let you resolve JIT compiled code as long as the JIT compilation // happens AFTER the session has started. To handle the case for JIT compiled code that was already // compiled we need to tell the CLR to dump 'Rundown' events for all existing JIT compiled code. We // do that here. 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 | // We need JIT events to be rundown to resolve method names ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks ClrTraceEventParser.Keywords.Loader | // As well as the module load events. ClrTraceEventParser.Keywords.StartEnumeration)); // This indicates to do the rundown now (at enable time) // Because we care about symbols in native code or NGEN images, we need a SymbolReader to decode them. // There is a lot of messages associated with looking up symbols, but we don't want to clutter up // The output by default, so we save it to an internal buffer you can ToString in debug code. // A real app should make this available somehow to the user, because sooner or later you DO need it. TextWriter SymbolLookupMessages = new StringWriter(); // TextWriter SymbolLookupMessages = Out; // If you want the symbol debug spew to go to the output, use this. // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable. However you can override // if you wish by passing it to the SymbolReader constructor. Since we want this to work even if you // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/ 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)) { // We use this action in the particular callbacks below. Basically we pass in a symbol reader so we can decode the stack. // Often the symbol reader is a global variable instead. Action <TraceEvent> PrintEvent = ((TraceEvent data) => Print(data, symbolReader)); // We will print Exceptions and ModuleLoad events. (with stacks). traceLogSource.Clr.ExceptionStart += PrintEvent; traceLogSource.Clr.LoaderModuleLoad += PrintEvent; // traceLogSource.Clr.All += PrintEvent; // If you want to see stacks for various other kernel events, uncomment these (you also need to turn on the events above) traceLogSource.Kernel.PerfInfoSample += ((SampledProfileTraceData data) => Print(data, symbolReader)); // traceLogSource.Kernel.ImageLoad += ((ImageLoadTraceData data) => Print(data, symbolReader)); // process events until Ctrl-C is pressed or timeout expires 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"); // Set up a timer to stop processing after monitoringTimeSec 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(); // Turn off the timer. } }