Skip to content

Commit

Permalink
Extensibility prototype (#129)
Browse files Browse the repository at this point in the history
* First prototype

* Use plugin manager to organize plugin loading. Add possibility to load multiple plugins.

* PR cleanup and fixes

* Fix plugin file name loading

* Fix vendoring sample references

* Fix comments

* refactor and add logging

* Fix plugin load logging

* Refactor plugins passing to tracer

* remove static property

* PR fixes and tests

* Refactor extendability points loading

* Refactor plugin with target framework loading

* Flatten propagators extension point

* Add logging for plugin config parsing error and fix comment

* Refactor composite propagator
  • Loading branch information
RassK authored May 6, 2021
1 parent e616d38 commit 47737ed
Show file tree
Hide file tree
Showing 51 changed files with 722 additions and 142 deletions.
21 changes: 17 additions & 4 deletions Datadog.Trace.sln
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitattributes = .gitattributes
.gitignore = .gitignore
Datadog.Trace.proj = Datadog.Trace.proj
OpenTelemetry.AutoInstrumentation.snk = OpenTelemetry.AutoInstrumentation.snk
Directory.Build.props = Directory.Build.props
docker-compose.yml = docker-compose.yml
GlobalSuppressions.cs = GlobalSuppressions.cs
integrations.json = integrations.json
LICENSE = LICENSE
LICENSE-3rdparty.csv = LICENSE-3rdparty.csv
OpenTelemetry.AutoInstrumentation.snk = OpenTelemetry.AutoInstrumentation.snk
docs\README.md = docs\README.md
stylecop.json = stylecop.json
EndProjectSection
Expand Down Expand Up @@ -428,7 +428,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "crank", "crank", "{E3FB283A
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DuplicateTypeProxy", "test\test-applications\regression\DuplicateTypeProxy\DuplicateTypeProxy.csproj", "{34B67004-7249-4EF1-8E12-6E6DA37EA6BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.AspNetCoreRazorPages", "test\test-applications\integrations\Samples.AspNetCoreRazorPages\Samples.AspNetCoreRazorPages.csproj", "{1B9E6BF4-9D48-4988-9945-248096119E46}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.AspNetCoreRazorPages", "test\test-applications\integrations\Samples.AspNetCoreRazorPages\Samples.AspNetCoreRazorPages.csproj", "{1B9E6BF4-9D48-4988-9945-248096119E46}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Vendoring", "test\test-applications\integrations\Samples.Vendoring\Samples.Vendoring.csproj", "{0D4ACA4A-44DC-4603-8992-926B5BED5D76}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Expand Down Expand Up @@ -1590,18 +1592,28 @@ Global
{34B67004-7249-4EF1-8E12-6E6DA37EA6BE}.Release|x64.Build.0 = Release|x64
{34B67004-7249-4EF1-8E12-6E6DA37EA6BE}.Release|x86.ActiveCfg = Release|x86
{34B67004-7249-4EF1-8E12-6E6DA37EA6BE}.Release|x86.Build.0 = Release|x86
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|Any CPU.Build.0 = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Debug|x64.ActiveCfg = Debug|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Debug|x64.Build.0 = Debug|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Debug|x86.ActiveCfg = Debug|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Debug|x86.Build.0 = Debug|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|Any CPU.Build.0 = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|x64.ActiveCfg = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|x64.Build.0 = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|x86.ActiveCfg = Release|Any CPU
{1B9E6BF4-9D48-4988-9945-248096119E46}.Release|x86.Build.0 = Release|Any CPU
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Debug|Any CPU.ActiveCfg = Debug|x86
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Debug|x64.ActiveCfg = Debug|x64
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Debug|x64.Build.0 = Debug|x64
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Debug|x86.ActiveCfg = Debug|x86
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Debug|x86.Build.0 = Debug|x86
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Release|Any CPU.ActiveCfg = Release|x86
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Release|x64.ActiveCfg = Release|x64
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Release|x64.Build.0 = Release|x64
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Release|x86.ActiveCfg = Release|x86
{0D4ACA4A-44DC-4603-8992-926B5BED5D76}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1727,6 +1739,7 @@ Global
{E3FB283A-B766-4887-95E1-329667671921} = {A0C5FBBB-CFB2-4FB9-B8F0-55676E9DCF06}
{34B67004-7249-4EF1-8E12-6E6DA37EA6BE} = {498A300E-D036-49B7-A43D-821D1CAF11A5}
{1B9E6BF4-9D48-4988-9945-248096119E46} = {BAF8F246-3645-42AD-B1D0-0F7EAFBAB34A}
{0D4ACA4A-44DC-4603-8992-926B5BED5D76} = {BAF8F246-3645-42AD-B1D0-0F7EAFBAB34A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
Expand Down
8 changes: 6 additions & 2 deletions src/Datadog.Trace.ClrProfiler.Managed/Instrumentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Datadog.Trace.Configuration;
using Datadog.Trace.DiagnosticListeners;
using Datadog.Trace.Logging;
using Datadog.Trace.Plugins;
using Datadog.Trace.ServiceFabric;

namespace Datadog.Trace.ClrProfiler
Expand Down Expand Up @@ -59,8 +60,11 @@ public static void Initialize()

try
{
// ensure global instance is created if it's not already
_ = Tracer.Instance;
// Creates GlobalSettings instance and loads plugins
var plugins = PluginManager.TryLoadPlugins(GlobalSettings.Source.PluginsConfiguration);

// First call to create Tracer instace
Tracer.Instance = new Tracer(plugins);
}
catch
{
Expand Down
5 changes: 5 additions & 0 deletions src/Datadog.Trace/Configuration/ConfigurationKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public static class ConfigurationKeys
/// </summary>
public const string ConfigurationFileName = "OTEL_TRACE_CONFIG_FILE";

/// <summary>
/// Configuration key for the path to the plugins configuration file.
/// </summary>
public const string PluginConfigurationFileName = "OTEL_DOTNET_TRACER_PLUGINS_FILE";

/// <summary>
/// Configuration key for the application's environment. Sets the "env" tag on every <see cref="Span"/>.
/// </summary>
Expand Down
35 changes: 29 additions & 6 deletions src/Datadog.Trace/Configuration/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ internal GlobalSettings(IConfigurationSource source)
DiagnosticSourceEnabled = source?.GetBool(ConfigurationKeys.DiagnosticSourceEnabled) ??
// default value
true;

if (TryLoadPluginJsonConfigurationFile(source, out JsonConfigurationSource jsonConfigurationSource))
{
PluginsConfiguration = jsonConfigurationSource;
}
}

/// <summary>
Expand All @@ -55,6 +60,11 @@ internal GlobalSettings(IConfigurationSource source)
/// </summary>
internal bool DiagnosticSourceEnabled { get; }

/// <summary>
/// Gets the plugins configuration.
/// </summary>
internal JsonConfigurationSource PluginsConfiguration { get; }

/// <summary>
/// Set whether debug mode is enabled.
/// Affects the level of logs written to file.
Expand Down Expand Up @@ -121,15 +131,28 @@ internal static CompositeConfigurationSource CreateDefaultConfigurationSource()
return configurationSource;
}

private static bool TryLoadJsonConfigurationFile(IConfigurationSource configurationSource, out IConfigurationSource jsonConfigurationSource)
private static bool TryLoadPluginJsonConfigurationFile(IConfigurationSource configurationSource, out JsonConfigurationSource jsonConfigurationSource)
{
var configurationFileName = configurationSource?.GetString(ConfigurationKeys.PluginConfigurationFileName) ??
Path.Combine(GetCurrentDirectory(), "plugins.json");

return TryLoadJsonConfigurationFile(configurationFileName, out jsonConfigurationSource);
}

private static bool TryLoadJsonConfigurationFile(IConfigurationSource configurationSource, out JsonConfigurationSource jsonConfigurationSource)
{
// if environment variable is not set, look for default file name in the current directory
var configurationFileName = configurationSource.GetString(ConfigurationKeys.ConfigurationFileName) ??
configurationSource.GetString("OTEL_DOTNET_TRACER_CONFIG_FILE") ??
Path.Combine(GetCurrentDirectory(), "datadog.json");

return TryLoadJsonConfigurationFile(configurationFileName, out jsonConfigurationSource);
}

private static bool TryLoadJsonConfigurationFile(string configurationFileName, out JsonConfigurationSource jsonConfigurationSource)
{
try
{
// if environment variable is not set, look for default file name in the current directory
var configurationFileName = configurationSource.GetString(ConfigurationKeys.ConfigurationFileName) ??
configurationSource.GetString("OTEL_DOTNET_TRACER_CONFIG_FILE") ??
Path.Combine(GetCurrentDirectory(), "datadog.json");

if (string.Equals(Path.GetExtension(configurationFileName), ".JSON", StringComparison.OrdinalIgnoreCase) &&
File.Exists(configurationFileName))
{
Expand Down
9 changes: 9 additions & 0 deletions src/Datadog.Trace/Configuration/JsonConfigurationSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ public IDictionary<string, string> GetDictionary(string key, bool allowOptionalM
return GetDictionaryInternal(key, allowOptionalMappings);
}

/// <summary>
/// Gets the string representation of json config.
/// </summary>
/// <returns>String format.</returns>
public override string ToString()
{
return _configuration.ToString();
}

private IDictionary<string, string> GetDictionaryInternal(string key, bool allowOptionalMappings)
{
var token = _configuration.SelectToken(key, errorWhenNoMatch: false);
Expand Down
29 changes: 0 additions & 29 deletions src/Datadog.Trace/Configuration/PropagatorType.cs

This file was deleted.

11 changes: 6 additions & 5 deletions src/Datadog.Trace/Configuration/TracerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Datadog.Trace.Configuration.Types;
using Datadog.Trace.ExtensionMethods;
using Datadog.Trace.PlatformHelpers;
using Datadog.Trace.Util;
Expand Down Expand Up @@ -369,7 +370,7 @@ public TracerSettings(IConfigurationSource source)
/// Default is <c>Datadog</c>
/// <seealso cref="ConfigurationKeys.Propagators"/>
/// </summary>
public HashSet<PropagatorType> Propagators { get; set; }
public HashSet<string> Propagators { get; set; }

/// <summary>
/// Gets or sets a value indicating whether runtime metrics
Expand Down Expand Up @@ -640,18 +641,18 @@ internal string GetServiceName(Tracer tracer, string serviceName)
return ServiceNameMappings.GetServiceName(tracer.DefaultServiceName, serviceName);
}

private static HashSet<PropagatorType> GetPropagators(IConfigurationSource source)
private static HashSet<string> GetPropagators(IConfigurationSource source)
{
var propagators = source.GetTypedValues<PropagatorType>(ConfigurationKeys.Propagators);
var propagators = source.GetStrings(ConfigurationKeys.Propagators);

if (!propagators.Any())
{
// TODO: Default to W3C (be aware of integration tests)
// see more: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#global-propagators
return new HashSet<PropagatorType>() { PropagatorType.Datadog };
return new HashSet<string>() { PropagatorTypes.Datadog };
}

return new HashSet<PropagatorType>(propagators);
return new HashSet<string>(propagators);
}
}
}
23 changes: 23 additions & 0 deletions src/Datadog.Trace/Configuration/Types/PropagatorTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Datadog.Trace.Configuration.Types
{
/// <summary>
/// Contains default available propagator types.
/// </summary>
public static class PropagatorTypes
{
/// <summary>
/// The Datadog propagator.
/// </summary>
public const string Datadog = "Datadog";

/// <summary>
/// The B3 propagator
/// </summary>
public const string B3 = "B3";

/// <summary>
/// The W3C propagator
/// </summary>
public const string W3C = "W3C";
}
}
11 changes: 10 additions & 1 deletion src/Datadog.Trace/Conventions/ITraceIdConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ namespace Datadog.Trace.Conventions
/// <summary>
/// Convention used when defining format of TraceId.
/// </summary>
internal interface ITraceIdConvention
public interface ITraceIdConvention
{
/// <summary>
/// Generates new unique trace id based on convention.
/// </summary>
/// <returns>Trace id.</returns>
TraceId GenerateNewTraceId();

/// <summary>
/// Creates new trace id based on given string.
/// </summary>
/// <param name="id">String of id.</param>
/// <returns>Trace id.</returns>
TraceId CreateFromString(string id);
}
}
32 changes: 28 additions & 4 deletions src/Datadog.Trace/FrameworkDescription.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Runtime.Versioning;
using Datadog.Trace.Logging;
using Microsoft.Win32;

namespace Datadog.Trace
{
Expand All @@ -29,6 +27,15 @@ internal partial class FrameworkDescription
Tuple.Create(378389, "4.5"),
};

private static readonly IReadOnlyDictionary<string, string> TargetFrameworkMapping = new Dictionary<string, string>()
{
{ ".NETFramework,Version=v4.5", "net45" },
{ ".NETFramework,Version=v4.6.1", "net461" },
{ ".NETStandard,Version=v2.0", "netstandard2.0" },
{ ".NETCoreApp,Version=v3.1", "netcoreapp3.1" },
{ ".NETCoreApp,Version=v5.0", "net50" }
};

private FrameworkDescription(
string name,
string productVersion,
Expand All @@ -41,6 +48,7 @@ private FrameworkDescription(
OSPlatform = osPlatform;
OSArchitecture = osArchitecture;
ProcessArchitecture = processArchitecture;
TargetFramework = GetTargetFramework();
}

public string Name { get; }
Expand All @@ -53,6 +61,8 @@ private FrameworkDescription(

public string ProcessArchitecture { get; }

public string TargetFramework { get; }

public override string ToString()
{
// examples:
Expand All @@ -61,6 +71,20 @@ public override string ToString()
return $"{Name} {ProductVersion} {ProcessArchitecture} on {OSPlatform} {OSArchitecture}";
}

private static string GetTargetFramework()
{
var framework = typeof(FrameworkDescription).Assembly
.GetCustomAttribute<TargetFrameworkAttribute>()?
.FrameworkName;

if (!TargetFrameworkMapping.TryGetValue(framework, out string targetFramework))
{
throw new InvalidOperationException($"Target framework mapping is not defined for '{framework}'");
}

return targetFramework;
}

private static string GetVersionFromAssemblyAttributes()
{
string productVersion = null;
Expand Down
9 changes: 9 additions & 0 deletions src/Datadog.Trace/Plugins/IOTelExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Datadog.Trace.Plugins
{
/// <summary>
/// Base marker interface for extendability points.
/// </summary>
public interface IOTelExtension
{
}
}
Loading

0 comments on commit 47737ed

Please sign in to comment.