public static void Run()

in Microsoft.Diagnostics.Tracing/TraceEvent/TraceEvent/51_SimpleMonitorRelogger.cs [32:151]


        public static void Run()
        {
            int monitoringTimeSec = 10;

            if (Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor < 62)
            {
                Out.WriteLine("This demo only works on Win8 / Win 2012 an above)");
                return;
            }

            // Today you have to be Admin to turn on ETW events (anyone can write ETW events).   
            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Out.WriteLine("To turn on ETW events you need to be Administrator, please run from an Admin process.");
                Debugger.Break();
                return;
            }

            string outputFileName = "ReloggerMonitorOutput.etl";
            if (File.Exists(outputFileName))
                File.Delete(outputFileName);

            Out.WriteLine("******************** Simple Relogger DEMO ********************");
            Out.WriteLine("This program shows how you can monitor an ETW stream in real time.");
            Out.WriteLine("And conditionally pass the events on to a ETL file");
            Out.WriteLine("Ctrl-C will end earlier");
            Out.WriteLine();
            Out.WriteLine("Please run some managed code while collection is happening...");
            Out.WriteLine();

            // To listen to ETW events you need a session, which allows you to control which events will be produced
            // Note that it is the session and not the source that buffers events, and by default sessions will buffer
            // 64MB of events before dropping events.  Thus even if you don't immediately connect up the source and
            // read the events you should not lose them. 
            //
            // As mentioned below, sessions can outlive the process that created them.  Thus you may need a way of 
            // naming the session so that you can 'reconnect' to it from another process.   This is what the name
            // is for.  It can be anything, but it should be descriptive and unique.   If you expect multiple versions
            // of your program to run simultaneously, you need to generate unique names (e.g. add a process ID suffix) 
            // however this is dangerous because you can leave data collection on if the program ends unexpectedly.  
            var sessionName = "SimpleMonitorSession";
            Out.WriteLine("Creating a '{0}' session", sessionName);
            using (var session = new TraceEventSession(sessionName))
            {
                // Enable the events we care about for the kernel in the kernel session
                // For this instant the session will buffer any incoming events.  
                // This has to be first, and it will fail if you are not on Win8.  
                session.EnableKernelProvider(
                    KernelTraceEventParser.Keywords.ImageLoad |
                    KernelTraceEventParser.Keywords.Process |
                    KernelTraceEventParser.Keywords.Thread);

                // A relogger is a TraceEventSource and acts much like an ETWTraceEventSource, with extra Write APIS. 
                // Thus you get a callback on any event you want.   
                // Only things that you call 'WriteEvent' on will end up in the output file.  
                var relogger = new ETWReloggerTraceEventSource(sessionName, TraceEventSourceType.Session, outputFileName);

                // Here we set up the callbacks we want in the output file.   In this case all GC allocation Tick
                // events for 'String' as well as any ExceptionStart events.  
                relogger.Clr.GCAllocationTick += delegate(GCAllocationTickTraceData data)
                {
                    if (data.TypeName == "System.String")
                        relogger.WriteEvent(data);
                };
                relogger.Clr.ExceptionStart += delegate(ExceptionTraceData data)
                {
                    relogger.WriteEvent(data);
                };

                // We also keep the image load events for DLL with 'clr' in their name.
                relogger.Kernel.ImageGroup += delegate(ImageLoadTraceData data)
                {
                    if (0 <= data.FileName.IndexOf("clr", StringComparison.OrdinalIgnoreCase))
                        relogger.WriteEvent(data);
                };

#if false       // Turn on to get debugging on unhandled events.  
                relogger.UnhandledEvents += delegate(TraceEvent data)
                {
                    Console.WriteLine("Unknown Event " + data);
                };
#endif
                // Allow the test to be terminated with Ctrl-C cleanly. 
                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { session.Dispose(); };

                // Set up a timer to stop processing after monitoringTimeSec
                var timer = new Timer(delegate(object state)
                {
                    Out.WriteLine("Stopped after {0} sec", monitoringTimeSec);
                    session.Dispose();
                }, null, monitoringTimeSec * 1000, Timeout.Infinite);

                // Turn on the events to the provider.  In this case most CLR events 

                Out.WriteLine("**** Turn on CLR Etw Providers.  Run managed code to see events.");
                session.EnableProvider(ClrTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)ClrTraceEventParser.Keywords.Default);

                // go into a loop processing events can calling the callbacks.  Because this is live data (not from a file)
                // processing never completes by itself, but only because someone called 'source.Dispose()'.  
                Out.WriteLine("**** Start listening for events from the Microsoft-Demos-SimpleMonitor provider.");
                Out.WriteLine("The monitor will run for a maximum of {0} seconds.  Run managed code for more output.", monitoringTimeSec);
                relogger.Process();
                Out.WriteLine();
                Out.WriteLine("Stopping the collection of events.");
                timer.Dispose();    // Turn off the timer.  
            }

            Out.WriteLine("Monitoring complete, only certain CLR events put in the output file.");
            Out.WriteLine("The output ETL file: {0}", Path.GetFullPath(outputFileName));
            Out.WriteLine();

            if (!File.Exists(outputFileName))
            {
                Out.WriteLine("Error: No output file was generated (did you run anything during the collection?");
                return;
            }

            // Show what was actually produced in the filtered file.  
            DataProcessing(outputFileName);
        }