Esempio n. 1
0
        private static void RealTimeSession()
        {
            if (options.ParsedClrKeywords == 0 &&
                options.ParsedKernelKeywords == KernelTraceEventParser.Keywords.None &&
                options.OtherProviders.Count == 0)
            {
                Bail("No events to collect");
            }

            Console.CancelKeyPress += (_, __) => CloseSession();

            if (options.DurationInSeconds > 0)
            {
                Task.Delay(TimeSpan.FromSeconds(options.DurationInSeconds))
                .ContinueWith(_ => CloseSession());
            }
            using (session = new TraceEventSession("etrace-realtime-session"))
            {
                if (options.ParsedKernelKeywords != KernelTraceEventParser.Keywords.None)
                {
                    session.EnableKernelProvider(options.ParsedKernelKeywords);
                }
                if (options.ParsedClrKeywords != 0)
                {
                    session.EnableProvider(ClrTraceEventParser.ProviderGuid,
                                           matchAnyKeywords: (ulong)options.ParsedClrKeywords);
                }
                if (options.OtherProviders.Any())
                {
                    foreach (var provider in options.OtherProviders)
                    {
                        Guid guid;
                        if (Guid.TryParse(provider, out guid))
                        {
                            session.EnableProvider(Guid.Parse(provider));
                        }
                        else
                        {
                            guid = TraceEventProviders.GetProviderGuidByName(provider);
                            if (guid != Guid.Empty)
                            {
                                session.EnableProvider(guid);
                            }
                        }
                    }
                }
                if (options.IsOutFile)
                {
                    outRelogger      = new ETWReloggerTraceEventSource(session.SessionName, TraceEventSourceType.Session, options.OutFile);
                    isOutReloggerSet = true;
                    ProcessTrace(outRelogger);
                }
                else
                {
                    ProcessTrace(session.Source);
                }
            }
        }
Esempio n. 2
0
        protected PerformanceTestContext(TraceEventDispatcher source)
        {
            _source        = source;
            _relogger      = source as ETWReloggerTraceEventSource;
            IsWriteEnabled = _relogger != null;

            if (IsWriteEnabled)
            {
                _relogger.Dynamic.All += WriteEvent;
                _relogger.Kernel.All  += WriteEvent;
                _relogger.Clr.All     += WriteEvent;
            }
        }
        /// <summary>
        /// This routine shows how to use ETWReloggerTraceEventSource take a ETL file (inputFileName)
        /// and filter out events to form another ETL file (outputFileName).
        ///
        /// For this example we filter out all events that are not GCAllocationTicks
        /// </summary>
        private static void FilterData(string inputFileName, string outFileName)
        {
            // Open the input file and output file.   You will then get a callback on every input event,
            // and if you call 'WriteEvent' you can copy it to output file.
            // In our example we only copy large object
            using (var relogger = new ETWReloggerTraceEventSource(inputFileName, outFileName))
            {
                // Here we register callbacks for data we are interested in and further filter by.

                // In this case we 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);
                    }
                };

                // Keep all the process start events
                relogger.Kernel.ProcessStart += delegate(ProcessTraceData data)
                {
                    relogger.WriteEvent(data);
                };

                // Keep GC Start and stop events.  This can be done more efficiently if you
                // use multiple callbacks, but this technique may be easier if the events are
                // not known at compile time.
                relogger.Clr.All += delegate(TraceEvent data)
                {
                    if (data.EventName == "GC/Start" || data.EventName == "GC/Stop")
                    {
                        relogger.WriteEvent(data);
                    }
                };

#if false       // Turn on to get debugging on unhandled events.
                relogger.UnhandledEvents += delegate(TraceEvent data)
                {
                    Console.WriteLine("Unknown Event " + data);
                };
#endif
                relogger.Process();
            }
        }
        /// <summary>
        /// This routine shows how to use ETWReloggerTraceEventSource take a ETL file (inputFileName)
        /// and filter out events to form another ETL file (outputFileName).  
        /// 
        /// For this example we filter out all events that are not GCAllocationTicks 
        /// </summary>
        private static void FilterData(string inputFileName, string outFileName)
        {
            // Open the input file and output file.   You will then get a callback on every input event,
            // and if you call 'WriteEvent' you can copy it to output file.   
            // In our example we only copy large object 
            using (var relogger = new ETWReloggerTraceEventSource(inputFileName, outFileName))
            {
                // Here we register callbacks for data we are interested in and further filter by.  
 
                // In this case we 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);
                };

                // Keep all the process start events 
                relogger.Kernel.ProcessStart += delegate(ProcessTraceData data)
                {
                    relogger.WriteEvent(data);
                };

                // Keep GC Start and stop events.  This can be done more efficiently if you 
                // use multiple callbacks, but this technique may be easier if the events are 
                // not known at compile time. 
                relogger.Clr.All += delegate(TraceEvent data)
                {
                    if (data.EventName == "GC/Start" || data.EventName == "GC/Stop")
                        relogger.WriteEvent(data);
                };

#if false       // Turn on to get debugging on unhandled events.  
                relogger.UnhandledEvents += delegate(TraceEvent data)
                {
                    Console.WriteLine("Unknown Event " + data);
                };
#endif 
                relogger.Process();
            }
        }
Esempio n. 5
0
        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 = "SimpleMontitorSession";

            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);
        }
        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 = "SimpleMontitorSession";
            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);
        }
Esempio n. 7
0
        static void Main(string[] args)
        {
            if (args.Count() < 3 || args.Count() > 4)
            {
                Console.WriteLine("\nUsage: ETWSplitter.exe <InputFile.etl> <OutputFile.etl> <#_of_Files> [compress]\n");
                return;
            }

            string inputFileName = args[0];
            string outFileName   = args[1];

            if (!File.Exists(inputFileName))
            {
                Console.WriteLine("ERROR: Input file {0} was not found!", inputFileName);
                return;
            }

            if (inputFileName.Equals(outFileName, StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine("ERROR: Input file and output file have the same name!");
                return;
            }

            if (outFileName.EndsWith(".etl", StringComparison.OrdinalIgnoreCase))
            {
                outFileName = outFileName.Remove(outFileName.Length - 4);
            }

            if (!int.TryParse(args[2], out int numberOfFiles))
            {
                Console.WriteLine("ERROR: {0} is not an integer!", args[2]);
                return;
            }

            if (numberOfFiles < 2 || numberOfFiles > 1024)
            {
                Console.WriteLine("ERROR: {0} is outside of range!", numberOfFiles);
                return;
            }

            bool compress = false;

            if (args.Count() > 3)
            {
                if (args[3].StartsWith("c", StringComparison.OrdinalIgnoreCase))
                {
                    compress = true;
                    Console.WriteLine("Compression enabled.");
                }
            }

            if (compress == false)
            {
                Console.WriteLine("Compression disabled.");
            }

            Int64 totalNumberOfEvents = 0;

            using (var etwReader = new ETWTraceEventSource(inputFileName))
            {
                etwReader.AllEvents += delegate(TraceEvent data)
                {
                    Interlocked.Increment(ref totalNumberOfEvents);
                };

                etwReader.Process();
            }

            if (totalNumberOfEvents < 2)
            {
                Console.WriteLine("ERROR: Did not detect any ETW events in the input file!");
                return;
            }

            Console.WriteLine("{0} total events found.", totalNumberOfEvents);

            Int64 numberOfEventsPerFile = totalNumberOfEvents / numberOfFiles;

            Console.WriteLine("Writing {0} files with {1} events each...", numberOfFiles, numberOfEventsPerFile);


            Int64 totalEventsWritten = 0;

            for (int fileNum = 0; fileNum < numberOfFiles; fileNum++)
            {
                Stopwatch fileTimer = new Stopwatch();

                string splitFileName = outFileName + fileNum + ".etl";

                Int64 thisFileStartIndex = numberOfEventsPerFile * fileNum;

                Int64 thisFileEventsWritten = 0;

                Int64 currentEvent = 0;

                fileTimer.Start();

                Console.Write("{0}...", splitFileName);

                using (var relogger = new ETWReloggerTraceEventSource(inputFileName, splitFileName))
                {
                    if (compress)
                    {
                        relogger.OutputUsesCompressedFormat = true;
                    }
                    else
                    {
                        relogger.OutputUsesCompressedFormat = false;
                    }

                    relogger.AllEvents += delegate(TraceEvent data)
                    {
                        if ((currentEvent >= thisFileStartIndex) && (currentEvent < (thisFileStartIndex + numberOfEventsPerFile)))
                        {
                            relogger.WriteEvent(data);
                            Interlocked.Increment(ref thisFileEventsWritten);
                            Interlocked.Increment(ref totalEventsWritten);
                        }
                        Interlocked.Increment(ref currentEvent);
                    };

                    relogger.Process();
                };

                fileTimer.Stop();

                TimeSpan timeElapsed = fileTimer.Elapsed;

                Console.WriteLine(" Done in {0:00}h:{1:00}m:{2:00}s. Wrote: {3} Filesize: {4}MB", timeElapsed.Hours, timeElapsed.Minutes, timeElapsed.Seconds, thisFileEventsWritten, (new FileInfo(splitFileName).Length) / 1024 / 1024);
            }
        }
        public override TestResult[] Execute(ITestMethod testMethod)
        {
            TestResult[] errorResults = ValidateElevated(testMethod);
            if (errorResults != null)
            {
                return(errorResults);
            }

            Exception signatureException = GetMethodSignatureException(testMethod);

            if (signatureException != null)
            {
                return(testMethod.CreateExceptionResult(signatureException));
            }

            var    runParameters = TestRunParameters.Read();
            string logFolder     = runParameters.LogFolder;
            bool   shouldLog     = !string.IsNullOrEmpty(logFolder);

            if (shouldLog)
            {
                try
                {
                    logFolder = CreateLogFolder(logFolder, testMethod.TestMethodName);
                }
                catch (Exception e)
                {
                    return(testMethod.CreateExceptionResult(e));
                }
            }

            int iterations = runParameters.Iterations;
            var results    = new TestResult[iterations];

            for (int iteration = 1; iteration <= iterations; iteration++)
            {
                string sessionName = $"{testMethod.TestMethodName}-{iteration}";

                using (var session = new TraceEventSession(sessionName))
                {
                    EnableKernelProviders(session, shouldLog);

                    TraceEventDispatcher source;
                    ZippedETLWriter      writer = null;
                    if (shouldLog)
                    {
                        string etlPath = Path.Combine(logFolder, $"Iteration{iteration}.etl");
                        source = new ETWReloggerTraceEventSource(sessionName, TraceEventSourceType.Session, etlPath);
                        writer = new ZippedETLWriter(etlPath);
                    }
                    else
                    {
                        source = session.Source;
                    }

                    EnableProviders(session);
                    PerformanceTestContext context = CreateContext(source);

                    Task <TestResult> testTask = Task.Run(() => testMethod.Invoke(new object[] { context }));

                    // This is a blocking call that in the case of ETWReloggerTraceEventSource, must be run on the same
                    // thread as ETWReloggerTraceEventSource was created on. It will become unblocked when the
                    // PerformanceTestContext calls StopProcessing on the source.
                    source.Process();

                    TestResult result      = testTask.Result;
                    string     displayName = testMethod.TestMethodName;
                    if (iterations > 1)
                    {
                        displayName += $" [{iteration}/{iterations}]";
                    }

                    result.DisplayName = displayName;

                    session.Flush();
                    OnIterationEnded(context);

                    context.LogScenarios();
                    context.LogMemoryDelta();
                    context.LogMessage($"{displayName} completed. {session.EventsLost} events lost.");
                    context.WriteLogsToResult(result, writer);

                    results[iteration - 1] = result;
                }
            }

            return(results);
        }