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(); } }
/// <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; }
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 }
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)); }
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 ) ); }
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 };
public void ClrEnableParameters(ClrTraceEventParser.Keywords keywords, TraceEventLevel level) { WriteEvent(13, (long)keywords, (int)level); }
public ClrEvents(ClrTraceEventParser.Keywords events) { m_events = events; }