public static void Run()

in Microsoft.Diagnostics.Tracing/TraceEvent/TraceEvent/41_TraceLogMonitor.cs [26:162]


        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 and 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.  
        }