Пример #1
1
        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;
            }
        }
        private void SetupProviderAndParser()
        {
            try
            {
                //enabling the providers
                if (SessionAttribute.IsKernelSession)
                {
                    if (SessionAttribute is KernelTraceSessionAttribute)
                    {
                        traceEventSession.EnableKernelProvider(((KernelTraceSessionAttribute)SessionAttribute).KernelSessionKeywords);
                    }
                    else
                    {
                        traceEventSession.EnableKernelProvider(KernelTraceEventParser.Keywords.Default);
                    }
                }
                else
                {
                    traceEventSession.EnableProvider(SessionAttribute.providerName, SessionAttribute.providerLevel, options: SessionAttribute.TraceEventProviderOptions);
                }

                //creating the trace event parser
                traceEventParser = Activator.CreateInstance(SessionAttribute.eventParserType, traceEventSession.Source) as TraceEventParser;

                //set the trace event parser through session's properties
                traceEventParser.AddCallbackForProviderEvents(CallbackForProviderEvents, CallbackForEvents);
            }
            catch (Exception ex)
            {
                TraceSessionError(ex);
            }
        }
Пример #3
0
        /// <summary>
        /// Observe Out-of-Process ETW Kernel TraceEvent.
        /// </summary>
        public static IObservable <TraceEvent> FromKernelTraceEvent(KernelTraceEventParser.Keywords flags, KernelTraceEventParser.Keywords stackCapture = KernelTraceEventParser.Keywords.None)
        {
            IConnectableObservable <TraceEvent> source;

            var session = new TraceEventSession("ObservableEventListenerFromKernelTraceEventSession." + Guid.NewGuid().ToString());

            try
            {
                var guid = KernelTraceEventParser.ProviderGuid;
                session.EnableKernelProvider(flags, stackCapture); // needs enable before observe
                source = session.Source.Kernel.Observe((pName, eName) => EventFilterResponse.AcceptEvent)
                         .Where(x => x.ProviderGuid == guid && x.EventName != ManifestEventName && x.ID != ManifestEventID)
                         .Finally(() => session.Dispose())
                         .Publish();
            }
            catch
            {
                session.Dispose();
                throw;
            }

            Task.Factory.StartNew(state =>
            {
                using (session)
                {
                    session.Source.Process();
                }
            }, TaskCreationOptions.LongRunning);

            return(source.RefCount());
        }
Пример #4
0
        /// <summary>
        /// Observe Out-of-Process ETW Kernel TraceEvent.
        /// </summary>
        public static IObservable <TData> FromKernelTraceEvent <TData>(KernelTraceEventParser.Keywords flags, KernelTraceEventParser.Keywords stackCapture = KernelTraceEventParser.Keywords.None)
            where TData : TraceEvent
        {
            IConnectableObservable <TData> source;
            var session = new TraceEventSession("ObservableEventListenerFromKernelTraceEventSession." + Guid.NewGuid().ToString());

            try
            {
                session.EnableKernelProvider(flags, stackCapture);
                source = session.Source.Kernel.Observe <TData>().Finally(() => session.Dispose()).Publish();
            }
            catch
            {
                session.Dispose();
                throw;
            }

            Task.Factory.StartNew(state =>
            {
                using (session)
                {
                    session.Source.Process();
                }
            }, TaskCreationOptions.LongRunning);

            return(source.RefCount());
        }
Пример #5
0
        public void Start(IEnumerable <EventType> types)
        {
            if (EventTrace == null)
            {
                throw new InvalidOperationException("Must register for event notifications");
            }

            _kernelSession =
                new TraceEventSession(KernelTraceEventParser.KernelSessionName,
                                      TraceEventSessionOptions.NoRestartOnCreate)
            {
                BufferSizeMB          = 128,
                CpuSampleIntervalMSec = 10,
            };
            var keywords = KernelTraceEventParser.Keywords.All;

            _processingThread = new Thread(() =>
            {
                _kernelSession.EnableKernelProvider(keywords);
                _kernelParser = new KernelTraceEventParser(_kernelSession.Source);
                SetupCallbacks(types);
                _kernelSession.Source.Process();
            });
            _processingThread.Priority     = ThreadPriority.Lowest;
            _processingThread.IsBackground = true;
            _processingThread.Start();
        }
Пример #6
0
        /// <summary>
        /// Starts the ETW session, and processes the stack samples that come in. This method
        /// does not return until another thread calls <see cref="Stop"/> to stop the session.
        /// While this method is executing, live stack aggregates can be obtained from the
        /// <see cref="Stacks"/> property, which is thread-safe.
        /// </summary>
        public void Start()
        {
            _session = new TraceEventSession($"LiveStacks-{Process.GetCurrentProcess().Id}");

            // TODO Make the CPU sampling interval configurable, although changing it doesn't seem to work in a VM?
            // _session.CpuSampleIntervalMSec = 10.0f;

            // TODO Should we use _session.StackCompression? What would the events look like?

            if (_provider == "kernel")
            {
                _session.EnableKernelProvider(_kernelKeyword, stackCapture: _kernelKeyword);
                _session.Source.Kernel.StackWalkStack += OnKernelStackEvent;
            }

            if (_provider == "clr")
            {
                _session.EnableProvider(
                    ClrTraceEventParser.ProviderGuid,
                    matchAnyKeywords: (ulong)(_clrKeyword | ClrTraceEventParser.Keywords.Stack));
                _session.Source.Clr.All          += OnAnyClrEvent;
                _session.Source.Clr.ClrStackWalk += OnClrStackEvent;
            }

            _session.Source.Process();
        }
Пример #7
0
        public void MonitorNetwork()
        {
            var sessionName = "NT Kernel Logger";

            using (var session = new TraceEventSession(sessionName, null))  // the null second parameter means 'real time session'
            {
                session.StopOnDispose = true;

                using (var source = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session))
                {
                    Action <TraceEvent> action = delegate(TraceEvent data)
                    {
                        if (ready)
                        {
                            tHandler = new TimeoutHandler(1);
                            tHandler.SessionTimeout += tHandler_SessionTimeout;
                            ready = false;
                            addData(data);
                        }
                    };
                    var registeredParser = new RegisteredTraceEventParser(source);
                    registeredParser.All += action;

                    session.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);
                    source.Process();
                }
            }
        }
Пример #8
0
    /// <summary>
    /// Dump the  dot net Heap for process 'processID' to the etl file name 'etlFileName'.  Send diagnostics to 'log'.
    /// If 'memoryGraph is non-null also update it to contain the heap Dump.  If null you get just the ETL file.
    /// returns true if successful.
    /// </summary>
    static public bool DumpAsEtlFile(int processID, string etlFileName, TextWriter log, MemoryGraph memoryGraph = null, DotNetHeapInfo dotNetInfo = null)
    {
        bool success = false;

        log.WriteLine("Starting ETW logging on File {0}", etlFileName);
        using (var session = new TraceEventSession("PerfViewGCHeapETLSession", etlFileName))
        {
            session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread | KernelTraceEventParser.Keywords.ImageLoad);

            // Isolate this to a single process.
            var options = new TraceEventProviderOptions()
            {
                ProcessIDFilter = new List <int>()
                {
                    processID
                }
            };

            // For non-project N we need module rundown to figure out the correct module name
            session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Verbose,
                                   (ulong)(ClrRundownTraceEventParser.Keywords.Loader | ClrRundownTraceEventParser.Keywords.ForceEndRundown), options);

            session.EnableProvider(ClrTraceEventParser.ProviderGuid, TraceEventLevel.Informational,
                                   (ulong)(ClrTraceEventParser.Keywords.GCHeapDump | ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.Type | ClrTraceEventParser.Keywords.Type | ClrTraceEventParser.Keywords.GCHeapAndTypeNames), options);
            // Project  N support.
            session.EnableProvider(ClrTraceEventParser.NativeProviderGuid, TraceEventLevel.Informational,
                                   (ulong)(ClrTraceEventParser.Keywords.GCHeapDump | ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.Type | ClrTraceEventParser.Keywords.Type | ClrTraceEventParser.Keywords.GCHeapAndTypeNames), options);

            success = Dump(processID, memoryGraph, log, dotNetInfo);
            log.WriteLine("Stopping ETW logging on {0}", etlFileName);
        }

        log.WriteLine("DumpAsETLFile returns.  Success={0}", success);
        return(success);
    }
Пример #9
0
        static void Main(string[] args)
        {
            Out = Console.Out;
            Out.WriteLine("Hello World!");

            using (var session = new TraceEventSession("pri"))
            {
                void ConsoleOnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
                {
                    Console.CancelKeyPress -= ConsoleOnCancelKeyPress;
                    session?.Dispose();
                }

                Console.CancelKeyPress += ConsoleOnCancelKeyPress;
                session.EnableKernelProvider(KernelTraceEventParser.Keywords.Registry);

                session.Source.Kernel.RegistryCreate          += KernelParser_RegistryCreate;
                session.Source.Kernel.RegistrySetValue        += KernelParser_RegistrySetValue;
                session.Source.Kernel.RegistryDeleteValue     += KernelParser_RegistryDeleteValue;
                session.Source.Kernel.RegistryDelete          += KernelParser_RegistryDelete;
                session.Source.Kernel.RegistryKCBCreate       += KernelParser_RegistryKCBCreate;
                session.Source.Kernel.RegistryKCBDelete       += KernelParser_RegistryKCBDelete;
                session.Source.Kernel.RegistryKCBRundownBegin += Kernel_RegistryKCBRundownBegin;
                session.Source.Kernel.RegistryKCBRundownEnd   += Kernel_RegistryKCBRundownEnd;

                Out.WriteLine("Collecting events");
                session.Source.Process();
                Out.WriteLine("Stopping collection of events");
            }
        }
Пример #10
0
        public ETWCollector(KernelTraceEventParser.Keywords flags = TraceProcessFlags)
        {
            Session = new TraceEventSession("Optick");
            Session.BufferSizeMB = 256;

            Session.EnableKernelProvider(flags);

            // Processes
            Session.Source.Kernel.ProcessStart += Kernel_ProcessStart;
            Session.Source.Kernel.ProcessStop  += Kernel_ProcessStop;

            // Image
            Session.Source.Kernel.ImageLoad += Kernel_ImageLoad;

            // Threads
            Session.Source.Kernel.ThreadStart += Kernel_ThreadStart;
            Session.Source.Kernel.ThreadStop  += Kernel_ThreadStop;

            // IO
            Session.Source.Kernel.FileIORead         += Kernel_FileIORead;
            Session.Source.Kernel.FileIOWrite        += Kernel_FileIOWrite;
            Session.Source.Kernel.FileIOOperationEnd += Kernel_FileIOOperationEnd;

            // SysCalls
            Session.Source.Kernel.PerfInfoSysClEnter += Kernel_PerfInfoSysClEnter;
            Session.Source.Kernel.PerfInfoSysClExit  += Kernel_PerfInfoSysClExit;

            // Switch Contexts
            Session.Source.Kernel.ThreadCSwitch += Kernel_ThreadCSwitch;

            // Samples
            Session.Source.Kernel.StackWalkStack += Kernel_StackWalkStack;
        }
Пример #11
0
        public CollectTraceEventsHelper(CommandLineOptions options)
        {
            if (TraceEventSession.IsElevated() != true)
                throw new InvalidOperationException("Collecting perf events requires administrative privileges.");

            if (options.ClrEvents.Events == ClrTraceEventParser.Keywords.None && options.KernelEvents == KernelTraceEventParser.Keywords.None)
                throw new PowerArgs.ArgException("Must specify at least one CLR or kernel event.");

            // verify session name
            var existingSessions = TraceEventSession.GetActiveSessionNames();

            if (options.Mode == ExecutionMode.Start && existingSessions.Contains(options.TestName))
                throw new InvalidOperationException(string.Format("The session name '{0}' is already in use.", options.TestName));
            else if (options.Mode == ExecutionMode.Stop && !existingSessions.Contains(options.TestName))
                throw new InvalidOperationException(string.Format("The session name '{0}' does not exist.", options.TestName));

            m_traceSession = new TraceEventSession(options.TestName, options.DataFile);

            if (options.Mode == ExecutionMode.Start)
            {
                m_traceSession.BufferSizeMB = 512;

                // starting a new session, enable providers
                m_traceSession.EnableKernelProvider(options.KernelEvents);
                m_traceSession.EnableProvider(ClrTraceEventParser.ProviderGuid, TraceEventLevel.Informational, (ulong)options.ClrEvents.Events);

                // keep the session active after the process terminates
                m_traceSession.StopOnDispose = false;
            }
        }
Пример #12
0
        public void Run()
        {
            var isElevated = TraceEventSession.IsElevated() ?? false;

            if (!isElevated)
            {
                Console.WriteLine("ETW tracing of kernel providers requires admin rights");
                Console.WriteLine("Please restart and run as administrator");
                return;
            }

            Console.WriteLine("Start processing");

            Console.CancelKeyPress += (sender, args) => Dispose();

            _session.EnableKernelProvider(KernelTraceEventParser.Keywords.All);

            _session.Source.Kernel.ProcessStart += data =>
            {
                Console.WriteLine($"Starting process {GetProcessName(data)}");
            };

            _session.Source.Kernel.ProcessStop += data =>
            {
                Console.WriteLine($"Stopping process {GetProcessName(data)}");
            };

            _timer = InitializeTimer();

            _session.Source.Process();
        }
Пример #13
0
 /// <summary>
 /// Interface to enable kernel providers.
 /// </summary>
 /// <param name="flags">Specifies the particular kernel events of interest.</param>
 /// <param name="stackCapture">Specifies which events should have their stack traces captured when an event is logged.</param>
 public void EnableKernelProvider(KernelTraceEventParser.Keywords flags, KernelTraceEventParser.Keywords stackCapture)
 {
     if (TraceEventSession.EnableKernelProvider(flags, stackCapture))
     {
         Debug.WriteLine("The session existed before and needed to be restarted.");
     }
 }
Пример #14
0
        public static void Run()
        {
            if (TraceEventSession.IsElevated() != true)
            {
                Console.WriteLine("Must be elevated (Admin) to run this program.");
                Debugger.Break();
                return;
            }

            // Set up Ctrl-C to stop both user mode and kernel mode sessions
            Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) =>
            {
                StopSessions();
                cancelArgs.Cancel = true;
            };
            Console.WriteLine("Start monitoring for ransomware file activity");
            var task1 = Task.Run(() =>
            {
                using (s_kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName))
                {
                    //This is the best spot to examine for efficiency improvments
                    //As you might expect, listening to large amounts of kernel events can be slow
                    s_kernelSession.EnableKernelProvider(
                        KernelTraceEventParser.Keywords.All
                        );
                    s_kernelSession.Source.Kernel.All += FilterIOEvents;
                    // process events until Ctrl-C is pressed
                    s_kernelSession.Source.Process();
                }
                Console.WriteLine("Thread 1 dieing");
            });

            Task.WaitAll(task1);
        }
Пример #15
0
        public void Start(IEnumerable <EventType> types, bool includeInit)
        {
            if (EventTrace == null)
            {
                throw new InvalidOperationException("Must register for event notifications");
            }

            _includeInit = includeInit;
            _session     = new TraceEventSession(KernelTraceEventParser.KernelSessionName)
            {
                BufferSizeMB          = 128,
                CpuSampleIntervalMSec = 10
            };

            var keywords = KernelTraceEventParser.Keywords.None;

            foreach (var type in types)
            {
                keywords |= EventInfo.AllEventsByType[type].Keyword;
            }

            _session.EnableKernelProvider(keywords);

            _processingThread = new Thread(() => {
                _parser = new KernelTraceEventParser(_session.Source);
                SetupCallbacks(types);
                _session.Source.Process();
            });
            _processingThread.Priority     = ThreadPriority.Lowest;
            _processingThread.IsBackground = true;
            _processingThread.Start();
        }
        private void SetupProviders(TraceEventSession session)
        {
            // Note: the kernel provider MUST be the first provider to be enabled
            // If the kernel provider is not enabled, the callstacks for CLR events are still received
            // but the symbols are not found (except for the application itself)
            // TraceEvent implementation details triggered when a module (image) is loaded
            session.EnableKernelProvider(
                KernelTraceEventParser.Keywords.ImageLoad |
                KernelTraceEventParser.Keywords.Process,
                KernelTraceEventParser.Keywords.None
                );

            session.EnableProvider(
                ClrTraceEventParser.ProviderGuid,
                TraceEventLevel.Verbose,    // this is needed in order to receive AllocationTick_V2 event
                (ulong)(
                    // required to receive AllocationTick events
                    ClrTraceEventParser.Keywords.GC |
                    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.Stack                       // Get the callstack for each event
                    )
                );

            // this provider will send events of already JITed methods
            session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Verbose,
                                   (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)
                                       ));
        }
Пример #17
0
        internal override Session EnableProviders()
        {
            var keywords = Config.KernelKeywords
                           | KernelTraceEventParser.Keywords.ImageLoad // handles stack frames from native modules, SUPER IMPORTANT!
                           | KernelTraceEventParser.Keywords.Profile;  // CPU stacks

            if (Details.Config.GetHardwareCounters().Any())
            {
                keywords |= KernelTraceEventParser.Keywords.PMCProfile; // Precise Machine Counters
            }
            TraceEventSession.StackCompression = true;

            try
            {
                TraceEventSession.EnableKernelProvider(keywords, Config.KernelStackKeywords);
            }
            catch (Win32Exception)
            {
                Details.Config.GetCompositeLogger().WriteLineError(
                    "Please install the latest Microsoft.Diagnostics.Tracing.TraceEvent package in the project with benchmarks so MSBuild can copy the native dependencies of TraceEvent to the output folder.");

                throw;
            }

            return(this);
        }
Пример #18
0
        static void Main(string[] args)
        {
            if (!(TraceEventSession.IsElevated() ?? false))
            {
                Console.WriteLine("Admin değilsin");
                return;
            }

            using (var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName))
            {
                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { kernelSession.Dispose(); };

                kernelSession.EnableKernelProvider(
                    KernelTraceEventParser.Keywords.Process |
                    KernelTraceEventParser.Keywords.NetworkTCPIP |
                    KernelTraceEventParser.Keywords.ImageLoad |
                    KernelTraceEventParser.Keywords.Registry
                    );

                kernelSession.Source.Kernel.ProcessStart   += _processStart;
                kernelSession.Source.Kernel.TcpIpConnect   += _tcpMetod;
                kernelSession.Source.Kernel.ImageLoad      += _imageLoad;
                kernelSession.Source.Kernel.RegistryCreate += _regCreate;

                kernelSession.Source.Process();
            }
        }
Пример #19
0
        private void StartEtwSession()
        {
            try
            {
                ResetCounters();

                using (_etwSession = new TraceEventSession("KernelTcpIpEventsSession"))
                {
                    _etwSession.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);
                    _etwSession.Source.Kernel.TcpIpRecv += data =>
                    {
                        if (_processList().Contains(data.ProcessID))
                        {
                            Interlocked.Add(ref _counters.processDownloadSpeed, data.size * 8);
                            Interlocked.Add(ref _counters.processTotalBytesReceived, data.size);
                        }
                    };

                    _etwSession.Source.Kernel.TcpIpSend += data =>
                    {
                        if (_processList().Contains(data.ProcessID))
                        {
                            Interlocked.Add(ref _counters.processUploadSpeed, data.size * 8);
                            Interlocked.Add(ref _counters.processTotalBytesSent, data.size);
                        }
                    };
                    _etwSession.Source.Process();
                }
            }
            catch
            {
                ResetCounters();
            }
        }
Пример #20
0
 void StartSession()
 {
     kernelsession.EnableKernelProvider(KernelTraceEventParser.Keywords.NetworkTCPIP);
     kernelsession.Source.Kernel.TcpIpSend += Kernel_TcpIpSend;
     kernelsession.Source.Kernel.TcpIpRecv += Kernel_TcpIpRecv;
     kernelsession.Source.Process();
 }
Пример #21
0
 public void StartWatch()
 {
     KernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName);
     KernelSession.EnableKernelProvider(KernelTraceEventParser.Keywords.Process);
     KernelSession.Source.Kernel.ProcessStart += OnProcessStart;
     watcherTask = new Task(Watch, cancellationTokenSource.Token);
     watcherTask.Start();
 }
Пример #22
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);
                }
            }
        }
Пример #23
0
        static void Main(string[] args)
        {
            int samples           = 0;
            var samplesPerProcess = new Dictionary <(int, string), int>(500);

            Console.WriteLine("Press ENTER to start");
            Console.ReadLine();
            Console.WriteLine("Profiling for 10 seconds...");

            using (var session = new TraceEventSession(KernelTraceEventParser.KernelSessionName)) {
                session.EnableKernelProvider(KernelTraceEventParser.Keywords.Profile);
                var parser = session.Source.Kernel;

                parser.PerfInfoSample += sample => {
                    var name = sample.ProcessName;
                    samples++;
                    if (sample.ProcessID < 0)
                    {
                        if (sample.NonProcess)
                        {
                            name = "(DPC/ISR)";
                        }
                    }
                    try {
                        if (string.IsNullOrEmpty(name) && sample.ProcessID >= 0)
                        {
                            name = Process.GetProcessById(sample.ProcessID)?.ProcessName;
                        }
                    }
                    catch {
                        name = "<Unknown>";
                    }
                    var key = (sample.ProcessID, name);
                    if (samplesPerProcess.ContainsKey(key))
                    {
                        samplesPerProcess[key]++;
                    }
                    else
                    {
                        samplesPerProcess.Add(key, 1);
                    }
                };

                parser.PerfInfoSetInterval += e => Console.WriteLine($"New interval: {e.NewInterval}");
                parser.LostEvent           += e => Console.WriteLine("Event lost");
                Task.Run(() => session.Source.Process());
                Thread.Sleep(10000);
            }

            Console.WriteLine($"Analyzing {samples} samples");
            foreach (var item in samplesPerProcess.OrderByDescending(pair => pair.Value).TakeWhile(pair => pair.Value * 100.0f / samples >= 1))
            {
                Console.WriteLine($"{item}: {item.Value * 100.0f / samples:N2} %");
            }
        }
Пример #24
0
        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();
            }
        }
Пример #25
0
        /// <summary>
        /// Turning on providers and creating files
        /// </summary>
        private static void DataCollection(string dataFileName)
        {
            Out.WriteLine("Collecting 10 seconds of kernel and CLR events to a file, and then printing.");
            Out.WriteLine();
            Out.WriteLine("Start a .NET program while monitoring to see some events!");
            Out.WriteLine();
            if (TraceEventSession.IsElevated() != true)
            {
                Out.WriteLine("Must be elevated (Admin) to run this program.");
                Debugger.Break();
                return;
            }

            string kernelDataFileName = Path.ChangeExtension(dataFileName, ".kernel.etl");

            // Create one user mode session and one kernel mode session
            Out.WriteLine("Creating two raw files, one with kernel events and one with clr events.");
            using (var userSession = new TraceEventSession("MonitorKernelAndClrEventsSession", dataFileName))
                using (var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, kernelDataFileName))
                {
                    // Set up Ctrl-C to stop both user mode and kernel mode sessions
                    Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs cancelArgs)
                    {
                        Out.WriteLine("Insuring all ETW sessions are stopped.");
                        kernelSession.Stop(true);     // true means don't throw on error
                        userSession.Stop(true);       // true means don't throw on error
                        // Since we don't cancel the Ctrl-C we will terminate the process as normal for Ctrl-C
                        Out.WriteLine("OnCtrl C handler ending.");
                    };

                    // Enable the events we care about for the kernel in the kernel session
                    // For this instant the session will buffer any incoming events.
                    kernelSession.EnableKernelProvider(
                        KernelTraceEventParser.Keywords.ImageLoad |
                        KernelTraceEventParser.Keywords.Process |
                        KernelTraceEventParser.Keywords.Thread);

                    // Enable the events we care about for the CLR (in the user session).
                    // unlike the kernel session, you can call EnableProvider on other things too.
                    // For this instant the session will buffer any incoming events.
                    userSession.EnableProvider(
                        ClrTraceEventParser.ProviderGuid,
                        TraceEventLevel.Informational,
                        (ulong)(ClrTraceEventParser.Keywords.Default));

                    Out.WriteLine("Collecting data for 10 seconds (run a .Net program to generate events).");
                    Thread.Sleep(10000);

                    Out.WriteLine("Stopping sessions");
                }// Using clauses will insure that session are disposed (and thus stopped) before Main returns.

            Out.WriteLine("Merging the raw files into a single '{0}' file.", dataFileName);
            TraceEventSession.MergeInPlace(dataFileName, Out);
            Out.WriteLine("Merge complete.");
        }
Пример #26
0
 public void Start()
 {
     if (kernelFlags != KernelTraceEventParser.Keywords.None)
     {
         traceSession.EnableKernelProvider(kernelFlags);
     }
     foreach (var handler in eventHandlers)
     {
         handler.SubscribeToSession(traceSession);
     }
     traceSession.Source.Process();
 }
Пример #27
0
 protected virtual void EnableKernelProviders(TraceEventSession session, bool isLoggingEnabled)
 {
     if (isLoggingEnabled)
     {
         // Traces cannot be symbolicated without the ImageLoad provider.
         session.EnableKernelProvider(
             KernelTraceEventParser.Keywords.Profile
             | KernelTraceEventParser.Keywords.Process
             | KernelTraceEventParser.Keywords.ImageLoad
             | KernelTraceEventParser.Keywords.Thread,
             KernelTraceEventParser.Keywords.Profile);
     }
 }
Пример #28
0
 protected override void Capture(TraceEventSession session)
 {
     session.EnableKernelProvider(Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser.Keywords.Process);
     session.Source.Kernel.ProcessStart += (ProcessTraceData data) =>
     {
         Debug.WriteLine(data.Dump());
         _sender.Send(data.ProcessID, "Process Started:" + data.CommandLine, PROCESS_CREATION);
     };
     session.Source.Kernel.ProcessStop += (ProcessTraceData data) =>
     {
         Debug.WriteLine(data.Dump());
         _sender.Send(data.ProcessID, "Process Ended:" + data.CommandLine, PROCESS_END);
     };
 }
Пример #29
0
        static TraceEventSession CreateKernelTraceEventSession()
        {
            var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName)
            {
                StopOnDispose = true
            };

            kernelSession.EnableKernelProvider(
                KernelTraceEventParser.Keywords.FileIOInit | KernelTraceEventParser.Keywords.FileIO
                | KernelTraceEventParser.Keywords.NetworkTCPIP | KernelTraceEventParser.Keywords.AdvancedLocalProcedureCalls
                );

            return(kernelSession);
        }
        /// <summary>
        /// Turning on providers and creating the file
        /// </summary>
        static void DataCollection(string dataFileName)
        {
            Out.WriteLine("Collecting 10 seconds of kernel and CLR events to a file, and then printing.");
            Out.WriteLine();
            Out.WriteLine("Start a .NET program while monitoring to see some events!");
            Out.WriteLine();
            if (TraceEventSession.IsElevated() != true)
            {
                Out.WriteLine("Must be elevated (Admin) to run this program.");
                Debugger.Break();
                return;
            }

            // Create one user mode session and one kernel mode session
            Out.WriteLine("Creating a file mode session");
            using (var session = new TraceEventSession("MonitorKernelAndClrEventsSession", dataFileName))
            {
                // Set up Ctrl-C to stop both user mode and kernel mode sessions
                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs cancelArgs)
                {
                    Out.WriteLine("Insuring all ETW sessions are stopped.");
                    session.Stop(true);         // true means don't throw on error
                    // Since we don't cancel the Ctrl-C we will terminate the process as normal for Ctrl-C
                    Out.WriteLine("OnCtrl C handler ending.");
                };

                // 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);

                // Enable the events we care about for the CLR (in the user session).
                // unlike the kernel session, you can call EnableProvider on other things too.  
                // For this instant the session will buffer any incoming events.  
                session.EnableProvider(
                    ClrTraceEventParser.ProviderGuid,
                    TraceEventLevel.Informational,
                    (ulong)(ClrTraceEventParser.Keywords.Default));

                Out.WriteLine("Collecting data for 10 seconds (run a .Net program to generate events).");
                Thread.Sleep(10000);

                Out.WriteLine("Stopping sessions");
            }    // Using clauses will insure that session are disposed (and thus stopped) before Main returns.  

        }
Пример #31
0
        public static void Listen()
        {
            var session = new TraceEventSession(KernelTraceEventParser.KernelSessionName);

            session.StopOnDispose = true;
            session.EnableKernelProvider(KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process);

            session.Source.Kernel.ProcessStart += (ProcessTraceData data) => {
                ProcessCreated?.Invoke(data);
            };
            session.Source.Kernel.ProcessStop += (ProcessTraceData data) => {
                ProcessExited?.Invoke(data);
            };
            new Thread(() => session.Source.Process()).Start();
        }
Пример #32
0
        static void Main(string[] args)
        {
            var processes = Process.GetProcesses().Select(p => new ProcessInfo {
                Name = p.ProcessName,
                Id   = p.Id
            }).ToDictionary(p => p.Id);

            using (var session = new TraceEventSession(Environment.OSVersion.Version.Build >= 9200 ? "MyKernelSession" : KernelTraceEventParser.KernelSessionName)) {
                session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.ImageLoad);
                var parser = session.Source.Kernel;

                parser.ProcessStart += e => {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Process {e.ProcessID} ({e.ProcessName}) Created by {e.ParentID}: {e.CommandLine}");
                    processes.Add(e.ProcessID, new ProcessInfo {
                        Id = e.ProcessID, Name = e.ProcessName
                    });
                };
                parser.ProcessStop += e => {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Process {e.ProcessID} {TryGetProcessName(e)} Exited");
                };

                parser.ImageLoad += e => {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    var name = TryGetProcessName(e);
                    Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Image Loaded: {e.FileName} into process {e.ProcessID} ({name}) Size=0x{e.ImageSize:X}");
                };

                parser.ImageUnload += e => {
                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                    var name = TryGetProcessName(e);
                    Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Image Unloaded: {e.FileName} from process {e.ProcessID} ({name})");
                };

                Task.Run(() => session.Source.Process());
                Thread.Sleep(TimeSpan.FromSeconds(60));
            }

            string TryGetProcessName(TraceEvent evt)
            {
                if (!string.IsNullOrEmpty(evt.ProcessName))
                {
                    return(evt.ProcessName);
                }
                return(processes.TryGetValue(evt.ProcessID, out var info) ? info.Name : string.Empty);
            }
        }
Пример #33
0
        public static void Run()
        {
            var monitoringTimeSec = 10;

            Out.WriteLine("******************** ModuleLoadMonitor DEMO ********************");
            Out.WriteLine("Monitoring DLL Loads and Process Starts/Stops system wide");
            Out.WriteLine("The monitor will run for a maximum of {0} seconds", monitoringTimeSec);
            Out.WriteLine("Press Ctrl-C to stop monitoring early.");
            Out.WriteLine();
            Out.WriteLine("Start a program to see some events!");
            Out.WriteLine();
            if (TraceEventSession.IsElevated() != true)
            {
                Out.WriteLine("Must be elevated (Admin) to run this program.");
                Debugger.Break();
                return;
            }

            // Start the session as a real time monitoring session,  
            // Before windows 8, there is a restriction that if you wanted kernel events you must name your session 
            // 'NT Kernel Logger' (the value of KernelSessionName) and there can only be one such session and no
            // other ETW providers can be enabled for that session (thus you need two sessions if you want both
            // kernel and non-kernel events (fixed in Win 8).  We want this to work on Win 7 so we live with those
            // restrictions.   
            using (TraceEventSession session = new TraceEventSession(KernelTraceEventParser.KernelSessionName))
            {
                /* BY DEFAULT ETW SESSIONS SURVIVE THE DEATH OF THE PROESS THAT CREATES THEM! */
                // Unlike most other resources on the system, ETW session live beyond the lifetime of the 
                // process that created them.   This is very useful in some scenarios, but also creates the 
                // very real possibility of leaving 'orphan' sessions running.  
                //
                // To help avoid this by default TraceEventSession sets 'StopOnDispose' so that it will stop
                // the ETW session if the TraceEventSession dies.   Thus executions that 'clean up' the TraceEventSession
                // will clean up the ETW session.   This covers many cases (including throwing exceptions)
                //  
                // However if the process is killed manually (including control C) this cleanup will not happen.  
                // Thus best practices include
                //
                //     * Add a Control C handler that calls session.Dispose() so it gets cleaned up in this common case
                //     * use the same session name run-to-run so you don't create many orphans. 
                //
                // By default TraceEventSessions are in 'create' mode where it assumes you want to create a new session.
                // In this mode if a session already exists, it is stopped and the new one is created.   
                // 
                // Here we install the Control C handler.   
                Console.CancelKeyPress += new ConsoleCancelEventHandler((object sender, ConsoleCancelEventArgs cancelArgs) =>
                {
                    Out.WriteLine("Control C pressed");     // Note that if you hit Ctrl-C twice rapidly you may be called concurrently.  
                    session.Dispose();                          // Note that this causes Process() to return.  
                    cancelArgs.Cancel = true;                   // This says don't abort, since Process() will return we can terminate nicely.   
                });

                // Enable the Kernel events that we want.   At this point data is being collected (but being buffered since we are not reading it)
                // See KernelTraceEventParser.Keywords for what else can be turned on and KernelTraceEventParser for a description
                // of the events that you get when you turn on the various kernel keywords.   Many kernel events will also log a stack
                // when they fire see EnableKernelProvider for more on that.  
                session.EnableKernelProvider(KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process);

                // .Source will auto-create a TraceEventSource reading the data from the session
                // .Kernel will auto-create a KernelTraceEventParser getting its events from the source
                // .ImageLoad is an event that you can subscribe to that will be called back when Image load events happen (complete with parsed event)
                session.Source.Kernel.ImageLoad += delegate(ImageLoadTraceData data)
                {
                    Out.WriteLine("Process {0,16} At 0x{1,8:x} Loaded {2}", data.ProcessName, data.ImageBase, data.FileName);
                };
                //  Subscribe to more events (process start) 
                session.Source.Kernel.ProcessStart += delegate(ProcessTraceData data)
                {
                    Out.WriteLine("Process Started {0,6} Parent {1,6} Name {2,8} Cmd: {3}",
                        data.ProcessID, data.ParentID, data.ProcessName, data.CommandLine);
                };
                //  Subscribe to more events (process end)
                session.Source.Kernel.ProcessStop += delegate(ProcessTraceData data)
                {
                    Out.WriteLine("Process Ending {0,6} ", data.ProcessID);
                };

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

                // Start listening for events, will end if session.Source.StopProcessing() is called or session.Dispose() is called.  
                // Here we never do either of these and thus will only stop when Ctrl-C is hit (but it will clean up because of 
                // our control C handler). 
                session.Source.Process();
                timer.Dispose();    // Done with the timer.  
            }
            Out.WriteLine("Stopping monitor");
        }
        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.  
        }
        public static void Run()
        {
            var monitoringTimeSec = 10;

            Out.WriteLine("******************** KernelAndClrMonitor DEMO (Win7) ********************");
            Out.WriteLine("Printing both Kernel and CLR (user mode) events simultaneously");
            Out.WriteLine("The monitor will run for a maximum of {0} seconds", monitoringTimeSec);
            Out.WriteLine("Press Ctrl-C to stop monitoring early.");
            Out.WriteLine();
            Out.WriteLine("Start a .NET program to see some events!");
            Out.WriteLine();
            if (TraceEventSession.IsElevated() != true)
            {
                Out.WriteLine("Must be elevated (Admin) to run this program.");
                Debugger.Break();
                return;
            }

            // Set up Ctrl-C to stop both user mode and kernel mode sessions
            Console.CancelKeyPress += (object sender, ConsoleCancelEventArgs cancelArgs) =>
            {
                StopSessions();
                cancelArgs.Cancel = true;
            };

            // Note that because there are different sessions, the events may not be printed
            // in time order since the different sessions may flush their buffers at different 
            // times.   If you care, you must buffer the events and order them by event 
            // timestamp.   Note that the timestamps however ARE accurate.  
            Out.WriteLine("Setup up threads to process the events");

            // start processing kernel events on a thread pool thread
            var task1 = Task.Run(() =>
            {
                // Note that TraceEventSession and EtwTraceEventParser are IN GENERAL NOT THREADSAFE, 
                // Normally this is not a hardship you just set up the session TraceDispacher on one
                // thread.  It is OK to call a session's Dispose() and 'Enable and Disable provider APIS
                // from another thread, but things associated with ETWTraceEventSource and TraceEventParsers
                // should all be on the same thread.  
                Out.WriteLine("Kernel event Thread Starting");
                Out.WriteLine("Enabling Image load, thread and process kernel events.");
                using (s_kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName))
                {
                    // Enable the events we care about for the kernel in the kernel session
                    // For this instant the session will buffer any incoming events.  
                    // If you only have to run on Win8 systems you can use one session for both.  
                    // Here we turn in process, thread and Image load events.  
                    s_kernelSession.EnableKernelProvider(
                        KernelTraceEventParser.Keywords.ImageLoad |
                        KernelTraceEventParser.Keywords.Process |
                        KernelTraceEventParser.Keywords.Thread);

                    // You should do all processing from a single source on a single thread.
                    // Thus call calls to .Source, or Process() should be on the same thread.  
                    s_kernelSession.Source.Kernel.All += Print;
#if DEBUG
                    // in debug builds it is useful to see any unhandled events because they could be bugs. 
                    s_kernelSession.Source.UnhandledEvents += Print;
#endif
                    // process events until Ctrl-C is pressed

                    Out.WriteLine("Waiting on kernel events.");
                    s_kernelSession.Source.Process();
                }
                Out.WriteLine("Thread 1 dieing");
            });

            // start processing CLR events on a thread pool thread
            var task2 = Task.Run(() =>
            {
                // Note that TraceEventSession and EtwTraceEventParser are IN GENERAL NOT THREADSAFE, 
                // Normally this is not a hardship you just set up the session TraceDispacher on one
                // thread.  It is OK to call a session's Dispose() and 'Enable and Disable provider APIS
                // from another thread, but things associated with ETWTraceEventSource and TraceEventParsers
                // should all be on the same thread.  
                using (s_userSession = new TraceEventSession("MonitorKernelAndClrEventsSession"))
                {
                    Out.WriteLine("Enabling CLR GC and Exception events.");
                    // Enable the events we care about for the CLR (in the user session).
                    // unlike the kernel session, you can call EnableProvider on other things too.  
                    // For this instant the ;session will buffer any incoming events.  
                    s_userSession.EnableProvider(
                        ClrTraceEventParser.ProviderGuid,
                        TraceEventLevel.Informational,
                        (ulong)(ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.Exception));

                    // s_userSession.Source.Clr.GCHeapStats += (GCHeapStatsTraceData data) => Out.WriteLine(" ", data.GenerationSize0);

                    Out.WriteLine("User event Thread  Starting");
                    s_userSession.Source.Clr.All += Print;
#if DEBUG
                    // in debug builds it is useful to see any unhandled events because they could be bugs. 
                    s_userSession.Source.UnhandledEvents += Print;
#endif
                    // process events until Ctrl-C is pressed or timeout expires
                    Out.WriteLine("Waiting on user events.");
                    s_userSession.Source.Process();
                }
                Out.WriteLine("Thread 2 dieing");
            });

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

            // Wait until tasks are complete 
            Out.WriteLine("Waiting for processing tasks to complete");
            Task.WaitAll(task1, task2);
            Out.WriteLine("Monitoring stopped");
            timer.Dispose();
        }
        public static void Run()
        {
            var 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;
            }

            Out.WriteLine("******************** KernelAndClrMonitor DEMO (Win 8) ********************");
            Out.WriteLine("Printing both Kernel and CLR (user mode) events simultaneously");
            Out.WriteLine("The monitor will run for a maximum of {0} seconds", monitoringTimeSec);
            Out.WriteLine("Press Ctrl-C to stop monitoring early.");
            Out.WriteLine();
            Out.WriteLine("Start a .NET program to see some events!");
            Out.WriteLine();
            if (TraceEventSession.IsElevated() != true)
            {
                Out.WriteLine("Must be elevated (Admin) to run this program.");
                Debugger.Break();
                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;
            };

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

            // 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("MonitorKernelAndClrEventsSession"))
            {
                // 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.  
                Out.WriteLine("Enabling Image load, Process and Thread events.");
                session.EnableKernelProvider(
                    KernelTraceEventParser.Keywords.ImageLoad |
                    KernelTraceEventParser.Keywords.Process |
                    KernelTraceEventParser.Keywords.Thread);

                // Subscribe the events of interest.   In this case we just print all events.  
                session.Source.Kernel.All += Print;

                Out.WriteLine("Enabling CLR GC and Exception events.");
                // Enable the events we care about for the CLR (in the user session).
                // unlike the kernel session, you can call EnableProvider on other things too.  
                // For this instant the ;session will buffer any incoming events.  
                session.EnableProvider(
                    ClrTraceEventParser.ProviderGuid,
                    TraceEventLevel.Informational,
                    (ulong)(ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.Exception));

                session.Source.Clr.All += Print;
#if DEBUG
                // in debug builds it is useful to see any unhandled events because they could be bugs. 
                session.Source.UnhandledEvents += Print;
#endif
                // process events until Ctrl-C is pressed or timeout expires
                Out.WriteLine("Waiting for Events.");
                session.Source.Process();
            }

            timer.Dispose();    // Turn off the timer.  
        }
        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);
        }
        /// <summary>
        /// CollectData doe will turn on logging of data from 'eventSourceName' to the file 'dataFileName'.
        /// It will then call EventGenerator.CreateEvents and wait 12 seconds for it to generate some data. 
        /// </summary>
        static void CollectData(string eventSourceName, string dataFileName)
        {

            // 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;
            }

            // As mentioned below, sessions can outlive the process that created them.  Thus you 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.  
            // 
            // In this case we tell the session to place the data in MonitorToFileData.etl.  
            var sessionName = "SimpleTraceLogSession";
            Out.WriteLine("Creating a '{0}' session writing to {1}", sessionName, dataFileName);
            Out.WriteLine("Use 'logman query -ets' to see active sessions.");
            Out.WriteLine("Use 'logman stop {0} -ets' to manually stop orphans.", sessionName);
            using (var session = new TraceEventSession(sessionName, dataFileName))      // Since we give it a file name, the data goes there. 
            using (var kernelSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName, Path.ChangeExtension(dataFileName, ".kernel.etl")))
            {
                /* BY DEFAULT ETW SESSIONS SURVIVE THE DEATH OF THE PROESS THAT CREATES THEM! */
                // Unlike most other resources on the system, ETW session live beyond the lifetime of the 
                // process that created them.   This is very useful in some scenarios, but also creates the 
                // very real possibility of leaving 'orphan' sessions running.  
                //
                // To help avoid this by default TraceEventSession sets 'StopOnDispose' so that it will stop
                // the ETW session if the TraceEventSession dies.   Thus executions that 'clean up' the TraceEventSession
                // will clean up the ETW session.   This covers many cases (including throwing exceptions)
                //  
                // However if the process is killed manually (including control C) this cleanup will not happen.  
                // Thus best practices include
                //
                //     * Add a Control C handler that calls session.Dispose() so it gets cleaned up in this common case
                //     * use the same session name run-to-run so you don't create many orphans. 
                //
                // By default TraceEventSessions are in 'create' mode where it assumes you want to create a new session.
                // In this mode if a session already exists, it is stopped and the new one is created.   
                // 
                // Here we install the Control C handler.   It is OK if Dispose is called more than once.  
                Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { session.Dispose(); kernelSession.Dispose(); };

                // Enable kernel events.  
                kernelSession.EnableKernelProvider(KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread);

                // Enable my provider, you can call many of these on the same session to get events from other providers  

                // Turn on the eventSource given its name.   
                // Note we turn on Verbose level all keywords (ulong.MaxValue == 0xFFF....) and turn on stacks for 
                // this provider (for all events, until Windows 8.1 you can only turn on stacks for every event 
                // for a particular provider or no stacks)
                var options = new TraceEventProviderOptions() { StacksEnabled = true };
                var restarted = session.EnableProvider(eventSourceName, TraceEventLevel.Verbose, ulong.MaxValue, options);
                if (restarted)      // Generally you don't bother with this warning, but for the demo we do.  
                    Out.WriteLine("The session {0} was already active, it has been restarted.", sessionName);

                // We also turn on CLR events because we need them to decode Stacks and we also get exception events (and their stacks)
                session.EnableProvider(ClrTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)ClrTraceEventParser.Keywords.Default);

                // Start another thread that Causes MyEventSource to create some events
                // Normally this code as well as the EventSource itself would be in a different process.  
                EventGenerator.CreateEvents();

                // Also generate some exceptions so we have interesting stacks to look at
                Thread.Sleep(100);
                EventGenerator.GenerateExceptions();

                Out.WriteLine("Waiting 12 seconds for events to come in.");
                Thread.Sleep(12000);

                // Because the process in question (this process) lives both before and after the time the events were 
                // collected, we don't have complete information about JIT compiled methods in that method.   There are 
                // some methods that were JIT compiled before the session started (e.g. SimpleTraceLog.Main) for which
                // we do not have information.   We collect this by forcing a CLR 'rundown' which will dump method information
                // for JIT compiled methods that were not present.  If you know that the process of interest ends before
                // data collection ended or that data collection started before the process started, then this is not needed.  
                Out.WriteLine("Forcing rundown of JIT methods.");
                var rundownFileName = Path.ChangeExtension(dataFileName, ".clrRundown.etl");
                using (var rundownSession = new TraceEventSession(sessionName + "Rundown", rundownFileName))
                {
                    rundownSession.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)ClrRundownTraceEventParser.Keywords.Default);
                    // Poll until 2 second goes by without growth.  
                    for (var prevLength = new FileInfo(rundownFileName).Length; ; )
                    {
                        Thread.Sleep(2000);
                        var newLength = new FileInfo(rundownFileName).Length;
                        if (newLength == prevLength) break;
                        prevLength = newLength;
                    }
                }
                Out.WriteLine("Done with rundown.");
            }

            Out.WriteLine("Merging the raw files into a single '{0}' file.", dataFileName);
            TraceEventSession.MergeInPlace(dataFileName, Out);
            Out.WriteLine("Merge complete.");
        }