public ImmutableProductConfiguration(IProductConfiguration otherConfig) { Validate.NotNull(otherConfig, nameof(otherConfig)); _profilesExport_DefaultInterval = otherConfig.ProfilesExport_DefaultInterval; _profilesExport_EarlyTriggerOnCollectedStackSnapshotsBytes = otherConfig.ProfilesExport_EarlyTriggerOnCollectedStackSnapshotsBytes; _profilesExport_EarlyTriggerOnCollectedStackSnapshotsCount = otherConfig.ProfilesExport_EarlyTriggerOnCollectedStackSnapshotsCount; _profilesExport_LocalFiles_Directory = otherConfig.ProfilesExport_LocalFiles_Directory; _profilesIngestionEndpoint_Url = otherConfig.ProfilesIngestionEndpoint_Url; _profilesIngestionEndpoint_Host = otherConfig.ProfilesIngestionEndpoint_Host; _profilesIngestionEndpoint_Port = otherConfig.ProfilesIngestionEndpoint_Port; _profilesIngestionEndpoint_ApiPath = otherConfig.ProfilesIngestionEndpoint_ApiPath; _profilesIngestionEndpoint_DatadogApiKey = otherConfig.ProfilesIngestionEndpoint_DatadogApiKey; _ddDataTags_Host = otherConfig.DDDataTags_Host; _ddDataTags_Service = otherConfig.DDDataTags_Service; _ddDataTags_Env = otherConfig.DDDataTags_Env; _ddDataTags_Version = otherConfig.DDDataTags_Version; _ddDataTags_CustomTags = otherConfig.DDDataTags_CustomTags; _log_IsDebugEnabled = otherConfig.Log_IsDebugEnabled; _log_PreferredLogFileDirectory = otherConfig.Log_PreferredLogFileDirectory; _metrics_Operational_IsEnabled = otherConfig.Metrics_Operational_IsEnabled; _metrics_StatsdAgent_Port = otherConfig.Metrics_StatsdAgent_Port; _frameKinds_Native_IsEnabled = otherConfig.FrameKinds_Native_IsEnabled; }
#pragma warning disable CS0162 // Unreachable code detected: Purposeful control using const bool fields in this class. public static void SetupLogger(IProductConfiguration config) { // In case that we are re-initializing, dispose previous log sinks (one log sink via one-or-more redirections). DisposeLogSinks(); if (UseConsoleLogInsteadOfFileLog) { if (TrySetupConsoleLogger()) { return; } } else { if (TrySetupFileLogger(config)) { return; } } if (UseConsoleLogIfFileLogNotAvailable) { if (TrySetupConsoleLogger()) { return; } } ConsoleWriteLine(); ConsoleWriteLine("PROBLEM! Could not setup logger."); }
public LocalFilesProfilesExporter(IProductConfiguration config) { _appName = GetSanitizedAppName(config); _outputDirectory = GetOutputDirectory(config, _appName); _isEnabled = _outputDirectory != null; Log.Info(LogSource.Info, "Initialized", "IsEnabled", _isEnabled, "AppName", _appName, "OutputDirectory", _outputDirectory); }
public static IProductConfiguration CreateImmutableSnapshot(this IProductConfiguration config) { if (config == null) { return(null); } else { return(new ImmutableProductConfiguration(config)); } }
public static bool TryCreateAndStart(out ProfilerEngine runningProfilerEngine) { IProductConfiguration config = ProductConfigurationProvider.CreateDefault() // .ApplyReleaseDefaults() // .ApplyDevDefaults() .ApplyReleaseOrDevDefaults() .ApplyEnvironmentVariables() .CreateImmutableSnapshot(); return(TryCreateAndStart(config, out runningProfilerEngine)); }
private static string GetSanitizedAppName(IProductConfiguration config) { string unsanitizedAppName = config.DDDataTags_Service; if (string.IsNullOrWhiteSpace(unsanitizedAppName)) { try { unsanitizedAppName = CurrentProcess.GetName(); } catch { unsanitizedAppName = "UnknownApp"; } } // Sanitize app name: var appName = new StringBuilder(unsanitizedAppName); // Note that the 'appName' is likely to be based on the service name tag setting, which, in turn, // is likely to be based on the ASP.NET site name. // Common "unwished" characters that come up in site names, such as '/', '\\', ':' and others are // contained in the invalid chars arrays below, especially in 'invalidFilenameChars'. char[] invalidPathChars = Path.GetInvalidPathChars(); char[] invalidFilenameChars = Path.GetInvalidFileNameChars(); for (int p = 0; p < appName.Length; p++) { char c = appName[p]; bool isInvalid = char.IsWhiteSpace(c) || c == '.'; for (int i = 0; i < invalidPathChars.Length && !isInvalid; i++) { isInvalid = (c == invalidPathChars[i]); } for (int i = 0; i < invalidFilenameChars.Length && !isInvalid; i++) { isInvalid = (c == invalidFilenameChars[i]); } if (isInvalid) { appName[p] = '_'; } } return(appName.ToString()); }
public MetricsSender(IProductConfiguration config) { var tags = $"profiler_version:{config.DDDataTags_Version},service_name:{config.DDDataTags_Service},environment:{config.DDDataTags_Env}"; _tagsAsBytes = Encoding.UTF8.GetBytes(tags); _colonAsBytes = Encoding.UTF8.GetBytes(":"); _metricTypeAndTagsSeparatorAsBytes = Encoding.UTF8.GetBytes("|c|#"); _socket = new Socket(SocketType.Dgram, ProtocolType.Udp); // We consider the statsd agent to be installed locally (for now) _statsdAgentEndpoint = CreateEndpoint("127.0.0.1", config.Metrics_StatsdAgent_Port); _buffer = new byte[1024]; _additionalTagsBuilder = new StringBuilder(); }
public static IProductConfiguration ApplyReleaseOrDevDefaults(this IProductConfiguration config) { const string EnvVarName = "DD_INTERNAL_USE_DEVELOPMENT_CONFIGURATION"; const bool ddInternalUseDevelopmentConfigurationValDefault = false; string ddInternalUseDevelopmentConfiguration = Environment.GetEnvironmentVariable(EnvVarName); if ( ConfigurationProviderUtils.TryParseBooleanSettingStr( ddInternalUseDevelopmentConfiguration, ddInternalUseDevelopmentConfigurationValDefault, out bool ddInternalUseDevelopmentConfigurationVal)) { Log.Info( LogComponentMoniker, "Use-Dev-Config environment setting found and parsed.", "Env var name", EnvVarName, "Parsed value", ddInternalUseDevelopmentConfigurationVal); } else { Log.Info( LogComponentMoniker, "Use-Dev-Config environment setting not found or not parsed. Default will be used.", "Env var name", EnvVarName, "Value", ddInternalUseDevelopmentConfiguration, "Used default value", ddInternalUseDevelopmentConfigurationVal); } if (ddInternalUseDevelopmentConfigurationVal) { return(DevProductConfigurationProvider.ApplyDevDefaults(config)); } else { return(DefaultReleaseProductConfigurationProvider.ApplyReleaseDefaults(config)); } }
/// <summary> /// Called internally AFTER <c>s_singletonAccessLock</c> has been taken and it was validated that no other engine is running. /// </summary> private static void CreateAndStart(IProductConfiguration config, out ProfilerEngine newProfilerEngine) { LogConfigurator.SetupLogger(config); Log.Info(Log.WithCallInfo(LogSourceMoniker), "Initializing. Will create and start the managed profiler engine."); try { ThreadUtil.EnsureSetCurrentManagedThreadNameNativeCallbackInitialized(); _currentEngine = new ProfilerEngine(config); newProfilerEngine = _currentEngine; LogInitializationCompleted(newProfilerEngine); } catch (Exception ex) { Log.Error(Log.WithCallInfo(LogSourceMoniker), "Initialization error.", ex); newProfilerEngine = null; } }
private string GetOutputDirectory(IProductConfiguration config, string appName) { if (string.IsNullOrWhiteSpace(config.ProfilesExport_LocalFiles_Directory)) { return(null); } string outDir; // First, try with the defined directory try { if (BuildAndValidateOutputDirectory(config.ProfilesExport_LocalFiles_Directory, appName, isLastResort: false, out outDir)) { return(outDir); } } catch (Exception ex) { // Probably did not have permissions to GetCurrentDirectory. Log.Error(LogSource.Info.WithCallInfo(), ex); } // Otherwise, save them in a temp folder try { string tempDir = Path.GetTempPath(); string outBaseDir = Path.Combine(tempDir, DirectoryFallbackRoot, DirectoryFallbackSub); if (BuildAndValidateOutputDirectory(outBaseDir, appName, isLastResort: true, out outDir)) { return(outDir); } } catch (Exception ex) { // Probably did not have permissions to GetTempPath. Log.Error(LogSource.Info.WithCallInfo(), ex); } return(null); }
private ProfilerEngine(IProductConfiguration config) { Validate.NotNull(config, nameof(config)); _versionInfo = ProfilerEngineVersionInfo.CreateNewInstance(); _profiledThreadInfoProvider = new ProfiledThreadInfoProvider(); _profiledAppDomainProvider = new ProfiledAppDomainProvider(); _enqueueStackSnapshotBufferSegmentForExport = NativeCallback_EnqueueStackSnapshotBufferSegmentForExport; _tryShutdownCurrentManagedProfilerEngine = NativeCallback_TryShutdownCurrentManagedProfilerEngine; _completedStackSnapshots = new StackSnapshotsBufferSegmentCollection(); _pprofBuilder = new PProfBuilder(); RegisterReversePInvokeCallbacks(); _resolveAndExportStacksBackgroundLoop = new ResolveAndExportStacksBackgroundLoop(this, config); _resolveAndExportStacksBackgroundLoop.Start(); }
public static bool TryCreateAndStart(IProductConfiguration config, out ProfilerEngine runningProfilerEngine) { Validate.NotNull(config, nameof(config)); runningProfilerEngine = _currentEngine; if (runningProfilerEngine != null) { return(false); } lock (_singletonAccessLock) { runningProfilerEngine = _currentEngine; if (runningProfilerEngine != null) { return(false); } CreateAndStart(config, out runningProfilerEngine); return(runningProfilerEngine != null); } }
private static bool TrySetupFileLogger(IProductConfiguration config) { try { var filenameBaseInfo = new DatadogEnvironmentFileLogSinkFactory.FilenameBaseInfo(ProductFamily, Product, ComponentGroup); if (DatadogEnvironmentFileLogSinkFactory.TryCreateNewFileLogSink( filenameBaseInfo, LoggingDemoLogGroupId, config?.Log_PreferredLogFileDirectory, LogFileSizeBytes, FileFormatOptions, out FileLogSink fileLogSink)) { RedirectLogs(fileLogSink, out _logRedirections); if (config != null) { LogComposer.IsDebugLoggingEnabled = config.Log_IsDebugEnabled; } else { LogComposer.SetDebugLoggingEnabledBasedOnEnvironment(); } return(true); } } catch (Exception ex) { ConsoleWriteLine(); ConsoleWriteLine("Error setting up a file logger."); ConsoleWriteLine($"{ex}"); } return(false); }
public static IProductConfiguration ApplyEnvironmentVariables(this IProductConfiguration config) { if (config == null) { return(null); } var mutableConfig = new MutableProductConfiguration(config); if (TryGetEnvironmentVariable("SIGNALFX_PROFILING_UPLOAD_PERIOD", out string envProfilesExportDefaultInterval)) { if (int.TryParse(envProfilesExportDefaultInterval, out var profilesExportDefaultInterval)) { mutableConfig.ProfilesExport_DefaultInterval = TimeSpan.FromSeconds(profilesExportDefaultInterval); } else { Log.Error( Log.WithCallInfo(LogComponentMoniker), "The environment variable \"SIGNALFX_PROFILING_UPLOAD_PERIOD\" is specified (\"", envProfilesExportDefaultInterval, "\") but cannot be parsed as an int. Using original value: ", mutableConfig.ProfilesExport_DefaultInterval); } } if (TryGetEnvironmentVariable("SIGNALFX_PROFILING_OUTPUT_DIR", out string directory)) { mutableConfig.ProfilesExport_LocalFiles_Directory = directory; } // If Ingestion Endpoint Url is specified, the Host, Port and ApiPath are ignored. // However, that logic is inside the export loop that actually interprets those values. // At this point we just extract all of the info that is contained in the environment variables. // If both, URL and Host-Port-Etc are specified, we will extract them all and leave the // priorization logic of what to use to the config consumer. if (TryGetEnvironmentVariable("SIGNALFX_TRACE_AGENT_URL", out string ddTraceAgentUrl)) { mutableConfig.ProfilesIngestionEndpoint_Url = ddTraceAgentUrl; } if (TryGetEnvironmentVariable("SIGNALFX_AGENT_HOST", out string ddTraceAgentHost)) { mutableConfig.ProfilesIngestionEndpoint_Host = ddTraceAgentHost; } if (TryGetEnvironmentVariable("SIGNALFX_TRACE_AGENT_PORT", out string szTraceAgentPort)) { if (int.TryParse(szTraceAgentPort, out int port)) { mutableConfig.ProfilesIngestionEndpoint_Port = port; } else { Log.Error( Log.WithCallInfo(LogComponentMoniker), "The environment variable \"SIGNALFX_TRACE_AGENT_PORT\" is specified (", szTraceAgentPort, ") but cannot be parsed as a number and will be ignored."); } } // Api Key is not required for agent-based ingestion scnarios; it IS required for agent-less ingestion. if (TryGetEnvironmentVariable("SIGNALFX_API_KEY", out string ddApiKey)) { mutableConfig.ProfilesIngestionEndpoint_DatadogApiKey = ddApiKey; } if (TryGetEnvironmentVariable("SIGNALFX_HOSTNAME", out string ddHostName)) { mutableConfig.DDDataTags_Host = ddHostName; } if (TryGetEnvironmentVariable("SIGNALFX_SERVICE", out string ddServiceName)) { mutableConfig.DDDataTags_Service = ddServiceName; } if (TryGetEnvironmentVariable("SIGNALFX_ENV", out string ddEnvironment)) { mutableConfig.DDDataTags_Env = ddEnvironment; } if (TryGetEnvironmentVariable("SIGNALFX_VERSION", out string ddServiceVersion)) { mutableConfig.DDDataTags_Version = ddServiceVersion; } if (TryGetEnvironmentVariable("SIGNALFX_TAGS", out string ddTagsStr)) { mutableConfig.DDDataTags_CustomTags = ParseAndMergeDdTags(mutableConfig.DDDataTags_CustomTags, ddTagsStr); } if (TryGetEnvironmentVariable("SIGNALFX_TRACE_DEBUG", out string envIsTraceDebugEnabled)) { const bool isTraceDebugEnabled = true; if ( ConfigurationProviderUtils.TryParseBooleanSettingStr( envIsTraceDebugEnabled, isTraceDebugEnabled, out bool ddIsTraceDebugEnabledVal)) { mutableConfig.Log_IsDebugEnabled = ddIsTraceDebugEnabledVal; } else { Log.Error( Log.WithCallInfo(LogComponentMoniker), "The environment variable \"SIGNALFX_TRACE_DEBUG\" is specified (", envIsTraceDebugEnabled, $") but cannot be parsed as a boolean. Using {isTraceDebugEnabled.ToString()} as default"); mutableConfig.Log_IsDebugEnabled = isTraceDebugEnabled; } } if (TryGetEnvironmentVariable("SIGNALFX_PROFILING_LOG_DIR", out string ddTraceLogDirectory)) { mutableConfig.Log_PreferredLogFileDirectory = ddTraceLogDirectory; } if (TryGetEnvironmentVariable("SIGNALFX_INTERNAL_OPERATIONAL_METRICS_ENABLED", out string envIsEnabled)) { const bool isOperationalMetricsEnabled = false; if (ConfigurationProviderUtils.TryParseBooleanSettingStr(envIsEnabled, isOperationalMetricsEnabled, out bool isEnabled)) { mutableConfig.Metrics_Operational_IsEnabled = isEnabled; } else { Log.Error( Log.WithCallInfo(LogComponentMoniker), "The environment variable \"SIGNALFX_INTERNAL_OPERATIONAL_METRICS_ENABLED\" is specified (", envIsEnabled, $") but cannot be parsed as a boolean. Using {isOperationalMetricsEnabled.ToString()} as default"); mutableConfig.Log_IsDebugEnabled = isOperationalMetricsEnabled; } } if (TryGetEnvironmentVariable("SIGNALFX_PROFILING_FRAMES_NATIVE_ENABLED", out string envFramesNativeIsEnabled)) { const bool isFramesNativeEnabled = false; if (ConfigurationProviderUtils.TryParseBooleanSettingStr(envFramesNativeIsEnabled, isFramesNativeEnabled, out bool isEnabled)) { mutableConfig.FrameKinds_Native_IsEnabled = isEnabled; } else { Log.Error( Log.WithCallInfo(LogComponentMoniker), "The environment variable \"SIGNALFX_PROFILING_FRAMES_NATIVE_ENABLED\" is specified (", envFramesNativeIsEnabled, $") but cannot be parsed as a boolean. Using isFramesNativeEnabled.ToString() as default"); mutableConfig.FrameKinds_Native_IsEnabled = isFramesNativeEnabled; } } return(mutableConfig.CreateImmutableSnapshot()); }
public static IProductConfiguration ApplyDevDefaults(this IProductConfiguration config) { if (config == null) { return(null); } var mutableConfig = new MutableProductConfiguration(config); // mutableConfig.ProfilesExport_DefaultInterval = TimeSpan.FromSeconds(20); mutableConfig.ProfilesExport_DefaultInterval = TimeSpan.FromSeconds(60); // These bytes are counted as encoded in the buffer segment, i.e. each snapshot takes (26 + 9 per frame) bytes (see StackSnapshotResult.h). // Snapshots with 100 frames: 1 snapshot uses 926 bytes, 1MB holds 1132 such snapshots. // Snapshots with 50 frames: 1 snapshot uses 476 bytes, 1MB holds 2202 such snapshots // Snapshots with 35 frames: 1 snapshot uses 341 bytes, 1MB holds 3075 such snapshots. // // We will not sample 5 threads more often than once every 9 milliseconds. // Assuming 50 frames per snapshot on average (based on some ad-hoc tests with Computer01 demo // it is a safe upper bound for the average), we don't expect to generate more than ~33,333 (= 5 * 60 * 1000 / 9) snapshots per minute // --> which requires 33,333 / 2202 ~= 15 MB. // A 50 MB buffer will work for ~3+ minutes // 50,000 samples currespond to ~22 MB. mutableConfig.ProfilesExport_EarlyTriggerOnCollectedStackSnapshotsBytes = 50 * 1024 * 1024; // 50 MBytes mutableConfig.ProfilesExport_EarlyTriggerOnCollectedStackSnapshotsCount = 50000; mutableConfig.ProfilesExport_LocalFiles_Directory = ConfigurationProviderUtils.GetOsSpecificDefaultPProfDirectory(); // If Ingestion Endpoint Url is specified, the Host, Port and ApiPath are ignored. // mutableConfig.ProfilesIngestionEndpoint_Url = "https://intake.profile.datadoghq.com/v1/input"; // --> to local agent that sends to staging // mutableConfig.ProfilesIngestionEndpoint_Host = "127.0.0.1"; // Local agent (avoids the IPv4 wait that can occur when using "localhost") // mutableConfig.ProfilesIngestionEndpoint_Host = "localhost"; // Local agent // mutableConfig.ProfilesIngestionEndpoint_Host = "intake.profile.datadoghq.com"; // Main DD ingestion endpoint for agent-less // mutableConfig.ProfilesIngestionEndpoint_Host = "intake.profile.datad0g.com"; // Staging DD ingestion endpoint for agent-less mutableConfig.ProfilesIngestionEndpoint_Port = 8126; // Local agent's default port // mutableConfig.ProfilesIngestionEndpoint_Port = 0; // Value <= 0 will result the defaut port for the protocol being used. mutableConfig.ProfilesIngestionEndpoint_ApiPath = "profiling/v1/input"; // Local agent's API path. // mutableConfig.ProfilesIngestionEndpoint_ApiPath = "v1/input"; // DD ingestion endpoint's API path (for agent-less scenarios) // Api Key is not required for agent-based ingestion scenarios; it IS required for agent-less ingestion. // mutableConfig.ProfilesIngestionEndpoint_DatadogApiKey = "xxx"; // mutableConfig.ProfilesIngestionEndpoint_DatadogApiKey = null; // --> to preprod mutableConfig.ProfilesIngestionEndpoint_Url = "https://intake.profile.datadoghq.com/v1/input"; mutableConfig.ProfilesIngestionEndpoint_DatadogApiKey = string.Empty; string ddService = ConfigurationProviderUtils.GetDdServiceFallback(); mutableConfig.DDDataTags_Host = ConfigurationProviderUtils.GetMachineName(); mutableConfig.DDDataTags_Service = string.IsNullOrWhiteSpace(ddService) ? ".Net-Profiling-TestService01" : ddService; mutableConfig.DDDataTags_Env = "APM-Profiling-Local"; mutableConfig.DDDataTags_Version = "Demo-Version-11"; mutableConfig.DDDataTags_CustomTags = new KeyValuePair <string, string>[] { new KeyValuePair <string, string>("CustomTag A", string.Empty), new KeyValuePair <string, string>(null, "Some Value B"), new KeyValuePair <string, string>("CustomTag C", "Some Value C"), new KeyValuePair <string, string>("service", "Foo-Bar") }; mutableConfig.Log_IsDebugEnabled = true; mutableConfig.Log_PreferredLogFileDirectory = ConfigurationProviderUtils.GetOsSpecificDefaultLogDirectory(); mutableConfig.Metrics_Operational_IsEnabled = false; mutableConfig.Metrics_StatsdAgent_Port = 8125; // For now, the default installation does not collect native frames. // The user can, however, enable it using an environment variable (see 'EnvironmentVariablesConfigurationProvider'). // This should be changed once the UI supports appropriate filtering. mutableConfig.FrameKinds_Native_IsEnabled = false; return(mutableConfig.CreateImmutableSnapshot()); }
public MutableProductConfiguration(IProductConfiguration otherConfig) : base(otherConfig) { }
public static IProductConfiguration ApplyReleaseDefaults(this IProductConfiguration config) { if (config == null) { return(null); } var mutableConfig = new MutableProductConfiguration(config); mutableConfig.ProfilesExport_DefaultInterval = TimeSpan.FromSeconds(60); // These bytes are counted as encoded in the buffer segment, i.e. each snapshot takes (26 + 9 per frame) bytes (see StackSnapshotResult.h). // Snapshots with 100 frames: 1 snapshot uses 926 bytes, 1MB holds 1132 such snapshots. // Snapshots with 50 frames: 1 snapshot uses 476 bytes, 1MB holds 2202 such snapshots // Snapshots with 35 frames: 1 snapshot uses 341 bytes, 1MB holds 3075 such snapshots. // // We will not sample 5 threads more often than once every 9 milliseconds. // Assuming 50 frames per snapshot on average (based on some ad-hoc tests with Computer01 demo // it is a safe upper bound for the average), we don't expect to generate more than ~33333 (= 5 * 60 * 1000 / 9) snapshots per minute // --> which requires 33333 / 2202 ~= 15 MB. // A 500 MB buffer will work for ~33 minutes // 1,000,000 samples currespond to ~454 MB. // // Based on the above, we go with the magic numbers that will limit the buffer to 500 MB and 1 Mio samples // by triggering the profiles export if those thresholds are met. // These are round numbers that will keep the impact on the customer app in check during early beta stages. // During the public beta we need to validate these assumptions and see if the numbers need to be tweaked in either direction. mutableConfig.ProfilesExport_EarlyTriggerOnCollectedStackSnapshotsBytes = 500 * 1024 * 1024; // 500 MBytes mutableConfig.ProfilesExport_EarlyTriggerOnCollectedStackSnapshotsCount = 1000000; // 1,000,000 stack samples mutableConfig.ProfilesExport_LocalFiles_Directory = null; mutableConfig.ProfilesIngestionEndpoint_Url = null; // If Ingestion Endpoint Url is specified, the Host, Port and ApiPath are ignored. mutableConfig.ProfilesIngestionEndpoint_Host = "127.0.0.1"; // Local agent (avoids the IPv4 wait that can occur when using "localhost") mutableConfig.ProfilesIngestionEndpoint_Port = 8126; // Local agent's default port mutableConfig.ProfilesIngestionEndpoint_ApiPath = "profiling/v1/input"; // Local agent's API path. // Api Key is not required for agent-based ingestion scnarios; it IS required for agent-less ingestion. mutableConfig.ProfilesIngestionEndpoint_DatadogApiKey = null; // For RELEASE, the we use defaults below, and better values need to be created by setting respective environment variables // (see the .ApplyEnvironmentVariables() API in EnvironmentVariablesConfigurationProvider). string ddService = ConfigurationProviderUtils.GetDdServiceFallback(); mutableConfig.DDDataTags_Host = ConfigurationProviderUtils.GetMachineName(); mutableConfig.DDDataTags_Service = string.IsNullOrWhiteSpace(ddService) ? "Unspecified-Service" : ddService; mutableConfig.DDDataTags_Env = "Unspecified-Environment"; mutableConfig.DDDataTags_Version = "Unspecified-Version"; mutableConfig.DDDataTags_CustomTags = new KeyValuePair <string, string> [0]; // When we get to public beta, Debug-Logging should be DISABLED by default. // However, while we are still working towards that level of maturity, debug logs are almost always helpful. mutableConfig.Log_IsDebugEnabled = true; mutableConfig.Log_PreferredLogFileDirectory = ConfigurationProviderUtils.GetOsSpecificDefaultLogDirectory(); mutableConfig.Metrics_Operational_IsEnabled = false; mutableConfig.Metrics_StatsdAgent_Port = 8125; // For now, the default installation does not collect native frames. // The user can, however, enable it using an environment variable (see 'EnvironmentVariablesConfigurationProvider'). // This should be changed once the UI supports appropriate filtering. mutableConfig.FrameKinds_Native_IsEnabled = false; return(mutableConfig.CreateImmutableSnapshot()); }