private static EventPipeConfiguration BuildConfigFromEnvironment() { // Build the full path to the trace file. string traceFileName = BuildTraceFileName(); string outputFilePath = Path.Combine(Config_EventPipeOutputPath, traceFileName); // Create a new configuration object. EventPipeConfiguration config = new EventPipeConfiguration( outputFilePath, Config_EventPipeCircularMB); // Get the configuration. string strConfig = Config_EventPipeConfig; if (!string.IsNullOrEmpty(strConfig)) { // If the configuration is specified, parse it and save it to the config object. SetProviderConfiguration(strConfig, config); } else { // Specify the default configuration. config.EnableProviderRange(DefaultProviderConfiguration); } return(config); }
private static void SetProviderConfiguration(string strConfig, EventPipeConfiguration config) { if (string.IsNullOrEmpty(strConfig)) { throw new ArgumentNullException(nameof(strConfig)); } // Provider format: "(GUID|KnownProviderName)[:Flags[:Level][:KeyValueArgs]]" // where KeyValueArgs are of the form: "[key1=value1][;key2=value2]" // `strConfig` must be of the form "Provider[,Provider]" string[] providers = strConfig.Split( ProviderConfigDelimiter, StringSplitOptions.RemoveEmptyEntries); // Remove "empty" providers. foreach (string provider in providers) { // Split expecting a maximum of four tokens. string[] components = provider.Split( ConfigComponentDelimiter, 4, // if there is ':' in the parameters then anything after it will not be ignored. StringSplitOptions.None); // Keep empty tokens string providerName = components.Length > 0 ? components[0] : null; if (string.IsNullOrEmpty(providerName)) { continue; // No provider name specified. } ulong keywords = ulong.MaxValue; if (components.Length > 1) { // We use a try/catch block here because ulong.TryParse won't accept 0x at the beginning // of a hex string. Thus, we either need to conditionally strip it or handle the exception. // Given that this is not a perf-critical path, catching the exception is the simpler code. try { keywords = Convert.ToUInt64(components[1], 16); } catch { } } uint level = 5; // Verbose if (components.Length > 2) { uint.TryParse(components[2], out level); } string filterData = components.Length > 3 ? components[3] : null; config.EnableProviderWithFilter(providerName, keywords, level, filterData); } }
private static EventPipeConfiguration GetConfiguration() { // Create a new configuration object. EventPipeConfiguration config = new EventPipeConfiguration( GetDisambiguatedTraceFilePath(Config_EventPipeOutputFile), Config_EventPipeCircularMB); // Get the configuration. string strConfig = Config_EventPipeConfig; if (!string.IsNullOrEmpty(strConfig)) { // String must be of the form "providerName:keywords:level,providerName:keywords:level..." string[] providers = strConfig.Split(ProviderConfigDelimiter); foreach (string provider in providers) { string[] components = provider.Split(ConfigComponentDelimiter); if (components.Length == 3) { string providerName = components[0]; // We use a try/catch block here because ulong.TryParse won't accept 0x at the beginning // of a hex string. Thus, we either need to conditionally strip it or handle the exception. // Given that this is not a perf-critical path, catching the exception is the simpler code. ulong keywords = 0; try { keywords = Convert.ToUInt64(components[1], 16); } catch { } uint level; if (!uint.TryParse(components[2], out level)) { level = 0; } config.EnableProvider(providerName, keywords, level); } } } else { // Specify the default configuration. config.EnableProviderRange(DefaultProviderConfiguration); } return(config); }
internal static void Enable(EventPipeConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } EventPipeProviderConfiguration[] providers = configuration.Providers; EventPipeInternal.Enable( configuration.OutputFile, configuration.CircularBufferSizeInMB, configuration.ProfilerSamplingRateInNanoseconds, providers, providers.Length); }
internal static void Enable(EventPipeConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (configuration.Providers == null) { throw new ArgumentNullException(nameof(configuration.Providers)); } EventPipeProviderConfiguration[] providers = configuration.Providers; s_sessionID = EventPipeInternal.Enable( configuration.OutputFile, configuration.Format, configuration.CircularBufferSizeInMB, providers); }
internal static void Enable(EventPipeConfiguration configuration) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (configuration.Providers == null) { throw new ArgumentNullException(nameof(configuration.Providers)); } EventPipeProviderConfiguration[] providers = configuration.Providers; s_sessionID = EventPipeInternal.Enable( configuration.OutputFile, configuration.CircularBufferSizeInMB, (ulong)configuration.ProfilerSamplingRateInNanoseconds, providers, (uint)providers.Length, configuration.MultiFileTraceLengthInSeconds); }
private void PollForTracingCommand(object state) { // Make sure that any transient errors don't cause the listener thread to exit. try { // Check for existence of the config file. // If the existence of the file has changed since the last time we checked or the update time has changed // this means that we need to act on that change. bool fileExists = File.Exists(m_configFilePath); if (m_configFileExists != fileExists) { // Save the result. m_configFileExists = fileExists; // Take the appropriate action. if (fileExists) { // Enable tracing. // Check for null here because it's possible that the configuration contains a process filter // that doesn't match the current process. IF this occurs, we should't enable tracing. EventPipeConfiguration config = BuildConfigFromFile(m_configFilePath); if (config != null) { EventPipe.Enable(config); } } else { // Disable tracing. EventPipe.Disable(); } } // Schedule the timer to run again. m_timer.Change(fileExists ? EnabledPollingIntervalMilliseconds : DisabledPollingIntervalMilliseconds, Timeout.Infinite); } catch { } }
private static void SetProviderConfiguration(string strConfig, EventPipeConfiguration config) { if (string.IsNullOrEmpty(strConfig)) { throw new ArgumentNullException(nameof(strConfig)); } // String must be of the form "providerName:keywords:level,providerName:keywords:level..." string[] providers = strConfig.Split(ProviderConfigDelimiter); foreach (string provider in providers) { string[] components = provider.Split(ConfigComponentDelimiter); if (components.Length == 3) { string providerName = components[0]; // We use a try/catch block here because ulong.TryParse won't accept 0x at the beginning // of a hex string. Thus, we either need to conditionally strip it or handle the exception. // Given that this is not a perf-critical path, catching the exception is the simpler code. ulong keywords = 0; try { keywords = Convert.ToUInt64(components[1], 16); } catch { } uint level; if (!uint.TryParse(components[2], out level)) { level = 0; } config.EnableProvider(providerName, keywords, level); } } }
private static EventPipeConfiguration BuildConfigFromFile(string configFilePath) { // Read the config file in once call. byte[] configContents = File.ReadAllBytes(configFilePath); // Convert the contents to a string. string strConfigContents = Encoding.UTF8.GetString(configContents); // Read all of the config options. string outputPath = null; string strProviderConfig = null; string strCircularMB = null; string strProcessID = null; string strMultiFileSec = null; // Split the configuration entries by line. string[] configEntries = strConfigContents.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string configEntry in configEntries) { //`Split the key and value by '='. string[] entryComponents = configEntry.Split( ConfigEntryDelimiter, 2, // Stop split on first occurrence of the separator. StringSplitOptions.RemoveEmptyEntries); if (entryComponents.Length == 2) { string key = entryComponents[0]; if (key.Equals(ConfigKey_Providers)) { strProviderConfig = entryComponents[1]; } else if (key.Equals(ConfigKey_OutputPath)) { outputPath = entryComponents[1]; } else if (key.Equals(ConfigKey_CircularMB)) { strCircularMB = entryComponents[1]; } else if (key.Equals(ConfigKey_ProcessID)) { strProcessID = entryComponents[1]; } else if (key.Equals(ConfigKey_MultiFileSec)) { strMultiFileSec = entryComponents[1]; } } } // Check the process ID filter if it is set. if (!string.IsNullOrEmpty(strProcessID)) { // If set, bail out early if the specified process does not match the current process. int processID = Convert.ToInt32(strProcessID); if (processID != Interop.Kernel32.GetCurrentProcessId()) { return(null); } } // Ensure that the output path is set. if (string.IsNullOrEmpty(outputPath)) { throw new ArgumentNullException(nameof(outputPath)); } // Check to see if MultiFileSec is specified. ulong multiFileSec = 0; if (!string.IsNullOrEmpty(strMultiFileSec)) { multiFileSec = Convert.ToUInt64(strMultiFileSec); } // Build the full path to the trace file. string traceFileName = BuildTraceFileName(); string outputFile = Path.Combine(outputPath, traceFileName); // Get the circular buffer size. uint circularMB = DefaultCircularBufferMB; if (!string.IsNullOrEmpty(strCircularMB)) { circularMB = Convert.ToUInt32(strCircularMB); } // Initialize a new configuration object. EventPipeConfiguration config = new EventPipeConfiguration(outputFile, circularMB); config.SetMultiFileTraceLength(multiFileSec); // Set the provider configuration if specified. if (!string.IsNullOrEmpty(strProviderConfig)) { SetProviderConfiguration(strProviderConfig, config); } else { // If the provider configuration isn't specified, use the default. config.EnableProviderRange(DefaultProviderConfiguration); } return(config); }