// Very awkward procedure that accesses global state in the name of only doing one iteration internal static void AddTagsToFMAndGlobalList( string tagsToAdd, FMCategoriesCollection existingFMTags, bool addToGlobalList = true) { if (tagsToAdd.IsWhiteSpace()) { return; } string[] tagsArray = tagsToAdd.Split(CA_CommaSemicolon, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < tagsArray.Length; i++) { if (!TryGetCatAndTag(tagsArray[i], out string cat, out string tag) || cat.IsEmpty() || tag.IsEmpty()) { continue; } #region FM tags if (existingFMTags.TryGetValue(cat, out FMTagsCollection tagsList)) { tagsList.Add(tag); } else { existingFMTags.Add(cat, new FMTagsCollection { tag }); } #endregion if (!addToGlobalList) { continue; } #region Global tags if (GlobalTags.TryGetValue(cat, out FMTagsCollection globalTagsList)) { globalTagsList.Add(tag); } else { GlobalTags.Add(cat, new FMTagsCollection { tag }); } #endregion } }
/// <summary> /// Initializes a new instance of the <see cref="TracerSettings"/> class /// using the specified <see cref="IConfigurationSource"/> to initialize values. /// </summary> /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param> public TracerSettings(IConfigurationSource source) { Environment = source?.GetString(ConfigurationKeys.Environment); ServiceName = source?.GetString(ConfigurationKeys.ServiceName) ?? // backwards compatibility for names used in the past source?.GetString("DD_SERVICE_NAME"); ServiceVersion = source?.GetString(ConfigurationKeys.ServiceVersion); TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ?? // default value true; var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations) ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? Enumerable.Empty <string>(); DisabledIntegrationNames = new HashSet <string>(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase); var agentHost = source?.GetString(ConfigurationKeys.AgentHost) ?? // backwards compatibility for names used in the past source?.GetString("DD_TRACE_AGENT_HOSTNAME") ?? source?.GetString("DATADOG_TRACE_AGENT_HOSTNAME") ?? // default value DefaultAgentHost; var agentPort = source?.GetInt32(ConfigurationKeys.AgentPort) ?? // backwards compatibility for names used in the past source?.GetInt32("DATADOG_TRACE_AGENT_PORT") ?? // default value DefaultAgentPort; var agentUri = source?.GetString(ConfigurationKeys.AgentUri) ?? // default value $"http://{agentHost}:{agentPort}"; AgentUri = new Uri(agentUri); if (string.Equals(AgentUri.Host, "localhost", StringComparison.OrdinalIgnoreCase)) { // Replace localhost with 127.0.0.1 to avoid DNS resolution. // When ipv6 is enabled, localhost is first resolved to ::1, which fails // because the trace agent is only bound to ipv4. // This causes delays when sending traces. var builder = new UriBuilder(agentUri) { Host = "127.0.0.1" }; AgentUri = builder.Uri; } AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ?? // default value false; LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ?? // default value false; MaxTracesSubmittedPerSecond = source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond) ?? // default value 100; Integrations = new IntegrationSettingsCollection(source); GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ?? // backwards compatibility for names used in the past source?.GetDictionary("DD_TRACE_GLOBAL_TAGS") ?? // default value (empty) new ConcurrentDictionary <string, string>(); // Filter out tags with empty keys or empty values, and trim whitespace GlobalTags = GlobalTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value)) .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); HeaderTags = source?.GetDictionary(ConfigurationKeys.HeaderTags) ?? // default value (empty) new ConcurrentDictionary <string, string>(); // Filter out tags with empty keys or empty values, and trim whitespace HeaderTags = HeaderTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value)) .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); DogStatsdPort = source?.GetInt32(ConfigurationKeys.DogStatsdPort) ?? // default value 8125; TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ?? // default value false; RuntimeMetricsEnabled = source?.GetBool(ConfigurationKeys.RuntimeMetricsEnabled) ?? false; CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules); GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate); StartupDiagnosticLogEnabled = source?.GetBool(ConfigurationKeys.StartupDiagnosticLogEnabled) ?? // default value true; TraceQueueSize = source?.GetInt32(ConfigurationKeys.QueueSize) ?? 1000; }
// Very awkward procedure that accesses global state in the name of only doing one iteration // TODO: Test perf when 1000+ FMs each have a bunch of tags internal static void AddTagsToFMAndGlobalList(string tagsToAdd, CatAndTagsList existingFMTags) { if (tagsToAdd.IsEmpty()) { return; } string[] tagsArray = tagsToAdd.Split(CA_CommaSemicolon, StringSplitOptions.RemoveEmptyEntries); foreach (string item in tagsArray) { string cat, tag; int colonCount = item.CountCharsUpToAmount(':', 2); // No way josé if (colonCount > 1) { continue; } if (colonCount == 1) { int index = item.IndexOf(':'); cat = item.Substring(0, index).Trim().ToLowerInvariant(); tag = item.Substring(index + 1).Trim(); if (cat.IsEmpty() || tag.IsEmpty()) { continue; } } else { cat = "misc"; tag = item.Trim(); } // Note: We've already converted cat to lowercase, so we just do straight == to shave time off #region FM tags CatAndTags?match = null; for (int i = 0; i < existingFMTags.Count; i++) { if (existingFMTags[i].Category == cat) { match = existingFMTags[i]; break; } } if (match == null) { existingFMTags.Add(new CatAndTags { Category = cat }); existingFMTags[existingFMTags.Count - 1].Tags.Add(tag); } else { if (!match.Tags.ContainsI(tag)) { match.Tags.Add(tag); } } #endregion #region Global tags GlobalCatAndTags?globalMatch = null; for (int i = 0; i < GlobalTags.Count; i++) { if (GlobalTags[i].Category.Name == cat) { globalMatch = GlobalTags[i]; break; } } if (globalMatch == null) { GlobalTags.Add(new GlobalCatAndTags { Category = new GlobalCatOrTag { Name = cat, UsedCount = 1 } }); GlobalTags[GlobalTags.Count - 1].Tags.Add(new GlobalCatOrTag { Name = tag, UsedCount = 1 }); } else { globalMatch.Category.UsedCount++; GlobalCatOrTag?ft = null; for (int i = 0; i < globalMatch.Tags.Count; i++) { if (globalMatch.Tags[i].Name.EqualsI(tag)) { ft = globalMatch.Tags[i]; break; } } if (ft == null) { globalMatch.Tags.Add(new GlobalCatOrTag { Name = tag, UsedCount = 1 }); } else { ft.UsedCount++; } } #endregion } }
internal static bool RemoveTagFromFM(FanMission fm, string catText, string tagText) { if (tagText.IsEmpty()) { return(false); } // Parent node (category) if (catText.IsEmpty()) { // TODO: These messageboxes are annoying, but they prevent accidental deletion. // Figure out something better. bool cont = Core.View.AskToContinue(LText.TagsTab.AskRemoveCategory, LText.TagsTab.TabText, true); if (!cont) { return(false); } CatAndTags?cat = fm.Tags.FirstOrDefault(x => x.Category == tagText); if (cat != null) { fm.Tags.Remove(cat); UpdateFMTagsString(fm); // TODO: Profile the FirstOrDefaults and see if I should make them for loops GlobalCatAndTags?globalCat = GlobalTags.FirstOrDefault(x => x.Category.Name == cat.Category); if (globalCat != null && !globalCat.Category.IsPreset) { if (globalCat.Category.UsedCount > 0) { globalCat.Category.UsedCount--; } if (globalCat.Category.UsedCount == 0) { GlobalTags.Remove(globalCat); } } } } // Child node (tag) else { bool cont = Core.View.AskToContinue(LText.TagsTab.AskRemoveTag, LText.TagsTab.TabText, true); if (!cont) { return(false); } CatAndTags?cat = fm.Tags.FirstOrDefault(x => x.Category == catText); string? tag = cat?.Tags.FirstOrDefault(x => x == tagText); if (tag != null) { cat !.Tags.Remove(tag); if (cat.Tags.Count == 0) { fm.Tags.Remove(cat); } UpdateFMTagsString(fm); GlobalCatAndTags?globalCat = GlobalTags.FirstOrDefault(x => x.Category.Name == cat.Category); GlobalCatOrTag? globalTag = globalCat?.Tags.FirstOrDefault(x => x.Name == tagText); if (globalTag != null && !globalTag.IsPreset) { if (globalTag.UsedCount > 0) { globalTag.UsedCount--; } if (globalTag.UsedCount == 0) { globalCat !.Tags.Remove(globalTag); } if (globalCat !.Tags.Count == 0) { GlobalTags.Remove(globalCat); } } } } Ini.WriteFullFMDataIni(); return(true); }
/// <summary> /// Initializes a new instance of the <see cref="TracerSettings"/> class /// using the specified <see cref="IConfigurationSource"/> to initialize values. /// </summary> /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param> public TracerSettings(IConfigurationSource source) { Environment = source?.GetString(ConfigurationKeys.Environment); ServiceName = source?.GetString(ConfigurationKeys.ServiceName) ?? // backwards compatibility for names used in the past source?.GetString("DD_SERVICE_NAME"); ServiceVersion = source?.GetString(ConfigurationKeys.ServiceVersion); TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ?? // default value true; var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations) ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? Enumerable.Empty <string>(); DisabledIntegrationNames = new HashSet <string>(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase); var agentHost = source?.GetString(ConfigurationKeys.AgentHost) ?? // backwards compatibility for names used in the past source?.GetString("DD_TRACE_AGENT_HOSTNAME") ?? source?.GetString("DATADOG_TRACE_AGENT_HOSTNAME") ?? // default value DefaultAgentHost; var agentPort = source?.GetInt32(ConfigurationKeys.AgentPort) ?? // backwards compatibility for names used in the past source?.GetInt32("DATADOG_TRACE_AGENT_PORT") ?? // default value DefaultAgentPort; var agentUri = source?.GetString(ConfigurationKeys.AgentUri) ?? // default value $"http://{agentHost}:{agentPort}"; AgentUri = new Uri(agentUri); AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ?? // default value false; LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ?? // default value false; var maxTracesPerSecond = source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond); if (maxTracesPerSecond != null) { // Ensure our flag for the rate limiter is enabled RuleBasedSampler.OptInTracingWithoutLimits(); } else { maxTracesPerSecond = 100; // default } MaxTracesSubmittedPerSecond = maxTracesPerSecond.Value; Integrations = new IntegrationSettingsCollection(source); GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ?? // backwards compatibility for names used in the past source?.GetDictionary("DD_TRACE_GLOBAL_TAGS") ?? // default value (empty) new ConcurrentDictionary <string, string>(); // Filter out tags with empty keys or empty values GlobalTags = GlobalTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); DogStatsdPort = source?.GetInt32(ConfigurationKeys.DogStatsdPort) ?? // default value 8125; TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ?? // default value false; CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules); GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate); DiagnosticSourceEnabled = source?.GetBool(ConfigurationKeys.DiagnosticSourceEnabled) ?? // default value true; }
/// <summary> /// Initializes a new instance of the <see cref="TracerSettings"/> class /// using the specified <see cref="IConfigurationSource"/> to initialize values. /// </summary> /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param> public TracerSettings(IConfigurationSource source) { Environment = source?.GetString(ConfigurationKeys.Environment); ServiceName = source?.GetString(ConfigurationKeys.ServiceName); ServiceVersion = source?.GetString(ConfigurationKeys.ServiceVersion); SignalFxAccessToken = source?.GetString(ConfigurationKeys.SignalFxAccessToken); TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ?? // default value true; if (AzureAppServices.Metadata.IsRelevant && AzureAppServices.Metadata.IsUnsafeToTrace) { TraceEnabled = false; } DisabledIntegrationNames = new HashSet <string>(source.GetStrings(ConfigurationKeys.DisabledIntegrations), StringComparer.OrdinalIgnoreCase); Integrations = new IntegrationSettingsCollection(source); ExporterSettings = new ExporterSettings(source); #pragma warning disable 618 // App analytics is deprecated, but still used AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ?? // default value false; #pragma warning restore 618 MaxTracesSubmittedPerSecond = source?.GetInt32(ConfigurationKeys.TraceRateLimit) ?? // default value 100; GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ?? // default value (empty) new ConcurrentDictionary <string, string>(); // Filter out tags with empty keys or empty values, and trim whitespace GlobalTags = GlobalTags.Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key) && !string.IsNullOrWhiteSpace(kvp.Value)) .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); var inputHeaderTags = source?.GetDictionary(ConfigurationKeys.HeaderTags, allowOptionalMappings: true) ?? // default value (empty) new Dictionary <string, string>(); var headerTagsNormalizationFixEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.HeaderTagsNormalizationFixEnabled) ?? true; // Filter out tags with empty keys or empty values, and trim whitespaces HeaderTags = InitializeHeaderTags(inputHeaderTags, headerTagsNormalizationFixEnabled); var serviceNameMappings = source?.GetDictionary(ConfigurationKeys.ServiceNameMappings) ?.Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key) && !string.IsNullOrWhiteSpace(kvp.Value)) ?.ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); ServiceNameMappings = new ServiceNames(serviceNameMappings); TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ?? // default value false; TagRedisCommands = source?.GetBool(ConfigurationKeys.TagRedisCommands) ?? // default value true; RuntimeMetricsEnabled = source?.GetBool(ConfigurationKeys.RuntimeMetricsEnabled) ?? false; CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules); GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate); StartupDiagnosticLogEnabled = source?.GetBool(ConfigurationKeys.StartupDiagnosticLogEnabled) ?? // default value true; Exporter = source.GetTypedValue <ExporterType>(ConfigurationKeys.Exporter); Convention = source.GetTypedValue <ConventionType>(ConfigurationKeys.Convention); var urlSubstringSkips = source?.GetString(ConfigurationKeys.HttpClientExcludedUrlSubstrings) ?? // default value (AzureAppServices.Metadata.IsRelevant ? AzureAppServices.Metadata.DefaultHttpClientExclusions : null); if (urlSubstringSkips != null) { HttpClientExcludedUrlSubstrings = TrimSplitString(urlSubstringSkips.ToUpperInvariant(), ',').ToArray(); } var httpServerErrorStatusCodes = source?.GetString(ConfigurationKeys.HttpServerErrorStatusCodes) ?? // Default value "500-599"; HttpServerErrorStatusCodes = ParseHttpCodesToArray(httpServerErrorStatusCodes); var httpClientErrorStatusCodes = source?.GetString(ConfigurationKeys.HttpClientErrorStatusCodes) ?? // Default value "400-599"; HttpClientErrorStatusCodes = ParseHttpCodesToArray(httpClientErrorStatusCodes); TraceBufferSize = source?.GetInt32(ConfigurationKeys.BufferSize) ?? 1024 * 1024 * 10; // 10MB TraceBatchInterval = source?.GetInt32(ConfigurationKeys.SerializationBatchInterval) ?? 100; RecordedValueMaxLength = source.SafeReadInt32( key: ConfigurationKeys.RecordedValueMaxLength, defaultTo: DefaultRecordedValueMaxLength, validators: (value) => value >= 0); RouteTemplateResourceNamesEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.RouteTemplateResourceNamesEnabled) ?? true; TraceResponseHeaderEnabled = source?.GetBool(ConfigurationKeys.TraceResponseHeaderEnabled) ?? true; ExpandRouteTemplatesEnabled = source?.GetBool(ConfigurationKeys.ExpandRouteTemplatesEnabled) // disabled by default if route template resource names enabled ?? !RouteTemplateResourceNamesEnabled; KafkaCreateConsumerScopeEnabled = source?.GetBool(ConfigurationKeys.KafkaCreateConsumerScopeEnabled) ?? true; // default TagMongoCommands = source?.GetBool(ConfigurationKeys.TagMongoCommands) ?? true; DelayWcfInstrumentationEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.DelayWcfInstrumentationEnabled) ?? false; PropagationStyleInject = TrimSplitString(source?.GetString(ConfigurationKeys.Propagators) ?? $"{nameof(Propagators.ContextPropagators.Names.B3)},{nameof(Propagators.ContextPropagators.Names.W3C)}", ',').ToArray(); PropagationStyleExtract = PropagationStyleInject; TagElasticsearchQueries = source?.GetBool(ConfigurationKeys.TagElasticsearchQueries) ?? true; // If you change this, change environment_variables.h too ThreadSamplingEnabled = source?.GetBool(ConfigurationKeys.AlwaysOnProfiler.Enabled) ?? false; ThreadSamplingPeriod = GetThreadSamplingPeriod(source); LogSubmissionSettings = new DirectLogSubmissionSettings(source); TraceMethods = source?.GetString(ConfigurationKeys.TraceMethods) ?? // Default value string.Empty; var grpcTags = source?.GetDictionary(ConfigurationKeys.GrpcTags, allowOptionalMappings: true) ?? // default value (empty) new Dictionary <string, string>(); // Filter out tags with empty keys or empty values, and trim whitespaces GrpcTags = InitializeHeaderTags(grpcTags, headerTagsNormalizationFixEnabled: true); IsActivityListenerEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.ActivityListenerEnabled) ?? // default value false; if (IsActivityListenerEnabled) { // If the activities support is activated, we must enable W3C propagators if (!Array.Exists(PropagationStyleExtract, key => string.Equals(key, nameof(Propagators.ContextPropagators.Names.W3C), StringComparison.OrdinalIgnoreCase))) { PropagationStyleExtract = PropagationStyleExtract.Concat(nameof(Propagators.ContextPropagators.Names.W3C)); } if (!Array.Exists(PropagationStyleInject, key => string.Equals(key, nameof(Propagators.ContextPropagators.Names.W3C), StringComparison.OrdinalIgnoreCase))) { PropagationStyleInject = PropagationStyleInject.Concat(nameof(Propagators.ContextPropagators.Names.W3C)); } } }
/// <summary> /// Initializes a new instance of the <see cref="TracerSettings"/> class /// using the specified <see cref="IConfigurationSource"/> to initialize values. /// </summary> /// <param name="source">The <see cref="IConfigurationSource"/> to use when retrieving configuration values.</param> public TracerSettings(IConfigurationSource source) { Environment = source?.GetString(ConfigurationKeys.Environment); ServiceName = source?.GetString(ConfigurationKeys.ServiceName) ?? // backwards compatibility for names used in the past source?.GetString("DD_SERVICE_NAME"); ServiceVersion = source?.GetString(ConfigurationKeys.ServiceVersion); TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ?? // default value true; if (AzureAppServices.Metadata.IsRelevant && AzureAppServices.Metadata.IsUnsafeToTrace) { TraceEnabled = false; } var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations) ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? Enumerable.Empty <string>(); DisabledIntegrationNames = new HashSet <string>(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase); Integrations = new IntegrationSettingsCollection(source); Exporter = new ExporterSettings(source); #pragma warning disable 618 // App analytics is deprecated, but still used AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ?? // default value false; #pragma warning restore 618 LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ?? // default value false; MaxTracesSubmittedPerSecond = source?.GetInt32(ConfigurationKeys.TraceRateLimit) ?? #pragma warning disable 618 // this parameter has been replaced but may still be used source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond) ?? #pragma warning restore 618 // default value 100; GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ?? // backwards compatibility for names used in the past source?.GetDictionary("DD_TRACE_GLOBAL_TAGS") ?? // default value (empty) new ConcurrentDictionary <string, string>(); // Filter out tags with empty keys or empty values, and trim whitespace GlobalTags = GlobalTags.Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key) && !string.IsNullOrWhiteSpace(kvp.Value)) .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); var inputHeaderTags = source?.GetDictionary(ConfigurationKeys.HeaderTags, allowOptionalMappings: true) ?? // default value (empty) new Dictionary <string, string>(); var headerTagsNormalizationFixEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.HeaderTagsNormalizationFixEnabled) ?? true; // Filter out tags with empty keys or empty values, and trim whitespaces HeaderTags = InitializeHeaderTags(inputHeaderTags, headerTagsNormalizationFixEnabled); var serviceNameMappings = source?.GetDictionary(ConfigurationKeys.ServiceNameMappings) ?.Where(kvp => !string.IsNullOrWhiteSpace(kvp.Key) && !string.IsNullOrWhiteSpace(kvp.Value)) ?.ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); ServiceNameMappings = new ServiceNames(serviceNameMappings); TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ?? // default value false; RuntimeMetricsEnabled = source?.GetBool(ConfigurationKeys.RuntimeMetricsEnabled) ?? false; CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules); GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate); StartupDiagnosticLogEnabled = source?.GetBool(ConfigurationKeys.StartupDiagnosticLogEnabled) ?? // default value true; var urlSubstringSkips = source?.GetString(ConfigurationKeys.HttpClientExcludedUrlSubstrings) ?? // default value (AzureAppServices.Metadata.IsRelevant ? AzureAppServices.Metadata.DefaultHttpClientExclusions : null); if (urlSubstringSkips != null) { HttpClientExcludedUrlSubstrings = TrimSplitString(urlSubstringSkips.ToUpperInvariant(), ',').ToArray(); } var httpServerErrorStatusCodes = source?.GetString(ConfigurationKeys.HttpServerErrorStatusCodes) ?? // Default value "500-599"; HttpServerErrorStatusCodes = ParseHttpCodesToArray(httpServerErrorStatusCodes); var httpClientErrorStatusCodes = source?.GetString(ConfigurationKeys.HttpClientErrorStatusCodes) ?? // Default value "400-499"; HttpClientErrorStatusCodes = ParseHttpCodesToArray(httpClientErrorStatusCodes); TraceBufferSize = source?.GetInt32(ConfigurationKeys.BufferSize) ?? 1024 * 1024 * 10; // 10MB TraceBatchInterval = source?.GetInt32(ConfigurationKeys.SerializationBatchInterval) ?? 100; RouteTemplateResourceNamesEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.RouteTemplateResourceNamesEnabled) ?? true; ExpandRouteTemplatesEnabled = source?.GetBool(ConfigurationKeys.ExpandRouteTemplatesEnabled) // disabled by default if route template resource names enabled ?? !RouteTemplateResourceNamesEnabled; KafkaCreateConsumerScopeEnabled = source?.GetBool(ConfigurationKeys.KafkaCreateConsumerScopeEnabled) ?? true; // default DelayWcfInstrumentationEnabled = source?.GetBool(ConfigurationKeys.FeatureFlags.DelayWcfInstrumentationEnabled) ?? false; PropagationStyleInject = TrimSplitString(source?.GetString(ConfigurationKeys.PropagationStyleInject) ?? nameof(Propagators.ContextPropagators.Names.Datadog), ',').ToArray(); PropagationStyleExtract = TrimSplitString(source?.GetString(ConfigurationKeys.PropagationStyleExtract) ?? nameof(Propagators.ContextPropagators.Names.Datadog), ',').ToArray(); LogSubmissionSettings = new DirectLogSubmissionSettings(source); }