Esempio n. 1
0
        // 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;
        }
Esempio n. 3
0
        // 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
            }
        }
Esempio n. 4
0
        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;
        }
Esempio n. 6
0
        /// <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));
                }
            }
        }
Esempio n. 7
0
        /// <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);
        }