Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WCF] Fix WCF instrumentation initialization #3650

Merged
merged 9 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h

### Fixed

- Initialize WCF instrumentation only when necessary ([#3650](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/pull/3650))

## [1.7.0](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/tag/v1.7.0)

- [Core components](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/VERSIONING.md#core-components):
Expand Down
21 changes: 20 additions & 1 deletion OpenTelemetry.AutoInstrumentation.sln
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.OracleMda.C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "getting-started-dotnet-monitor-logs", "next-gen\docs\getting-started-dotnet-monitor-logs\getting-started-dotnet-monitor-logs.csproj", "{959764E7-5A0C-4511-8004-48DE6B10F499}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.RabbitMq", "test\test-applications\integrations\TestApplication.RabbitMq\TestApplication.RabbitMq.csproj", "{91D883EC-069E-46BC-B6F7-67C94299851E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.RabbitMq", "test\test-applications\integrations\TestApplication.RabbitMq\TestApplication.RabbitMq.csproj", "{91D883EC-069E-46BC-B6F7-67C94299851E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.Owin.IIS.NetFramework", "test\test-applications\integrations\TestApplication.Owin.IIS.NetFramework\TestApplication.Owin.IIS.NetFramework.csproj", "{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -1477,6 +1479,22 @@ Global
{91D883EC-069E-46BC-B6F7-67C94299851E}.Release|x64.Build.0 = Release|x64
{91D883EC-069E-46BC-B6F7-67C94299851E}.Release|x86.ActiveCfg = Release|x86
{91D883EC-069E-46BC-B6F7-67C94299851E}.Release|x86.Build.0 = Release|x86
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|ARM64.Build.0 = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|x64.ActiveCfg = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|x64.Build.0 = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|x86.ActiveCfg = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Debug|x86.Build.0 = Debug|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|Any CPU.Build.0 = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|ARM64.ActiveCfg = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|ARM64.Build.0 = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|x64.ActiveCfg = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|x64.Build.0 = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|x86.ActiveCfg = Release|Any CPU
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1564,6 +1582,7 @@ Global
{21A915DF-8B9E-4CE8-84DA-1057CDCE117E} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
{959764E7-5A0C-4511-8004-48DE6B10F499} = {3F051815-8E0D-4356-BC36-55CA642DDF18}
{91D883EC-069E-46BC-B6F7-67C94299851E} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
{AA3E0C5C-A4E2-46AB-BD18-2D30D3ABF692} = {E409ADD3-9574-465C-AB09-4324D205CC7C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F}
Expand Down
3 changes: 3 additions & 0 deletions build/Build.Steps.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ partial class Build
var wcfProject = Solution.GetProjectByName(Projects.Tests.Applications.WcfIis);
BuildDockerImage(wcfProject);
var owinProject = Solution.GetProjectByName(Projects.Tests.Applications.OwinIis);
BuildDockerImage(owinProject);
});

void BuildDockerImage(Project project)
Expand Down
3 changes: 2 additions & 1 deletion build/Build.Steps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ DotNetRestoreSettings Restore(DotNetRestoreSettings s) =>
// Projects using `packages.config` can't be restored via "dotnet restore", use a NuGet Task to restore these projects.
var legacyRestoreProjects = Solution.GetNativeProjects()
.Concat(Solution.GetProjectByName(Projects.Tests.Applications.AspNet))
.Concat(Solution.GetProjectByName(Projects.Tests.Applications.WcfIis));
.Concat(Solution.GetProjectByName(Projects.Tests.Applications.WcfIis))
.Concat(Solution.GetProjectByName(Projects.Tests.Applications.OwinIis));
RestoreLegacyNuGetPackagesConfig(legacyRestoreProjects);
}
Expand Down
3 changes: 2 additions & 1 deletion build/Projects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ public static class Tests
public static class Applications
{
public const string AspNet = "TestApplication.AspNet.NetFramework";
public const string ContinuousProfilerNativeDep = "TestApplication.ContinuousProfiler.NativeDep";
public const string OwinIis = "TestApplication.Owin.IIS.NetFramework";
public const string WcfIis = "TestApplication.Wcf.Server.IIS.NetFramework";
public const string WcfServer = "TestApplication.Wcf.Server.NetFramework";
public const string ContinuousProfilerNativeDep = "TestApplication.ContinuousProfiler.NativeDep";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ public static void AddGraphQL(LazyInstrumentationLoader lazyInstrumentationLoade
}
#endif

[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddWcf(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
{
lazyInstrumentationLoader.Add(new WcfInitializer(pluginManager));
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddQuartz(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@ public static TracerProviderBuilder UseEnvironmentVariables(
TracerSettings settings,
PluginManager pluginManager)
{
// ensure WcfInitializer is added only once,
// ensure WCF instrumentation activity source is added only once,
// it is needed when either WcfClient or WcfService instrumentations are enabled
// to initialize WcfInstrumentationOptions
var wcfInstrumentationAdded = false;
foreach (var enabledInstrumentation in settings.EnabledInstrumentations)
{
_ = enabledInstrumentation switch
{
#if NETFRAMEWORK
TracerInstrumentation.AspNet => Wrappers.AddAspNetInstrumentation(builder, pluginManager, lazyInstrumentationLoader, settings),
TracerInstrumentation.WcfService => AddWcfIfNeeded(builder, pluginManager, lazyInstrumentationLoader, ref wcfInstrumentationAdded),
TracerInstrumentation.WcfService => AddWcfIfNeeded(builder, ref wcfInstrumentationAdded),
#endif
TracerInstrumentation.GrpcNetClient => Wrappers.AddGrpcClientInstrumentation(builder, pluginManager, lazyInstrumentationLoader, settings),
TracerInstrumentation.HttpClient => Wrappers.AddHttpClientInstrumentation(builder, pluginManager, lazyInstrumentationLoader, settings),
Expand All @@ -39,7 +38,7 @@ public static TracerProviderBuilder UseEnvironmentVariables(
TracerInstrumentation.MongoDB => builder.AddSource("MongoDB.Driver.Core.Extensions.DiagnosticSources"),
TracerInstrumentation.MySqlConnector => builder.AddSource("MySqlConnector"),
TracerInstrumentation.Azure => Wrappers.AddAzureInstrumentation(builder),
TracerInstrumentation.WcfClient => AddWcfIfNeeded(builder, pluginManager, lazyInstrumentationLoader, ref wcfInstrumentationAdded),
TracerInstrumentation.WcfClient => AddWcfIfNeeded(builder, ref wcfInstrumentationAdded),
TracerInstrumentation.OracleMda => Wrappers.AddOracleMdaInstrumentation(builder, lazyInstrumentationLoader, settings),
#if NET6_0_OR_GREATER
TracerInstrumentation.AspNetCore => Wrappers.AddAspNetCoreInstrumentation(builder, pluginManager, lazyInstrumentationLoader, settings),
Expand Down Expand Up @@ -74,16 +73,14 @@ public static TracerProviderBuilder UseEnvironmentVariables(

private static TracerProviderBuilder AddWcfIfNeeded(
TracerProviderBuilder tracerProviderBuilder,
PluginManager pluginManager,
LazyInstrumentationLoader lazyInstrumentationLoader,
ref bool wcfInstrumentationAdded)
{
if (wcfInstrumentationAdded)
{
return tracerProviderBuilder;
}

Wrappers.AddWcfInstrumentation(tracerProviderBuilder, pluginManager, lazyInstrumentationLoader);
tracerProviderBuilder.AddSource("OpenTelemetry.Instrumentation.Wcf");
wcfInstrumentationAdded = true;

return tracerProviderBuilder;
Expand Down Expand Up @@ -113,14 +110,6 @@ private static class Wrappers
{
// Instrumentations

[MethodImpl(MethodImplOptions.NoInlining)]
public static TracerProviderBuilder AddWcfInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager, LazyInstrumentationLoader lazyInstrumentationLoader)
{
DelayedInitialization.Traces.AddWcf(lazyInstrumentationLoader, pluginManager);

return builder.AddSource("OpenTelemetry.Instrumentation.Wcf");
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static TracerProviderBuilder AddHttpClientInstrumentation(TracerProviderBuilder builder, PluginManager pluginManager, LazyInstrumentationLoader lazyInstrumentationLoader, TracerSettings tracerSettings)
{
Expand Down
20 changes: 0 additions & 20 deletions src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,6 @@ private static void AddLazilyLoadedMetricInstrumentations(LazyInstrumentationLoa

private static void AddLazilyLoadedTraceInstrumentations(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
{
// ensure WcfInitializer is added only once,
// it is needed when either WcfClient or WcfService instrumentations are enabled
// to initialize WcfInstrumentationOptions
var wcfInstrumentationAdded = false;
foreach (var instrumentation in tracerSettings.EnabledInstrumentations)
{
switch (instrumentation)
Expand All @@ -324,7 +320,6 @@ private static void AddLazilyLoadedTraceInstrumentations(LazyInstrumentationLoad
DelayedInitialization.Traces.AddAspNet(lazyInstrumentationLoader, pluginManager, tracerSettings);
break;
case TracerInstrumentation.WcfService:
AddWcfIfNeeded(lazyInstrumentationLoader, pluginManager, ref wcfInstrumentationAdded);
break;
#endif
case TracerInstrumentation.HttpClient:
Expand All @@ -340,7 +335,6 @@ private static void AddLazilyLoadedTraceInstrumentations(LazyInstrumentationLoad
DelayedInitialization.Traces.AddQuartz(lazyInstrumentationLoader, pluginManager);
break;
case TracerInstrumentation.WcfClient:
AddWcfIfNeeded(lazyInstrumentationLoader, pluginManager, ref wcfInstrumentationAdded);
break;
#if NET6_0_OR_GREATER
case TracerInstrumentation.AspNetCore:
Expand Down Expand Up @@ -391,20 +385,6 @@ private static void AddLazilyLoadedTraceInstrumentations(LazyInstrumentationLoad
}
}

private static void AddWcfIfNeeded(
LazyInstrumentationLoader lazyInstrumentationLoader,
PluginManager pluginManager,
ref bool wcfInstrumentationAdded)
{
if (wcfInstrumentationAdded)
{
return;
}

DelayedInitialization.Traces.AddWcf(lazyInstrumentationLoader, pluginManager);
wcfInstrumentationAdded = true;
}

private static void OnExit(object? sender, EventArgs e)
{
if (Interlocked.Exchange(ref _isExiting, value: 1) != 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public static class HttpModuleIntegration
{
private static int _initialized;

internal static bool IsInitialized => Interlocked.CompareExchange(ref _initialized, 0, 0) != default;

/// <summary>
/// OnMethodBegin callback
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ internal interface IEndpoint

public static void Initialize(IChannelFactory channelFactory)
{
WcfInstrumentationInitializer.TryInitializeOptions();

var behaviors = channelFactory.Endpoint.Behaviors;
if (!behaviors.Contains(typeof(TelemetryEndpointBehavior)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ internal interface IDescription

public static void Initialize(IServiceHostBase serviceHost)
{
WcfInstrumentationInitializer.TryInitializeOptions();
WcfInstrumentationInitializer.TryInitializeParentSpanCorrector();

var behaviors = serviceHost.Description.Behaviors;
if (!behaviors.Contains(typeof(TelemetryServiceBehavior)))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#if NETFRAMEWORK
using System.Reflection;
using OpenTelemetry.AutoInstrumentation.Instrumentations.AspNet;
#endif
using OpenTelemetry.Instrumentation.Wcf;

namespace OpenTelemetry.AutoInstrumentation.Instrumentations.Wcf;

internal static class WcfInstrumentationInitializer
{
private static int _instrumentationOptionsInitialized;
#if NETFRAMEWORK
private static int _aspNetParentSpanCorrectorInitialized;
#endif

public static void TryInitializeOptions()
{
if (Interlocked.Exchange(ref _instrumentationOptionsInitialized, value: 1) != default)
{
return;
}

var options = new WcfInstrumentationOptions();

Instrumentation.PluginManager?.ConfigureTracesOptions(options);

var instrumentationType =
Type.GetType(
"OpenTelemetry.Instrumentation.Wcf.WcfInstrumentationActivitySource, OpenTelemetry.Instrumentation.Wcf");

instrumentationType?.GetProperty("Options")?.SetValue(null, options);
}

#if NETFRAMEWORK
public static void TryInitializeParentSpanCorrector()
{
if (Interlocked.Exchange(ref _aspNetParentSpanCorrectorInitialized, value: 1) != default)
{
return;
}

if (HttpModuleIntegration.IsInitialized)
{
var aspNetParentSpanCorrectorType = Type.GetType("OpenTelemetry.Instrumentation.Wcf.Implementation.AspNetParentSpanCorrector, OpenTelemetry.Instrumentation.Wcf");
var methodInfo = aspNetParentSpanCorrectorType?.GetMethod("Register", BindingFlags.Static | BindingFlags.Public);
methodInfo?.Invoke(null, null);
}
}
#endif
}

This file was deleted.

Loading
Loading