コード例 #1
0
        public AllocationTickMemoryProfiler(TraceEventSession session, int pid, ProcessAllocationInfo allocations, bool verbose = false)
        {
            if (session == null)
            {
                throw new NullReferenceException(nameof(session));
            }
            _session = session;

            if (allocations == null)
            {
                throw new NullReferenceException(nameof(allocations));
            }
            _allocations = allocations;

            _pid     = pid;
            _verbose = verbose;

            _symbolLookupMessages = new StringWriter();

            // 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 = new SymbolReader(_symbolLookupMessages, symbolPath.ToString());

            // By default the symbol reader will NOT read PDBs from 'unsafe' locations (like next to the EXE)
            // because hackers might make malicious PDBs. If you wish ignore this threat, you can override this
            // check to always return 'true' for checking that a PDB is 'safe'.
            _symbolReader.SecurityCheck = (path => true);
        }
コード例 #2
0
        public CpuSampleProfilerBase()
        {
            _symbolLookupMessages = new StringWriter();

            // 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 = new SymbolReader(_symbolLookupMessages, symbolPath.ToString());

            // By default the symbol reader will NOT read PDBs from 'unsafe' locations (like next to the EXE)
            // because hackers might make malicious PDBs. If you wish ignore this threat, you can override this
            // check to always return 'true' for checking that a PDB is 'safe'.
            _symbolReader.SecurityCheck = (path => true);
        }
コード例 #3
0
        public static void Run()
        {
            var monitoringTimeSec = 10;

            Out.WriteLine("******************** RealTimeTraceLog DEMO (win8) ********************");
            Out.WriteLine("This program Shows how to use the real-time support in TraceLog");
            Out.WriteLine("We do this by showing how to monitor exceptions in real time ");
            Out.WriteLine();
            Out.WriteLine("This code depends on a Feature of Windows 8.1 (combined user and kernel sessions)");
            Out.WriteLine();
            Out.WriteLine("Note that this support is currently experimental and subject to change");
            Out.WriteLine();
            Out.WriteLine("Monitoring .NET Module load and Exception events (with stacks).");
            Out.WriteLine("Run some managed code (ideally that has exceptions) while the monitor is running.");
            Out.WriteLine();

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

            TraceEventSession session = null;

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

            // Cause an exception to be thrown a few seconds in (so we have something interesting to look at)
            var exceptionGeneationTask = Task.Factory.StartNew(delegate
            {
                Thread.Sleep(3000);
                ThrowException();
            });

            Timer timer = null;

            // Create the new session to receive the events.
            // Because we are on Win 8 this single session can handle both kernel and non-kernel providers.
            using (session = new TraceEventSession("TraceLogSession"))
            {
                // Enable the events we care about for the kernel
                // For this instant the session will buffer any incoming events.
                // Enabling kernel events must be done before anything else.
                // This will fail on Win7.
                //
                // Note that if you turn on the KernelTraceEventParser.Keywords.Profile, you can also get stacks for CPU sampling
                // (every millisecond).  (You can use the traceLogSource.Kernel.PerfInfoSample callback).
                Out.WriteLine("Enabling Image load, Process and Thread events.  These are needed to look up native method names.");
                session.EnableKernelProvider(
                    // KernelTraceEventParser.Keywords.Profile |            // If you want CPU sampling events
                    // KernelTraceEventParser.Keywords.ContextSwitch |      // If you want context switch events
                    // KernelTraceEventParser.Keywords.Thread |             // If you want context switch events you also need thread start events.
                    KernelTraceEventParser.Keywords.ImageLoad |
                    KernelTraceEventParser.Keywords.Process,   /****** The second parameter indicates which kernel events should have stacks *****/
                    // KernelTraceEventParser.Keywords.ImageLoad |          // If you want Stacks image load (load library) events
                    // KernelTraceEventParser.Keywords.Profile |            // If you want Stacks for CPU sampling events
                    // KernelTraceEventParser.Keywords.ContextSwitch |      // If you want Stacks for context switch events
                    KernelTraceEventParser.Keywords.None
                    );

                Out.WriteLine("Enabling CLR Exception and Load events (and stack for those events)");
                // We are monitoring exception events (with stacks) and module load events (with stacks)
                session.EnableProvider(
                    ClrTraceEventParser.ProviderGuid,
                    TraceEventLevel.Informational,
                    (ulong)(ClrTraceEventParser.Keywords.Jit |                       // Turning on JIT events is necessary to resolve JIT compiled code
                            ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks
                            ClrTraceEventParser.Keywords.Loader |                    // You must include loader events as well to resolve JIT compiled code.
                            ClrTraceEventParser.Keywords.Exception |                 // We want to see the exception events.
                            ClrTraceEventParser.Keywords.Stack));                    // And stacks on all CLR events where it makes sense.

                // The CLR events turned on above will let you resolve JIT compiled code as long as the JIT compilation
                // happens AFTER the session has started.   To handle the case for JIT compiled code that was already
                // compiled we need to tell the CLR to dump 'Rundown' events for all existing JIT compiled code.  We
                // do that here.
                Out.WriteLine("Enabling CLR Events to 'catch up' on JIT compiled code in running processes.");
                session.EnableProvider(ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Informational,
                                       (ulong)(ClrTraceEventParser.Keywords.Jit |                       // We need JIT events to be rundown to resolve method names
                                               ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | // This is needed if you want line number information in the stacks
                                               ClrTraceEventParser.Keywords.Loader |                    // As well as the module load events.
                                               ClrTraceEventParser.Keywords.StartEnumeration));         // This indicates to do the rundown now (at enable time)

                // Because we care about symbols in native code or NGEN images, we need a SymbolReader to decode them.

                // There is a lot of messages associated with looking up symbols, but we don't want to clutter up
                // The output by default, so we save it to an internal buffer you can ToString in debug code.
                // A real app should make this available somehow to the user, because sooner or later you DO need it.
                TextWriter SymbolLookupMessages = new StringWriter();
                // TextWriter SymbolLookupMessages = Out;           // If you want the symbol debug spew to go to the output, use this.

                // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable.  However you can override
                // if you wish by passing it to the SymbolReader constructor.  Since we want this to work even if you
                // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/
                var          symbolPath   = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath);
                SymbolReader symbolReader = new SymbolReader(SymbolLookupMessages, symbolPath.ToString());

                Out.WriteLine("Open a real time TraceLog session (which understands how to decode stacks).");
                using (TraceLogEventSource traceLogSource = TraceLog.CreateFromTraceEventSession(session))
                {
                    // We use this action in the particular callbacks below.  Basically we pass in a symbol reader so we can decode the stack.
                    // Often the symbol reader is a global variable instead.
                    Action <TraceEvent> PrintEvent = ((TraceEvent data) => Print(data, symbolReader));

                    // We will print Exceptions and ModuleLoad events. (with stacks).
                    traceLogSource.Clr.ExceptionStart   += PrintEvent;
                    traceLogSource.Clr.LoaderModuleLoad += PrintEvent;
                    // traceLogSource.Clr.All += PrintEvent;

                    // If you want to see stacks for various other kernel events, uncomment these (you also need to turn on the events above)
                    traceLogSource.Kernel.PerfInfoSample += ((SampledProfileTraceData data) => Print(data, symbolReader));
                    // traceLogSource.Kernel.ImageLoad += ((ImageLoadTraceData data) => Print(data, symbolReader));

                    // process events until Ctrl-C is pressed or timeout expires
                    Out.WriteLine("Waiting {0} sec for Events.  Run managed code to see data. ", monitoringTimeSec);
                    Out.WriteLine("Keep in mind there is a several second buffering delay");

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

                    traceLogSource.Process();
                }
            }
            Out.WriteLine("Finished");
            if (timer != null)
            {
                timer.Dispose();    // Turn off the timer.
            }
        }
コード例 #4
0
        public ICallTreeDataProvider Get()
        {
            var queryString = this.httpRequest.Query;

            string filename  = queryString["filename"];
            string stacktype = queryString["stacktype"];

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }

            if (string.IsNullOrEmpty(stacktype))
            {
                throw new ArgumentNullException("stacktype");
            }

            /* symbols and sources related parameters */
            string     sympathStr         = (string)queryString["sympath"] ?? SymbolPath.MicrosoftSymbolServerPath;
            SymbolPath symPath            = new SymbolPath(sympathStr);
            string     defaultSymbolCache = symPath.DefaultSymbolCache();

            // Normalize the symbol path.
            symPath    = symPath.InsureHasCache(defaultSymbolCache);
            sympathStr = symPath.ToString();

            string srcpath = (string)queryString["srcpath"];
            //TODO FIX NOW: Dont spew to the Console, send it back to the client.
            SymbolReader symbolReader = new SymbolReader(Console.Out, sympathStr);

            if (srcpath != null)
            {
                symbolReader.SourcePath = srcpath;
            }

            string modulePatStr = (string)queryString["symLookupPats"] ?? @"^(clr|ntoskrnl|ntdll|.*\.ni)";

            /* filtering parameters */
            string start     = (string)queryString["start"] ?? string.Empty;
            string end       = (string)queryString["end"] ?? string.Empty;
            string incpats   = (string)queryString["incpats"] ?? string.Empty;
            string excpats   = (string)queryString["excpats"] ?? string.Empty;
            string foldpats  = (string)queryString["foldpats"] ?? string.Empty;
            string grouppats = (string)queryString["grouppats"] ?? string.Empty;
            string foldpct   = (string)queryString["foldpct"] ?? string.Empty;
            string find      = (string)queryString["find"] ?? string.Empty;

            EtlxFile etlxFile;

            // Do it twice so that XXX.etl.zip becomes XXX.
            string etlxFilePath = Path.ChangeExtension(Path.ChangeExtension(filename, null), ".etlx");

            lock (this.etlxCache)
            {
                if (this.etlxCache.TryGetValue(filename, out etlxFile))
                {
                    if (etlxFile == null)
                    {
                        throw new ArgumentNullException("etlxFile");
                    }
                }
                else
                {
                    etlxFile = new EtlxFile(filename)
                    {
                        Pending = true
                    };
                    this.etlxCache.Set(filename, etlxFile, this.cacheExpirationTime);
                }
            }

            lock (etlxFile)
            {
                if (etlxFile.Pending)
                {
                    if (!File.Exists(etlxFilePath))
                    {
                        // if it's a zip file
                        if (string.Equals(Path.GetExtension(filename), ".zip", StringComparison.OrdinalIgnoreCase))
                        {
                            //TODO FIX NOW: Dont spew to the Console, send it back to the client.
                            ZippedETLReader reader = new ZippedETLReader(filename, Console.Out);
                            reader.SymbolDirectory = defaultSymbolCache;
                            reader.EtlFileName     = Path.ChangeExtension(etlxFilePath, etlExtension);
                            reader.UnpackAchive();
                            TraceLog.CreateFromEventTraceLogFile(reader.EtlFileName, etlxFilePath);
                        }
                        else
                        {
                            TraceLog.CreateFromEventTraceLogFile(filename, etlxFilePath);
                        }
                    }

                    etlxFile.TraceLog = TraceLog.OpenOrConvert(etlxFilePath);
                    etlxFile.Pending  = false;
                }

                Regex modulePat = new Regex(modulePatStr, RegexOptions.IgnoreCase);
                foreach (var moduleFile in etlxFile.TraceLog.ModuleFiles)
                {
                    if (modulePat.IsMatch(moduleFile.Name))
                    {
                        etlxFile.TraceLog.CodeAddresses.LookupSymbolsForModule(symbolReader, moduleFile);
                    }
                }
            }

            StackViewerSession stackViewerSession;

            lock (this.stackViewerSessionCache)
            {
                var filterParams = new FilterParams {
                    Name = filename + stacktype, StartTimeRelativeMSec = start, EndTimeRelativeMSec = end, MinInclusiveTimePercent = foldpct, FoldRegExs = foldpats, IncludeRegExs = incpats, ExcludeRegExs = excpats, GroupRegExs = grouppats
                };
                var keyBuilder = new StringBuilder();
                keyBuilder.Append(filterParams.Name).Append("?" + filterParams.StartTimeRelativeMSec).Append("?" + filterParams.EndTimeRelativeMSec).Append("?" + filterParams.MinInclusiveTimePercent).Append("?" + filterParams.FoldRegExs).Append("?" + filterParams.IncludeRegExs).Append("?" + filterParams.ExcludeRegExs).Append("?" + filterParams.GroupRegExs).Append("?" + find);

                var stackViewerKey = keyBuilder.ToString();
                if (this.stackViewerSessionCache.TryGetValue(stackViewerKey, out stackViewerSession))
                {
                    if (stackViewerSession == null)
                    {
                        throw new ArgumentNullException("stackViewerSession");
                    }
                }
                else
                {
                    stackViewerSession = new StackViewerSession(filename, stacktype, etlxFile.TraceLog, filterParams, symbolReader);
                    this.stackViewerSessionCache.Set(stackViewerKey, stackViewerSession, cacheExpirationTime);
                }
            }

            lock (stackViewerSession)
            {
                if (stackViewerSession.Pending)
                {
                    stackViewerSession.InitializeDataProvider();
                    stackViewerSession.Pending = false;
                }
            }

            return(stackViewerSession.GetDataProvider());
        }
コード例 #5
0
        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.  
        }