Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -73,69 +73,10 @@ internal static void ConfigureSettingsWithManualOverrides(Dictionary<string, obj
? new ManualInstrumentationLegacyConfigurationSource(values, isFromDefaults)
: new ManualInstrumentationConfigurationSource(values, isFromDefaults);

// We need to save this immediately, even if there's no manifest changes in the final settings
GlobalConfigurationSource.UpdateManualConfigurationSource(manualConfig);

var tracerSettings = Datadog.Trace.Tracer.Instance.Settings;
var dynamicConfig = GlobalConfigurationSource.DynamicConfigurationSource;
var initialSettings = isFromDefaults
? tracerSettings.InitialMutableSettings
: MutableSettings.CreateWithoutDefaultSources(tracerSettings);

// TODO: these will eventually live elsewhere
var currentSettings = tracerSettings.MutableSettings;

var manualTelemetry = new ConfigurationTelemetry();
var newMutableSettings = MutableSettings.CreateUpdatedMutableSettings(
dynamicConfig,
manualConfig,
initialSettings,
tracerSettings,
manualTelemetry,
new OverrideErrorLog()); // TODO: We'll later report these

var isSameMutableSettings = currentSettings.Equals(newMutableSettings);

// The only exporter setting we currently _allow_ to change is the AgentUri, but if that does change,
// it can mean that _everything_ about the exporter settings changes. To minimize the work to do, and
// to simplify comparisons, we try to read the agent url from the manual setting. If it's missing, not
// set, or unchanged, there's no need to update the exporter settings. In the future, ExporterSettings
// will live separate from TracerSettings entirely.
var exporterTelemetry = new ConfigurationTelemetry();
var newRawExporterSettings = ExporterSettings.Raw.CreateUpdatedFromManualConfig(
tracerSettings.Exporter.RawSettings,
manualConfig,
exporterTelemetry,
isFromDefaults);
var isSameExporterSettings = tracerSettings.Exporter.RawSettings.Equals(newRawExporterSettings);

if (isSameMutableSettings && isSameExporterSettings)
var wasUpdated = Datadog.Trace.Tracer.Instance.Settings.Manager.UpdateManualConfigurationSettings(manualConfig, TelemetryFactory.Config);
if (wasUpdated)
{
Log.Debug("No changes detected in the new configuration in code");
// Even though there were no "real" changes, there may be _effective_ changes in telemetry that
// need to be recorded (e.g. the customer set the value in code but it was already set via
// env vars). We _should_ record exporter settings too, but that introduces a bunch of complexity
// which we'll resolve later anyway, so just have that gap for now (it's very niche).
// If there are changes, they're recorded automatically in ConfigureInternal
manualTelemetry.CopyTo(TelemetryFactory.Config);
return;
Log.Information("Setting updates made via configuration in code were applied");
}

Log.Information("Applying new configuration in code");
TracerSettings newSettings;
if (isSameExporterSettings)
{
newSettings = tracerSettings with { MutableSettings = newMutableSettings };
}
else
{
var exporterSettings = new ExporterSettings(newRawExporterSettings, exporterTelemetry);
newSettings = isSameMutableSettings
? tracerSettings with { Exporter = exporterSettings }
: tracerSettings with { MutableSettings = newMutableSettings, Exporter = exporterSettings };
}

// Update the global instance
Trace.Tracer.Configure(newSettings);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,13 @@ namespace Datadog.Trace.Configuration;
/// </summary>
internal class GlobalConfigurationSource
{
private static IConfigurationSource _dynamicConfigConfigurationSource = NullConfigurationSource.Instance;
private static ManualInstrumentationConfigurationSourceBase _manualConfigurationSource = new ManualInstrumentationConfigurationSource(new Dictionary<string, object?>(), useDefaultSources: true);

/// <summary>
/// Gets the configuration source instance.
/// </summary>
internal static IConfigurationSource Instance => CreationResult.ConfigurationSource;

internal static GlobalConfigurationSourceResult CreationResult { get; private set; } = CreateDefaultConfigurationSource();

internal static IConfigurationSource DynamicConfigurationSource => _dynamicConfigConfigurationSource;

internal static ManualInstrumentationConfigurationSourceBase ManualConfigurationSource => _manualConfigurationSource;

/// <summary>
/// Creates a <see cref="IConfigurationSource"/> by combining environment variables,
/// Precedence is as follows:
Expand Down Expand Up @@ -142,14 +135,4 @@ private static string GetCurrentDirectory()
{
return AppDomain.CurrentDomain.BaseDirectory ?? Directory.GetCurrentDirectory();
}

public static void UpdateDynamicConfigConfigurationSource(IConfigurationSource dynamic)
{
Interlocked.Exchange(ref _dynamicConfigConfigurationSource, dynamic);
}

public static void UpdateManualConfigurationSource(ManualInstrumentationConfigurationSourceBase manual)
{
Interlocked.Exchange(ref _manualConfigurationSource, manual);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using System.Threading;
using System.Threading.Tasks;
using Datadog.Trace.Configuration.ConfigurationSources;
using Datadog.Trace.Configuration.ConfigurationSources.Telemetry;
using Datadog.Trace.Configuration.Telemetry;
using Datadog.Trace.Debugger;
using Datadog.Trace.Debugger.Configurations;
Expand Down Expand Up @@ -68,79 +67,17 @@ public void Dispose()
}
}

internal static void OnlyForTests_ApplyConfiguration(IConfigurationSource dynamicConfig)
internal static void OnlyForTests_ApplyConfiguration(IConfigurationSource dynamicConfig, TracerSettings tracerSettings)
{
OnConfigurationChanged(dynamicConfig);
OnConfigurationChanged(dynamicConfig, tracerSettings);
}

private static void OnConfigurationChanged(IConfigurationSource dynamicConfig)
private static void OnConfigurationChanged(IConfigurationSource dynamicConfig, TracerSettings tracerSettings)
{
var tracerSettings = Tracer.Instance.Settings;
var manualSource = GlobalConfigurationSource.ManualConfigurationSource;
var mutableSettings = manualSource.UseDefaultSources
? tracerSettings.InitialMutableSettings
: MutableSettings.CreateWithoutDefaultSources(tracerSettings);

// We save this immediately, even if there's no manifest changes in the final settings
GlobalConfigurationSource.UpdateDynamicConfigConfigurationSource(dynamicConfig);

OnConfigurationChanged(
dynamicConfig,
manualSource,
mutableSettings,
tracerSettings,
// TODO: In the future this will 'live' elsewhere
currentSettings: tracerSettings.MutableSettings,
new ConfigurationTelemetry(),
new OverrideErrorLog()); // TODO: We'll later report these
}

private static void OnConfigurationChanged(
IConfigurationSource dynamicConfig,
ManualInstrumentationConfigurationSourceBase manualConfig,
MutableSettings initialSettings,
TracerSettings tracerSettings,
MutableSettings currentSettings,
ConfigurationTelemetry telemetry,
OverrideErrorLog errorLog)
{
var newMutableSettings = MutableSettings.CreateUpdatedMutableSettings(
dynamicConfig,
manualConfig,
initialSettings,
tracerSettings,
telemetry,
errorLog);

TracerSettings newSettings;
if (currentSettings.Equals(newMutableSettings))
{
Log.Debug("No changes detected in the new dynamic configuration");
// Even though there were no "real" changes, there may be _effective_ changes in telemetry that
// need to be recorded (e.g. the customer set the value in code but it was already set via
// env vars). We _should_ record exporter settings too, but that introduces a bunch of complexity
// which we'll resolve later anyway, so just have that gap for now (it's very niche).
// If there are changes, they're recorded automatically in Tracer.Configure()
telemetry.CopyTo(TelemetryFactory.Config);
newSettings = tracerSettings;
}
else
var wasUpdated = tracerSettings.Manager.UpdateDynamicConfigurationSettings(dynamicConfig, TelemetryFactory.Config);
if (wasUpdated)
{
Log.Information("Applying new dynamic configuration");

newSettings = tracerSettings with { MutableSettings = newMutableSettings };

/*
if (debugLogsEnabled != null && debugLogsEnabled.Value != GlobalSettings.Instance.DebugEnabled)
{
GlobalSettings.SetDebugEnabled(debugLogsEnabled.Value);
Security.Instance.SetDebugEnabled(debugLogsEnabled.Value);

NativeMethods.UpdateSettings(new[] { ConfigurationKeys.DebugEnabled }, new[] { debugLogsEnabled.Value ? "1" : "0" });
}
*/

Tracer.Configure(newSettings);
Log.Information("Setting updates made via dynamic configuration were applied");
}

// TODO: This might not record the config in the correct order in future, but would require
Expand Down Expand Up @@ -173,7 +110,7 @@ private static void OnConfigurationChanged(

var newDebuggerSettings = oldDebuggerSettings with { DynamicSettings = dynamicDebuggerSettings };

DebuggerManager.Instance.UpdateConfiguration(newSettings, newDebuggerSettings)
DebuggerManager.Instance.UpdateConfiguration(Tracer.Instance.Settings, newDebuggerSettings)
.ContinueWith(t => Log.Error(t?.Exception, "Error updating dynamic configuration for debugger"), TaskContinuationOptions.OnlyOnFaulted);
}

Expand Down Expand Up @@ -247,7 +184,8 @@ private ApplyDetails[] ConfigurationUpdated(
private void ApplyMergedConfiguration(List<RemoteConfiguration> remoteConfigurations)
{
// Get current service/environment for filtering
var currentSettings = Tracer.Instance.CurrentTraceSettings.Settings;
var tracer = Tracer.Instance;
var currentSettings = tracer.CurrentTraceSettings.Settings;

var mergedConfigJToken = ApmTracingConfigMerger.MergeConfigurations(
remoteConfigurations,
Expand All @@ -256,7 +194,7 @@ private void ApplyMergedConfiguration(List<RemoteConfiguration> remoteConfigurat

var configurationSource = new DynamicConfigConfigurationSource(mergedConfigJToken, ConfigurationOrigins.RemoteConfig);

OnConfigurationChanged(configurationSource);
OnConfigurationChanged(configurationSource, tracer.Settings);
}
}
}
7 changes: 7 additions & 0 deletions tracer/src/Datadog.Trace/Configuration/MutableSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,13 @@ public static MutableSettings CreateWithoutDefaultSources(TracerSettings tracerS
new OverrideErrorLog(),
tracerSettings);

public static MutableSettings CreateForTesting(TracerSettings tracerSettings, Dictionary<string, object?> settings)
=> CreateInitialMutableSettings(
new DictionaryConfigurationSource(settings.ToDictionary(x => x.Key, x => x.Value?.ToString()!)),
new ConfigurationTelemetry(),
new OverrideErrorLog(),
tracerSettings);

private static ConfigurationBuilder.ClassConfigurationResultWithKey<IDictionary<string, string>> RemapOtelTags(
in ConfigurationBuilder.ClassConfigurationResultWithKey<IDictionary<string, string>> original)
{
Expand Down
Loading
Loading