Skip to content

Commit 53a55c1

Browse files
Tracer configuration system (managed code) (DataDog#289)
* add IConfigurationSource and several implementations * add assembly and nuget references * initialize a configuration source * add xml-doc comments, rename ConfigurationSource to StringConfigurationSource * reorder configuration sources * move private method further down to make StyleCop happy * allow initializer syntax by renaming method to `Add()` and implementing `IEnumerable` * add `YamlConfigurationSource` * rewrite `CreateConfigurationSource()` * fix build errors from last merge * use ConfigurationSource for default service name * remove yaml configuration (we can provide as separate nuget later if needed) * add constants for standard configuration keys and a strongly-typed configuration wrapper around IConfigurationSource * refactor Tracer to use an IConfigurationSource for all its configuration needs, simplfy the Create() overloads and several constructors * rename AggregateConfigurationSource to CompositeConfigurationSource * use the new "default" syntax; reformat code * add comments and a parameterless constructor * move another constant to ConfigurationKeys * fix compiler errors in unit tests * use default configuration in Tracer.Create() * add additional settings * rename CreateAgentUri() to GetAgentUri() * refactor Configuration to read all value in ctor and not keep the IConfigurationSource reference * rename Configuration to TracerConfiguration * refactor Tracer ctor to take a Configuration instead of IConfigurationSource * fix compiler errors in test project * rename Configuration to TracerConfiguration * move CreateDefaultConfigurationSource() from Tracer to TracerConfiguration * use TracerConfiguration.FromDefaultSources() where possible * add IScopeManager * split ctor into public and internal to allow injecting dependencies * rename TracerConfiguration to TracerSettings * add constants for default values * fix compiler errors * remove unused SimpleSampler * initialize Tracer.Instance with default configuration sources * revert change so we ensure we return null * fix unit tests * fix comment * fix xml doc comments * add new DD_TRACE_AGENT_URL setting * merge AgentHost and AgentPort into AgentUri
1 parent b761d95 commit 53a55c1

24 files changed

+710
-205
lines changed

src/Datadog.Trace.OpenTracing/OpenTracingTracer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public OpenTracingTracer(IDatadogTracer datadogTracer)
1717
{
1818
}
1919

20-
public OpenTracingTracer(IDatadogTracer datadogTracer, IScopeManager scopeManager)
20+
public OpenTracingTracer(IDatadogTracer datadogTracer, global::OpenTracing.IScopeManager scopeManager)
2121
{
2222
DatadogTracer = datadogTracer;
2323
DefaultServiceName = datadogTracer.DefaultServiceName;
@@ -29,7 +29,7 @@ public OpenTracingTracer(IDatadogTracer datadogTracer, IScopeManager scopeManage
2929

3030
public string DefaultServiceName { get; }
3131

32-
public IScopeManager ScopeManager { get; }
32+
public global::OpenTracing.IScopeManager ScopeManager { get; }
3333

3434
public OpenTracingSpan ActiveSpan => (OpenTracingSpan)ScopeManager.Active?.Span;
3535

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
using System;
22
using System.Net.Http;
3-
using Datadog.Trace.Agent;
4-
using Datadog.Trace.Sampling;
53
using OpenTracing;
64

75
namespace Datadog.Trace.OpenTracing
@@ -11,8 +9,6 @@ namespace Datadog.Trace.OpenTracing
119
/// </summary>
1210
public static class OpenTracingTracerFactory
1311
{
14-
private static Uri _defaultUri = new Uri("http://localhost:8126");
15-
1612
/// <summary>
1713
/// Create a new Datadog compatible ITracer implementation with the given parameters
1814
/// </summary>
@@ -22,18 +18,13 @@ public static class OpenTracingTracerFactory
2218
/// <returns>A Datadog compatible ITracer implementation</returns>
2319
public static ITracer CreateTracer(Uri agentEndpoint = null, string defaultServiceName = null, bool isDebugEnabled = false)
2420
{
25-
agentEndpoint = agentEndpoint ?? _defaultUri;
2621
return CreateTracer(agentEndpoint, defaultServiceName, null, isDebugEnabled);
2722
}
2823

29-
internal static OpenTracingTracer CreateTracer(Uri agentEndpoint, string defaultServiceName = null, DelegatingHandler delegatingHandler = null, bool isDebugEnabled = false)
24+
internal static OpenTracingTracer CreateTracer(Uri agentEndpoint, string defaultServiceName, DelegatingHandler delegatingHandler, bool isDebugEnabled)
3025
{
31-
var api = new Api(agentEndpoint, delegatingHandler);
32-
var agentWriter = new AgentWriter(api);
33-
var sampler = new RateByServiceSampler();
34-
var ddTracer = new Tracer(agentWriter, sampler, defaultServiceName, isDebugEnabled);
35-
var tracer = new OpenTracingTracer(ddTracer);
36-
return tracer;
26+
var tracer = Tracer.Create(agentEndpoint, defaultServiceName, isDebugEnabled);
27+
return new OpenTracingTracer(tracer);
3728
}
3829
}
3930
}

src/Datadog.Trace/AsyncLocalScopeManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
namespace Datadog.Trace
44
{
5-
internal class AsyncLocalScopeManager
5+
internal class AsyncLocalScopeManager : IScopeManager
66
{
77
private static readonly ILog Log = LogProvider.For<AsyncLocalScopeManager>();
88

99
private readonly AsyncLocalCompat<Scope> _activeScope = new AsyncLocalCompat<Scope>();
1010

1111
public Scope Active => _activeScope.Get();
1212

13-
public Scope Activate(Span span, bool finishOnClose = true)
13+
public Scope Activate(Span span, bool finishOnClose)
1414
{
1515
var activeScope = _activeScope.Get();
1616
var scope = new Scope(activeScope, span, this, finishOnClose);
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace Datadog.Trace.Configuration
7+
{
8+
/// <summary>
9+
/// Represents one or more configuration sources.
10+
/// </summary>
11+
public class CompositeConfigurationSource : IConfigurationSource, IEnumerable<IConfigurationSource>
12+
{
13+
private readonly List<IConfigurationSource> _sources = new List<IConfigurationSource>();
14+
15+
/// <summary>
16+
/// Adds a new configuration source to this instance.
17+
/// </summary>
18+
/// <param name="source">The configuration source to add.</param>
19+
public void Add(IConfigurationSource source)
20+
{
21+
if (source == null) { throw new ArgumentNullException(nameof(source)); }
22+
23+
_sources.Add(source);
24+
}
25+
26+
/// <summary>
27+
/// Inserts an element into the <see cref="CompositeConfigurationSource"/> at the specified index.
28+
/// </summary>
29+
/// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
30+
/// <param name="item">The configuration source to insert.</param>
31+
public void Insert(int index, IConfigurationSource item)
32+
{
33+
if (item == null) { throw new ArgumentNullException(nameof(item)); }
34+
35+
_sources.Insert(index, item);
36+
}
37+
38+
/// <summary>
39+
/// Gets the <see cref="string"/> value of the first setting found with
40+
/// the specified key from the current list of configuration sources.
41+
/// Sources are queried in the order in which they were added.
42+
/// </summary>
43+
/// <param name="key">The key that identifies the setting.</param>
44+
/// <returns>The value of the setting, or null if not found.</returns>
45+
public string GetString(string key)
46+
{
47+
return _sources.Select(source => source.GetString(key))
48+
.FirstOrDefault(value => value != null);
49+
}
50+
51+
/// <summary>
52+
/// Gets the <see cref="int"/> value of the first setting found with
53+
/// the specified key from the current list of configuration sources.
54+
/// Sources are queried in the order in which they were added.
55+
/// </summary>
56+
/// <param name="key">The key that identifies the setting.</param>
57+
/// <returns>The value of the setting, or null if not found.</returns>
58+
public int? GetInt32(string key)
59+
{
60+
return _sources.Select(source => source.GetInt32(key))
61+
.FirstOrDefault(value => value != null);
62+
}
63+
64+
/// <summary>
65+
/// Gets the <see cref="bool"/> value of the first setting found with
66+
/// the specified key from the current list of configuration sources.
67+
/// Sources are queried in the order in which they were added.
68+
/// </summary>
69+
/// <param name="key">The key that identifies the setting.</param>
70+
/// <returns>The value of the setting, or null if not found.</returns>
71+
public bool? GetBool(string key)
72+
{
73+
return _sources.Select(source => source.GetBool(key))
74+
.FirstOrDefault(value => value != null);
75+
}
76+
77+
/// <inheritdoc />
78+
IEnumerator<IConfigurationSource> IEnumerable<IConfigurationSource>.GetEnumerator()
79+
{
80+
return _sources.GetEnumerator();
81+
}
82+
83+
/// <inheritdoc />
84+
IEnumerator IEnumerable.GetEnumerator()
85+
{
86+
return _sources.GetEnumerator();
87+
}
88+
}
89+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
namespace Datadog.Trace.Configuration
2+
{
3+
/// <summary>
4+
/// String constants for standard Datadog configuration keys.
5+
/// </summary>
6+
public static class ConfigurationKeys
7+
{
8+
/// <summary>
9+
/// Configuration key for the path to the configuration file.
10+
/// Can only be set with an environment variable.
11+
/// </summary>
12+
public const string ConfigurationFileName = "DD_DOTNET_TRACER_CONFIG_FILE";
13+
14+
/// <summary>
15+
/// Configuration key for the application's environment. Sets the "env" tag on every <see cref="Span"/>.
16+
/// </summary>
17+
public const string Environment = "DD_ENV";
18+
19+
/// <summary>
20+
/// Configuration key for the application's default service name.
21+
/// Used as the service name for top-level spans,
22+
/// and used to determine service name of some child spans.
23+
/// </summary>
24+
public const string ServiceName = "DD_SERVICE_NAME";
25+
26+
/// <summary>
27+
/// Configuration key for enabling or disabling the Tracer.
28+
/// Default is enabled.
29+
/// </summary>
30+
public const string TraceEnabled = "DD_TRACE_ENABLED";
31+
32+
/// <summary>
33+
/// Configuration key for enabling or disabling the Tracer's debug mode.
34+
/// Default is disabled.
35+
/// </summary>
36+
public const string DebugEnabled = "DD_TRACE_DEBUG";
37+
38+
/// <summary>
39+
/// Configuration key for a list of integrations to disable. All other integrations remain enabled.
40+
/// Default is empty (all integrations are enabled).
41+
/// Supports multiple values separated with semi-colons.
42+
/// </summary>
43+
public const string DisabledIntegrations = "DD_DISABLED_INTEGRATIONS";
44+
45+
/// <summary>
46+
/// Configuration key for the Agent host where the Tracer can send traces.
47+
/// Default is "localhost".
48+
/// </summary>
49+
public const string AgentHost = "DD_AGENT_HOST";
50+
51+
/// <summary>
52+
/// Configuration key for the Agent port where the Tracer can send traces.
53+
/// Default is 8126.
54+
/// </summary>
55+
public const string AgentPort = "DD_TRACE_AGENT_PORT";
56+
57+
/// <summary>
58+
/// Configuration key for the Agent URL where the Tracer can send traces.
59+
/// Default is "http://localhost:8126".
60+
/// </summary>
61+
public const string AgentUri = "DD_TRACE_AGENT_URL";
62+
}
63+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace Datadog.Trace.Configuration
4+
{
5+
/// <summary>
6+
/// Represents a configuration source that
7+
/// retrieves values from environment variables.
8+
/// </summary>
9+
public class EnvironmentConfigurationSource : StringConfigurationSource
10+
{
11+
/// <inheritdoc />
12+
public override string GetString(string key)
13+
{
14+
return Environment.GetEnvironmentVariable(key);
15+
}
16+
}
17+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
3+
namespace Datadog.Trace.Configuration
4+
{
5+
/// <summary>
6+
/// A source of configuration settings, identifiable by a string key.
7+
/// </summary>
8+
public interface IConfigurationSource
9+
{
10+
/// <summary>
11+
/// Gets the <see cref="string"/> value of
12+
/// the setting with the specified key.
13+
/// </summary>
14+
/// <param name="key">The key that identifies the setting.</param>
15+
/// <returns>The value of the setting, or null if not found.</returns>
16+
string GetString(string key);
17+
18+
/// <summary>
19+
/// Gets the <see cref="int"/> value of
20+
/// the setting with the specified key.
21+
/// </summary>
22+
/// <param name="key">The key that identifies the setting.</param>
23+
/// <returns>The value of the setting, or null if not found.</returns>
24+
int? GetInt32(string key);
25+
26+
/// <summary>
27+
/// Gets the <see cref="bool"/> value of
28+
/// the setting with the specified key.
29+
/// </summary>
30+
/// <param name="key">The key that identifies the setting.</param>
31+
/// <returns>The value of the setting, or null if not found.</returns>
32+
bool? GetBool(string key);
33+
}
34+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.IO;
2+
using Newtonsoft.Json;
3+
using Newtonsoft.Json.Linq;
4+
5+
namespace Datadog.Trace.Configuration
6+
{
7+
/// <summary>
8+
/// Represents a configuration source that retrieves
9+
/// values from the provided JSON string.
10+
/// </summary>
11+
public class JsonConfigurationSource : IConfigurationSource
12+
{
13+
private readonly JObject _configuration;
14+
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="JsonConfigurationSource"/>
17+
/// class with the specified JSON string.
18+
/// </summary>
19+
/// <param name="json">A JSON string that contains configuration values.</param>
20+
public JsonConfigurationSource(string json)
21+
{
22+
_configuration = (JObject)JsonConvert.DeserializeObject(json);
23+
}
24+
25+
/// <summary>
26+
/// Creates a new <see cref="JsonConfigurationSource"/> instance
27+
/// by loading the JSON string from the specified file.
28+
/// </summary>
29+
/// <param name="filename">A JSON file that contains configuration values.</param>
30+
/// <returns>The newly created configuration source.</returns>
31+
public static JsonConfigurationSource LoadFile(string filename)
32+
{
33+
string json = File.ReadAllText(filename);
34+
return new JsonConfigurationSource(json);
35+
}
36+
37+
/// <summary>
38+
/// Gets the <see cref="string"/> value of
39+
/// the setting with the specified key.
40+
/// Supports JPath.
41+
/// </summary>
42+
/// <param name="key">The key that identifies the setting.</param>
43+
/// <returns>The value of the setting, or null if not found.</returns>
44+
string IConfigurationSource.GetString(string key)
45+
{
46+
return GetValue<string>(key);
47+
}
48+
49+
/// <summary>
50+
/// Gets the <see cref="int"/> value of
51+
/// the setting with the specified key.
52+
/// Supports JPath.
53+
/// </summary>
54+
/// <param name="key">The key that identifies the setting.</param>
55+
/// <returns>The value of the setting, or null if not found.</returns>
56+
int? IConfigurationSource.GetInt32(string key)
57+
{
58+
return GetValue<int?>(key);
59+
}
60+
61+
/// <summary>
62+
/// Gets the <see cref="bool"/> value of
63+
/// the setting with the specified key.
64+
/// Supports JPath.
65+
/// </summary>
66+
/// <param name="key">The key that identifies the setting.</param>
67+
/// <returns>The value of the setting, or null if not found.</returns>
68+
bool? IConfigurationSource.GetBool(string key)
69+
{
70+
return GetValue<bool?>(key);
71+
}
72+
73+
private T GetValue<T>(string key)
74+
{
75+
JToken token = _configuration.SelectToken(key, errorWhenNoMatch: false);
76+
return token == null ? default(T) : token.Value<T>();
77+
}
78+
}
79+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Collections.Specialized;
2+
3+
namespace Datadog.Trace.Configuration
4+
{
5+
/// <summary>
6+
/// Represents a configuration source that retrieves
7+
/// values from the provided <see cref="NameValueCollection"/>.
8+
/// </summary>
9+
public class NameValueConfigurationSource : StringConfigurationSource
10+
{
11+
private readonly NameValueCollection _nameValueCollection;
12+
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="NameValueConfigurationSource"/> class
15+
/// that wraps the specified <see cref="NameValueCollection"/>.
16+
/// </summary>
17+
/// <param name="nameValueCollection">The collection that will be wrapped by this configuration source.</param>
18+
public NameValueConfigurationSource(NameValueCollection nameValueCollection)
19+
{
20+
_nameValueCollection = nameValueCollection;
21+
}
22+
23+
/// <inheritdoc />
24+
public override string GetString(string key)
25+
{
26+
return _nameValueCollection[key];
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)