private void ParseEvent(string[] parts)
        {
            if (_provider == "kernel")
            {
                string keyword = parts[0];
                KernelTraceEventParser.Keywords parsedKeyword;
                if (!Enum.TryParse(keyword, true, out parsedKeyword))
                {
                    throw new ArgumentException("Unrecognized kernel keyword: '" + keyword + "'.");
                }
                _kernelKeyword = parsedKeyword;
            }
            else if (_provider == "clr")
            {
                if (parts.Length != 2)
                {
                    throw new ArgumentException("CLR event specification must contain a keyword and an event name.");
                }

                string keyword   = parts[0];
                string eventName = parts[1];
                ClrTraceEventParser.Keywords parsedKeyword;
                if (!Enum.TryParse(keyword, true, out parsedKeyword))
                {
                    throw new ArgumentException("Unrecognized CLR keyword: '" + keyword + "'.");
                }
                _clrKeyword   = parsedKeyword;
                _clrEventName = eventName.ToLower();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Wire up parsing of CLR event data from the specified ETWTraceEventSource.
        /// </summary>
        /// <param name="eventSource">The ETWTraceEventSource from which to parse the data.</param>
        private void ParseClrTraceEvents(ETWTraceEventSource eventSource)
        {
            if (m_clrEvents == ClrTraceEventParser.Keywords.None)
            {
                return;
            }

            var clrTraceEventParser = new ClrTraceEventParser(eventSource);

            // iterate over each set bit, wiring up a callback to parse the data
            ulong eventBits = (ulong)m_clrEvents;
            int   bitPos    = 0;

            while (eventBits > 0)
            {
                // cycle through until a set bit is found
                while ((((ulong)eventBits) & (ulong)(1 << bitPos)) == 0)
                {
                    ++bitPos;
                    Debug.Assert(bitPos < 64);
                }

                var bitVal = (ulong)(1 << bitPos);

                // now strip it from eventBits and covert it to its enum value
                eventBits ^= bitVal;
                ClrTraceEventParser.Keywords clrEvent = (ClrTraceEventParser.Keywords)bitVal;

                // aggregate the high and low events if both are available (enabling both provides a more complete value)
                if ((clrEvent & ClrTraceEventParser.Keywords.GCSampledObjectAllocationHigh) == ClrTraceEventParser.Keywords.GCSampledObjectAllocationHigh ||
                    (clrEvent & ClrTraceEventParser.Keywords.GCSampledObjectAllocationLow) == ClrTraceEventParser.Keywords.GCSampledObjectAllocationLow ||
                    (clrEvent & ClrTraceEventParser.Keywords.GCAllObjectAllocation) == ClrTraceEventParser.Keywords.GCAllObjectAllocation)
                {
                    if (!m_aed.ClrEventsData.ContainsKey(ClrPerfEvents.GCBytesAllocated))
                    {
                        m_aed.AddData(new EventDataScalarLong <ClrPerfEvents>(ClrPerfEvents.GCBytesAllocated));
                    }

                    var gcBytesAllocated = (EventDataScalarLong <ClrPerfEvents>)m_aed.ClrEventsData[ClrPerfEvents.GCBytesAllocated];

                    clrTraceEventParser.GCSampledObjectAllocation += delegate(GCSampledObjectAllocationTraceData data)
                    {
                        if (string.Compare(data.ProcessName, m_process, true) == 0)
                        {
                            gcBytesAllocated.Value += data.TotalSizeForTypeSample;
                            m_processFound          = true;
                        }
                    };
                }
                else
                {
                    Console.WriteLine("WARNING: CLR event {0} NYI for reporting.", clrEvent);
                }
            }
        }
        public TraceEventsReportGenerator(CommandLineOptions commandLineOptions)
        {
            if (!File.Exists(commandLineOptions.DataFile))
                throw new FileNotFoundException("Couldn't find the specified data file.", commandLineOptions.DataFile);

            m_testName = commandLineOptions.TestName;
            m_etlFile = commandLineOptions.DataFile;
            m_process = commandLineOptions.ProcessName;
            m_clrEvents = commandLineOptions.ClrEvents.Events;
            m_kernelEvents = commandLineOptions.KernelEvents;
        }
Beispiel #4
0
        public TraceEventsReportGenerator(CommandLineOptions commandLineOptions)
        {
            if (!File.Exists(commandLineOptions.DataFile))
            {
                throw new FileNotFoundException("Couldn't find the specified data file.", commandLineOptions.DataFile);
            }

            m_testName     = commandLineOptions.TestName;
            m_etlFile      = commandLineOptions.DataFile;
            m_process      = commandLineOptions.ProcessName;
            m_clrEvents    = commandLineOptions.ClrEvents.Events;
            m_kernelEvents = commandLineOptions.KernelEvents;
        }
        private void SetupProviders(TraceEventSession session, bool noSampling)
        {
            // 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)
            // Maybe a TraceEvent implementation details triggered when a module (image) is loaded
            session.EnableKernelProvider(
                KernelTraceEventParser.Keywords.ImageLoad |
                KernelTraceEventParser.Keywords.Process,
                KernelTraceEventParser.Keywords.None
                );

            // The CLR source code indicates that the provider must be set before the monitored application starts
            // Note: no real difference between High and Low
            ClrTraceEventParser.Keywords eventsKeyword = noSampling
                ? ClrTraceEventParser.Keywords.GCSampledObjectAllocationLow | ClrTraceEventParser.Keywords.GCSampledObjectAllocationHigh
                : ClrTraceEventParser.Keywords.GCSampledObjectAllocationLow
            ;

            session.EnableProvider(
                ClrTraceEventParser.ProviderGuid,
                TraceEventLevel.Verbose,    // this is needed in order to receive GCSampledObjectAllocation event
                (ulong)(

                    eventsKeyword |

                    // required to receive the BulkType events that allows
                    // mapping between the type ID received in the allocation events
                    ClrTraceEventParser.Keywords.GCHeapAndTypeNames |
                    ClrTraceEventParser.Keywords.Type |

                    // events related to JITed methods
                    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.

                    // this is mandatory to get the callstacks in each CLR event payload.
                    ClrTraceEventParser.Keywords.Stack
                    )
                );

            // Note: ClrRundown is not needed because only new processes will be monitored
        }
Beispiel #6
0
        public static ClrEvents Revive(string key, string value)
        {
            // this reviver is a workaround due to a limitation in PowerArgs,
            // it doesn't support enums with an underlying type other than int.

            ClrTraceEventParser.Keywords events = ClrTraceEventParser.Keywords.None;

            var options = value.Split(new char[] { ',' });

            foreach (var option in options)
            {
                ClrTraceEventParser.Keywords result;
                var success = Enum.TryParse <ClrTraceEventParser.Keywords>(option, true, out result);
                if (!success)
                {
                    throw new ArgException(string.Format("Bad value '{0}' parsing CLR events.", option));
                }

                events |= result;
            }

            return(new ClrEvents(events));
        }
Beispiel #7
0
        private void SetupProviders(TraceEventSession session, bool noSampling)
        {
            // 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)
            // Maybe a TraceEvent implementation details triggered when a module (image) is loaded
            session.EnableKernelProvider(
                KernelTraceEventParser.Keywords.ImageLoad |
                KernelTraceEventParser.Keywords.Process,
                KernelTraceEventParser.Keywords.None
                );

            // The CLR source code indicates that the provider must be set before the monitored application starts
            // Note: no real difference between High and Low
            ClrTraceEventParser.Keywords eventsKeyword = noSampling
                ? ClrTraceEventParser.Keywords.GCSampledObjectAllocationLow | ClrTraceEventParser.Keywords.GCSampledObjectAllocationHigh
                : ClrTraceEventParser.Keywords.GCSampledObjectAllocationLow
            ;

            session.EnableProvider(
                ClrTraceEventParser.ProviderGuid,
                TraceEventLevel.Informational,    // this is needed in order to receive GCSampledObjectAllocation event
                (ulong)(

                    eventsKeyword |

                    // required to receive the BulkType events that allows
                    // mapping between the type ID received in the allocation events
                    ClrTraceEventParser.Keywords.GCHeapAndTypeNames |
                    ClrTraceEventParser.Keywords.Type |

                    // this is mandatory to get the callstacks in each CLR event payload.
                    ClrTraceEventParser.Keywords.Stack
                    )
                );
        }
Beispiel #8
0
        private void SetupCommandLine(CommandLineParser parser)
        {
            // #CommandLineDefinitions
            parser.ParameterSetsWhereQualifiersMustBeFirst = new string[] { "run", "UserCommand" };
            parser.NoDashOnParameterSets = true;

            parser.DefineOptionalQualifier("LogFile", ref LogFile, "Send messages to this file instead launching the GUI.  Intended for batch scripts and other automation.");

            // These apply to start, collect and run
            parser.DefineOptionalQualifier("BufferSize", ref BufferSizeMB, "The size the buffers (in MB) the OS should use to store events waiting to be written to disk."); // TODO remove eventually.
            parser.DefineOptionalQualifier("Circular", ref CircularMB, "Do Circular logging with a file size in MB.  Zero means non-circular.");                             // TODO remove eventually.
            parser.DefineOptionalQualifier("BufferSizeMB", ref BufferSizeMB, "The size the buffers (in MB) the OS should use to store events waiting to be written to disk.");
            parser.DefineOptionalQualifier("CircularMB", ref CircularMB, "Do Circular logging with a file size in MB.  Zero means non-circular.");
            parser.DefineOptionalQualifier("InMemoryCircularBuffer", ref InMemoryCircularBuffer, "Keeps the circular buffer in memory until the session is stopped.");
            parser.DefineOptionalQualifier("StackCompression", ref StackCompression, "Use stack compression (only on Win 8+) to make collected file smaller.");
            parser.DefineOptionalQualifier("MaxCollectSec", ref MaxCollectSec,
                                           "Turn off collection (and kill the program if perfView started it) after this many seconds. Zero means no timeout.");
            parser.DefineOptionalQualifier("StopOnPerfCounter", ref StopOnPerfCounter,
                                           "This is of the form CATEGORY:COUNTERNAME:INSTANCE OP NUM  where CATEGORY:COUNTERNAME:INSTANCE, identify " +
                                           "a performance counter (same as PerfMon), OP is either < or >, and NUM is a number.  " +
                                           "When that condition is true then collection will stop.  You can specify this qualifier more than once (logical OR).  See 'Stop Trigger' in the users guide for more.");
            parser.DefineOptionalQualifier("StopOnEventLogMessage", ref StopOnEventLogMessage,
                                           "Stop when an event log message that matches the given (ignore case) regular expression is written to the Windows 'Application' event log.  " +
                                           "You can specify a particular event log with the syntax eventLogName@RegExp.   Can be specified more than once (logical OR).");

            parser.DefineOptionalQualifier("StopOnEtwEvent", ref StopOnEtwEvent,
                                           "This is of the form PROVIDER/EVENTNAME;key1=value1;key2=value2... " +
                                           "This option is quite powerful, See the users guide for more details.");

            int StopOnRequestOverMsec   = 0;
            int StopOnGCSuspendOverMSec = 0;

            // These are basically special cases of the /StopOnEtwEvent
            parser.DefineOptionalQualifier("StopOnRequestOverMsec", ref StopOnRequestOverMsec,
                                           "Trigger a stop of a collect command if there is any IIS request that is longer than the given number of MSec.");
            parser.DefineOptionalQualifier("StopOnGCOverMsec", ref StopOnGCOverMsec,
                                           "Trigger a stop of a collect command if there is a .NET Garbage Collection (GC) is longer than the given number of MSec.");
            parser.DefineOptionalQualifier("StopOnGCSuspendOverMSec", ref StopOnGCSuspendOverMSec,
                                           "Trigger a stop of a collect command if there is a .NET Garbage Collection (GC) where suspending for the GC took over the given number of MSec.");
            parser.DefineOptionalQualifier("StopOnBGCFinalPauseOverMsec", ref StopOnBGCFinalPauseOverMsec,
                                           "Trigger a stop of a collect command if there is a background .NET Garbage Collection (GC) whose final pause is longer than the given number of MSec. To work correctly, " +
                                           "this requires that heap survival and movement tracking is not enabled.");
            parser.DefineOptionalQualifier("StopOnAppFabricOverMsec", ref StopOnAppFabricOverMsec,
                                           "Trigger a stop of a collect command if there is a AppFabric request is longer than the given number of MSec.");

            parser.DefineOptionalQualifier("StopOnException", ref StopOnException,
                                           "Where the text is a regular expression that will be used to match the full name and message of the .NET Exception thrown." +
                                           "The empty string represents any exception.");
            parser.DefineOptionalQualifier("StopOnGen2GC", ref StopOnGen2GC,
                                           "This will stop on any non-background Gen2 GC from the given process (can be a process ID or a process Name (exe file name without path or extension) or * (any process)");

            parser.DefineOptionalQualifier("Process", ref Process, "A process name (exe file name without directory or extension) or the Decimal Process ID.  " +
                                           "If used with the /StopOn* qualifiers using ETW events, will restrict events to only that process.");
            parser.DefineOptionalQualifier("DecayToZeroHours", ref DecayToZeroHours,
                                           "The trigger value used in StopOnPerfCounter or StopOn*OverMSec will decay to zero in this interval of time.");
            parser.DefineOptionalQualifier("MinSecForTrigger", ref MinSecForTrigger,
                                           "The number of seconds a perf Counter has to be above threshold before it is considered triggered.");
            parser.DefineOptionalQualifier("DelayAfterTriggerSec", ref DelayAfterTriggerSec,
                                           "Wait this number of seconds after a trigger before actually stopping the trace.");
            parser.DefineOptionalQualifier("CollectMultiple", ref CollectMultiple, "Collect Multiple instance (used in conjunction with StopTrigger).");
            parser.DefineOptionalQualifier("StartOnPerfCounter", ref StartOnPerfCounter,
                                           "This is of the form CATEGORY:COUNTERNAME:INSTANCE OP NUM  where CATEGORY:COUNTERNAME:INSTANCE, identify " +
                                           "a performance counter (same as PerfMon), OP is either < or >, and NUM is a number.  " +
                                           "When that condition is true then collection will start.  You can specify this qualifier more than once.  Search for 'MonitorPerfCounter' in the users guide for more.");
            parser.DefineOptionalQualifier("StopCommand", ref StopCommand,
                                           "If present this command is executed when a PerfView stops.  It is useful to stopping other tracing logic external to PerfView.");

            List <string> etwStopEvents = new List <string>();

            if (StopOnRequestOverMsec != 0)
            {
                etwStopEvents.Add("Microsoft-Windows-IIS/EventID(1);Level=Critical;TriggerMSec=" + StopOnRequestOverMsec);
            }
            if (StopOnGCSuspendOverMSec != 0)
            {
                etwStopEvents.Add("E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4/GC/SuspendEEStart;StopEvent=GC/SuspendEEStop;StartStopID=ThreadID;Keywords=0x1;TriggerMSec=" + StopOnGCSuspendOverMSec);
            }

            if (0 < etwStopEvents.Count)
            {
                if (StopOnEtwEvent != null)
                {
                    etwStopEvents.AddRange(StopOnEtwEvent);
                }
                StopOnEtwEvent = etwStopEvents.ToArray();
            }

            // Respect the /Process and /DecayToZeroHours options by tacking them on the end if they are not already present.
            if (StopOnEtwEvent != null && (Process != null || DecayToZeroHours != 0))
            {
                etwStopEvents.Clear();
                foreach (var stopEtwEvent in StopOnEtwEvent)
                {
                    var newStopEtwEvent = stopEtwEvent;
                    if (Process != null && !stopEtwEvent.Contains(";Process="))
                    {
                        newStopEtwEvent += ";Process=" + Process;
                    }

                    if (DecayToZeroHours != 0 && !stopEtwEvent.Contains(";DecayToZeroHours="))
                    {
                        newStopEtwEvent += ";DecayToZeroHours=" + DecayToZeroHours;
                    }
                    etwStopEvents.Add(newStopEtwEvent);
                }
                StopOnEtwEvent = etwStopEvents.ToArray();
            }

            parser.DefineOptionalQualifier("MonitorPerfCounter", ref MonitorPerfCounter,
                                           "This is of the form CATEGORY:COUNTERNAME:INSTANCE@NUM  where CATEGORY:COUNTERNAME:INSTANCE, identify " +
                                           "a performance counter (same as PerfMon), and NUM is a number representing seconds.  The @NUM part is " +
                                           "optional and defaults to 2.   The value of the performance counter is logged to the ETL file as an " +
                                           "event ever NUM seconds");
            parser.DefineOptionalQualifier("CpuSampleMSec", ref CpuSampleMSec,
                                           "The interval (MSec) between CPU samples (.125Msec min).");

            // These apply to Stop Collect and Run
            parser.DefineOptionalQualifier("Merge", ref Merge, "Do a merge after stopping collection.");
            parser.DefineOptionalQualifier("Zip", ref Zip, "Zip the ETL file (implies /Merge).");
            parser.DefineOptionalQualifier("Wpr", ref Wpr, "Make output mimic WPR (Windows Performance Recorder). Don't ZIP, make a .ngenpdbs directory.  " +
                                           "This also enables threadTime as well as user mode providers WPR would normally collect by default.   This option can also be used " +
                                           "On the unzip command.   See 'Working with WPA' in the help for more.");
            parser.DefineOptionalQualifier("NoRundown", ref NoRundown, "Don't request CLR Rundown events.");
            parser.DefineOptionalQualifier("NoNGenRundown", ref NoNGenRundown,
                                           "Don't do rundown of symbolic information in NGEN images (only needed pre V4.5).");
            parser.DefineOptionalQualifier("NoClrRundown", ref NoClrRundown,
                                           "Don't do rundown .NET (CLR) rundown information )(for symbolic name lookup).");
            parser.DefineOptionalQualifier("RundownTimeout", ref RundownTimeout,
                                           "Maximum number of seconds to wait for CLR rundown to complete.");
            parser.DefineOptionalQualifier("MinRundownTime", ref MinRundownTime,
                                           "Minimum number of seconds to wait for CLR rundown to complete.");
            parser.DefineOptionalQualifier("KeepAllEvents", ref KeepAllEvents,
                                           "A debug option to keep all events, even symbolic rundown events.");
            parser.DefineOptionalQualifier("MaxEventCount", ref MaxEventCount, "Limits the total number of events.  " +
                                           "Useful for trimming large ETL files. 1M typically yields 300-400 Meg of data considered.");
            parser.DefineOptionalQualifier("SkipMSec", ref SkipMSec, "Skips the first N MSec of the trace.  " +
                                           "Useful for trimming large ETL files in conjunction with the /MaxEventCount qualifier.");

            parser.DefineOptionalQualifier("CpuCounters", ref CpuCounters,
                                           "A comma separated list of hardware CPU counters specifications NAME:COUNT to turn on.  " +
                                           "See Users guide for details.  See ListCpuCounters for available sources (Win8 only)");

            parser.DefineOptionalQualifier("Providers", ref Providers,
                                           "Additional providers.  This is comma separated list of ProviderGuid:Keywords:Level:Stack specs.  " +
                                           "This qualifier has the same syntax as the Additional Providers TextBox in the collection window.  " +
                                           " See help on that for more.");

            string[] onlyProviders = null;
            parser.DefineOptionalQualifier("OnlyProviders", ref onlyProviders,
                                           "Like the Providers qualifier, but also turns off the default Kernel and CLR providers.");
            if (onlyProviders != null)
            {
                // Allow stack traces to work if 'stacks' was specified.
                bool hasStacks = false;
                bool hasTpl    = false;
                foreach (var provider in onlyProviders)
                {
                    if (0 <= provider.IndexOf(":stack", StringComparison.OrdinalIgnoreCase))
                    {
                        hasStacks = true;
                    }
                    if (provider.StartsWith(".NETTasks", StringComparison.OrdinalIgnoreCase))
                    {
                        hasTpl = true;
                    }
                }

                if (hasStacks)
                {
                    KernelEvents = KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread | KernelTraceEventParser.Keywords.ImageLoad;
                    ClrEvents    = ClrTraceEventParser.Keywords.Jit | ClrTraceEventParser.Keywords.Loader;
                }
                else
                {
                    KernelEvents  = KernelTraceEventParser.Keywords.None;
                    ClrEvents     = ClrTraceEventParser.Keywords.None;
                    NoNGenRundown = true;   // We still do normal rundown because EventSource rundown is done there.
                    NoClrRundown  = true;
                }
                Providers = onlyProviders;
                if (!hasTpl)
                {
                    Providers = new string[onlyProviders.Length + 1];
                    Array.Copy(onlyProviders, Providers, onlyProviders.Length);
                    Providers[onlyProviders.Length] = ".NETTasks:0x80";     // Turn on causality tracking.
                }
            }
            parser.DefineOptionalQualifier("ThreadTime", ref ThreadTime, "Shortcut for turning on context switch and readyThread events");
            if (ThreadTime)
            {
                KernelEvents = KernelTraceEventParser.Keywords.ThreadTime;
            }

            parser.DefineOptionalQualifier("GCOnly", ref GCOnly, "Turns on JUST GC collections an allocation sampling.");
            if (GCOnly)
            {
                // TODO this logic is cloned.  We need it in only one place.  If you update it do the other location as well
                // For stack parsing.
                KernelEvents = KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread | KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.VirtualAlloc;
                ClrEvents    = ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.GCHeapSurvivalAndMovement | ClrTraceEventParser.Keywords.Stack |
                               ClrTraceEventParser.Keywords.Jit | ClrTraceEventParser.Keywords.StopEnumeration | ClrTraceEventParser.Keywords.SupressNGen |
                               ClrTraceEventParser.Keywords.Loader | ClrTraceEventParser.Keywords.Exception;

                // This is not quite correct if you have providers of your own, but this covers the most important case.
                if (Providers == null)
                {
                    Providers = new string[] { "Microsoft-Windows-Kernel-Memory:0x60" }
                }
                ;

                CommandProcessor.s_UserModeSessionName = "PerfViewGCSession";
                DataFile = "PerfViewGCOnly.etl";
            }
            parser.DefineOptionalQualifier("GCCollectOnly", ref GCCollectOnly, "Turns on GC collections (no allocation sampling).");
            if (GCCollectOnly)
            {
                // TODO this logic is cloned.  We need it in only one place.  If you update it do the other location as well
                KernelEvents  = KernelTraceEventParser.Keywords.Process;    // For process names
                ClrEvents     = ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.Exception;
                ClrEventLevel = TraceEventLevel.Informational;
                NoRundown     = true;
                CommandProcessor.s_UserModeSessionName = "PerfViewGCSession";
                DataFile = "PerfViewGCCollectOnly.etl";
            }

            // WPR option implies a bunch of kernel events.
            if (Wpr)
            {
                KernelEvents = KernelTraceEventParser.Keywords.ThreadTime |
                               KernelTraceEventParser.Keywords.DeferedProcedureCalls |
                               KernelTraceEventParser.Keywords.Driver |
                               KernelTraceEventParser.Keywords.Interrupt;
            }

            parser.DefineOptionalQualifier("DumpHeap", ref DumpHeap, "Capture a heap snapshot on profile stop");
            parser.DefineOptionalQualifier("Finalizers", ref Finalizers, "Track the number of objects of each type finalized.");
            parser.DefineOptionalQualifier("ClrEventLevel", ref ClrEventLevel, "The verbosity for CLR events");
            parser.DefineOptionalQualifier("ClrEvents", ref ClrEvents,
                                           "A comma separated list of .NET CLR events to turn on.  See Users guide for details.");
            parser.DefineOptionalQualifier("KernelEvents", ref KernelEvents,
                                           "A comma separated list of windows OS kernel events to turn on.  See Users guide for details.");

            parser.DefineOptionalQualifier("DotNetAlloc", ref DotNetAlloc, "Turns on per-allocation .NET profiling.");
            parser.DefineOptionalQualifier("DotNetAllocSampled", ref DotNetAllocSampled, "Turns on per-allocation .NET profiling, sampling types in a smart way to keep overhead low.");
            parser.DefineOptionalQualifier("DotNetCalls", ref DotNetCalls, "Turns on per-call .NET profiling.");
            parser.DefineOptionalQualifier("DotNetCallsSampled", ref DotNetCallsSampled, "Turns on per-call .NET profiling, sampling types in a smart way to keep overhead low.");
            parser.DefineOptionalQualifier("JITInlining", ref JITInlining, "Turns on logging of successful and failed JIT inlining attempts.");

            parser.DefineOptionalQualifier("OSHeapProcess", ref OSHeapProcess, "Turn on per-allocation profiling of allocation from the OS heap for the process with the given process ID.");
            parser.DefineOptionalQualifier("OSHeapExe", ref OSHeapExe, "Turn on per-allocation profiling of allocation from the OS heap for the process with the given EXE (only filename WITH extension).");

            parser.DefineOptionalQualifier("NetworkCapture", ref NetworkCapture, "Captures the full data of every network packet entering or leaving the OS.");
            parser.DefineOptionalQualifier("NetMonCapture", ref NetMonCapture, "Create _netmon.etl file that NetMon.exe can read, along with the standard ETL file.   Implies /NetworkCapture.");

            parser.DefineOptionalQualifier("ForceNgenRundown", ref ForceNgenRundown,
                                           "By default on a V4.0 runtime NGEN rundown is suppressed, because NGEN PDB are a less expensive way of getting symbolic " +
                                           "information for NGEN images.  This option forces NGEN rundown, so NGEN PDBs are not needed.  This can be useful " +
                                           "in some scenarios where NGEN PDB are not working properly.");
            parser.DefineOptionalQualifier("NoV2Rundown", ref NoV2Rundown,
                                           "Don't do rundown for .NET (CLR) V2 processes.");
            parser.DefineOptionalQualifier("TrustPdbs", ref TrustPdbs, "Normally PerfView does not trust PDBs outside the _NT_SYMBOL_PATH and pops a dialog box.  Suppress this.");
            parser.DefineOptionalQualifier("AcceptEULA", ref AcceptEULA, "Accepts the EULA associated with PerfView.");
            parser.DefineOptionalQualifier("DataFile", ref DataFile,
                                           "FileName of the profile data to generate.");
            parser.DefineOptionalQualifier("NoView", ref NoView,
                                           "Normally after collecting data the data is viewed.  This suppresses that.");
            parser.DefineOptionalQualifier("UnsafePDBMatch", ref UnsafePDBMatch,
                                           "Allow the use of PDBs even when the trace does not contain PDB signatures.");
            parser.DefineOptionalQualifier("ShowUnknownAddresses", ref ShowUnknownAddresses,
                                           "Displays the hexadecimal address rather than ? when the address is unknown.");
            parser.DefineOptionalQualifier("NoGui", ref NoGui,
                                           "Use the Command line version of the command (like on ARM).  Brings up a console window.  For batch scripts/automation use /LogFile instead (see users guide under 'Scripting' for more).");
            parser.DefineOptionalQualifier("SafeMode", ref SafeMode, "Turn off parallelism and other risky features.");
            parser.DefineOptionalQualifier("RestartingToElevelate", ref RestartingToElevelate, "Internal: indicates that perfView is restarting to get Admin privileges.");

            // TODO FIX NOW this is a hack, does not handle kernel mode ...
            parser.DefineOptionalQualifier("SessionName", ref CommandProcessor.s_UserModeSessionName, "Define the name for the user mode session, if kernel events are off.");

            parser.DefineOptionalQualifier("MaxNodeCountK", ref MaxNodeCountK,
                                           "The maximum number of objects (in K or thousands) that will even be examined when dumping the heap.  Avoids memory use at collection time.  " +
                                           "This is useful if heap dumping causes out of memory exceptions.");


            /* end of qualifier that apply to more than one parameter set (command) */
            /****************************************************************************************/
            /* Parameter set (command) definitions */
            parser.DefineParameterSet("run", ref DoCommand, App.CommandProcessor.Run,
                                      "Starts data collection, runs a command and stops.");
            parser.DefineParameter("CommandAndArgs", ref CommandAndArgs,
                                   "Command to run and arguments (PerfView options must come before run command).");

            parser.DefineParameterSet("collect", ref DoCommand, App.CommandProcessor.Collect,
                                      "Starts data collection, wait for user input, then stops.");
            parser.DefineOptionalParameter("DataFile", ref DataFile,
                                           "ETL file containing profile data.");

            parser.DefineParameterSet("start", ref DoCommand, App.CommandProcessor.Start,
                                      "Starts machine wide profile data collection.");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");

            parser.DefineParameterSet("stop", ref DoCommand, App.CommandProcessor.Stop,
                                      "Stop collecting profile data (machine wide).  If you specified EventSources with the /Providers qualifier on start you should repeat them here to insure manifest rundown.");

            parser.DefineParameterSet("mark", ref DoCommand, App.CommandProcessor.Mark,
                                      "Add a PerfView 'Mark' event to the event stream with a optional string message");
            parser.DefineOptionalParameter("Message", ref Message, "The string message to attach to the PerfView Mark event.");

            parser.DefineParameterSet("abort", ref DoCommand, App.CommandProcessor.Abort,
                                      "Insures that any active PerfView sessions are stopped.");

            parser.DefineParameterSet("merge", ref DoCommand, App.CommandProcessor.Merge,
                                      "Combine separate ETL files into a single ETL file (that can be decoded on another machine).");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");

            parser.DefineParameterSet("unzip", ref DoCommand, App.CommandProcessor.Unzip,
                                      "Unpack a ZIP file into its ETL file (and possibly its NGEN PDBS) /WPR option can be specified.");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");

            parser.DefineParameterSet("listSessions", ref DoCommand, App.CommandProcessor.ListSessions,
                                      "Lists active ETW sessions.");

            parser.DefineParameterSet("ListCpuCounters", ref DoCommand, App.CommandProcessor.ListCpuCounters,
                                      "Lists the ListCpuCounters CPU counters available on the system (win8+ only).");

            parser.DefineParameterSet("EnableKernelStacks", ref DoCommand, App.CommandProcessor.EnableKernelStacks,
                                      "On X64 machines if you have problems with broken stacks when the code is executing in the kernel," +
                                      " setting this option and rebooting may improve things");

            parser.DefineParameterSet("DisableKernelStacks", ref DoCommand, App.CommandProcessor.DisableKernelStacks,
                                      "Resets the registry keys set by EnableKernelStack.");

            string ProcessParam = null;

            parser.DefineParameterSet("HeapSnapshot", ref DoCommand, App.CommandProcessor.HeapSnapshot,
                                      "Take a snapshot of the CLR GC heap of a process.");
            parser.DefineParameter("Process", ref ProcessParam, "The process ID or Process Name (Exe without extension) of the process  take a heap snapshot.");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "The name of the file to place the heap snapshot.");
            parser.DefineOptionalQualifier("SaveETL", ref SaveETL, "Save an ETL file along with the GCDump file when dumping the JS Heap.");
            parser.DefineOptionalQualifier("MaxDumpCountK", ref MaxDumpCountK,
                                           "The maximum number of objects (in K or thousands) to place int the .gcDump file.   Sample sufficiently to hit this metric.");
            parser.DefineOptionalQualifier("Freeze", ref Freeze, "Freeze the dump while data is taken.");

            parser.DefineParameterSet("ForceGC", ref DoCommand, App.CommandProcessor.ForceGC,
                                      "Forces a GC on the specified process");
            parser.DefineParameter("Process", ref ProcessParam, "The process ID or Process Name (Exe without extension) of the process to force a GC.");

            // We have both a qualifier and a parameter named Process. It is OK that they use the same variable, but the parameter should not
            // overwrite the qualifier if it is null.
            if (ProcessParam != null)
            {
                Process = ProcessParam;
            }

            parser.DefineParameterSet("HeapSnapshotFromProcessDump", ref DoCommand, App.CommandProcessor.HeapSnapshotFromProcessDump,
                                      "Extract the CLR GC heap from a process dump file specified.");
            parser.DefineParameter("ProcessDumpFile", ref ProcessDumpFile, "The name of the input process dump file.");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "The name of the file to place the heap snapshot.");
            // TODO FIX NOW parser.DefineOptionalQualifier("DumpData", ref DumpData, "Dump the data as well as the connectivity information.");

            parser.DefineParameterSet("GuiRun", ref DoCommand, App.CommandProcessor.GuiRun, "Opens the 'Run' dialog box.");
            parser.DefineParameterSet("GuiCollect", ref DoCommand, App.CommandProcessor.GuiCollect, "Opens the 'Collect' dialog box.");
            parser.DefineParameterSet("GuiHeapSnapshot", ref DoCommand, App.CommandProcessor.GuiHeapSnapshot,
                                      "Opens the 'TakeHeapSnapshot' dialog box.");

            parser.DefineParameterSet("UserCommand", ref DoCommand, App.CommandProcessor.UserCommand,
                                      "Runs a user defined command.  Type 'PerfView UserCommandHelp' to see the help for all the user commands. " +
                                      "See PerfView Extensions in the users guide for more on creating user commands.");
            parser.DefineParameter("CommandAndArgs", ref CommandAndArgs, "User command to run and any arguments.");

            parser.DefineParameterSet("UserCommandHelp", ref DoCommand, App.CommandProcessor.UserCommandHelp,
                                      "Displays help for user commands.  Also see Help->User Command Help in the GUI.");

            parser.DefineParameterSet("CreateExtensionProject", ref DoCommand, App.CommandProcessor.CreateExtensionProject,
                                      "Creates a VS project for creates a perfView extension.");
            parser.DefineOptionalParameter("ExtensionName", ref ExtensionName, "The name of the extension (no .DLL)");

            // TODO FIX NOW, this should be a user command
            parser.DefineParameterSet("FetchSymbolsForProcess", ref DoCommand, App.CommandProcessor.FetchSymbolsForProcess,
                                      "Fetch all the PDBs files needed for viewing locally.  ");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL file containing profile data.");

#if CROSS_GENERATION_LIVENESS
            parser.DefineParameterSet("CollectCrossGenerationLiveness", ref DoCommand, App.CommandProcessor.CollectCrossGenerationLiveness,
                                      "Collect a heap snapshot that can be used to do cross-generation liveness analysis.");
            parser.DefineQualifier("PID", ref CGL_PID, "The process ID of the process to snapshot.");
            parser.DefineQualifier("Generation", ref CGL_Generation, "The generation of the GC to collect.");
            parser.DefineQualifier("PromotedBytesThreshold", ref CGL_PromotedBytesThreshold, "The threshold of promoted bytes after which a snapshot of the heap should be collected.");
            parser.DefineQualifier("OutputFile", ref CGL_PathToOutputFile, "The full path including filename where the resulting gcdump file should be stored.");
#endif

            parser.DefineDefaultParameterSet(ref DoCommand, App.CommandProcessor.View, "View profile data.");
            parser.DefineOptionalParameter("DataFile", ref DataFile, "ETL or ETLX file containing profile data.");
        }

        #endregion
    };
Beispiel #9
0
 public void ClrEnableParameters(ClrTraceEventParser.Keywords keywords, TraceEventLevel level)
 {
     WriteEvent(13, (long)keywords, (int)level);
 }
Beispiel #10
0
 public ClrEvents(ClrTraceEventParser.Keywords events)
 {
     m_events = events;
 }
Beispiel #11
0
 public ClrEvents(ClrTraceEventParser.Keywords events)
 {
     m_events = events;
 }