Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Adjust WCF instrumentation to ASP.NET changes
  • Loading branch information
Kielek committed Sep 29, 2025
commit 50a5dd8faa28731f85ede76ad9115e21efcb29a7
5 changes: 5 additions & 0 deletions src/OpenTelemetry.Instrumentation.Wcf/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
* Added server instrumentation support for `RecordException` option.
([#2880](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2880))

* **Breaking changes** Adjust to breaking changes from
`OpenTelemetry.Instrumentation.AspNet` version `1.12.0-beta.3`.
Fixing span hierarchy when hosted in ASP.NET.
([#3151](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3151))

## 1.12.0-beta.1

Released 2025-May-06
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,75 @@
private static Func<object> GenerateSubscribeLambda()
{
// this method effectively generates this lambda:
// () => TelemetryHttpModule.Options.OnRequestStartedCallback += OnRequestStarted
// technically it generates this:
// () => TelemetryHttpModule.Options.OnRequestStartedCallback =
// (Action<Activity, HttpContext>)addOurCallbackToDelegate(TelemetryHttpModule.Options.OnRequestStartedCallback);
// () => TelemetryHttpModule.Options.OnRequestStartedCallback = CreateCombinedCallback(TelemetryHttpModule.Options.OnRequestStartedCallback)
// The callback signature is Func<HttpContextBase, ActivityContext, Activity?>

var telemetryHttpModuleType = Type.GetType(TelemetryHttpModuleTypeName, true);
var telemetryHttpModuleOptionsType = Type.GetType(TelemetryHttpModuleOptionsTypeName, true);
var onRequestStartedProp = telemetryHttpModuleOptionsType.GetProperty("OnRequestStartedCallback") ?? throw new NotSupportedException("TelemetryHttpModuleOptions.OnRequestStartedCallback property not found");
Func<Delegate, Delegate> addOurCallbackToDelegate = (existingCallback) =>
{
var myCallback = OnRequestStarted;
var myCallbackProperlyTyped = Delegate.CreateDelegate(onRequestStartedProp.PropertyType, myCallback.Target, myCallback.Method);
return Delegate.Combine(existingCallback, myCallbackProperlyTyped);
};
var onRequestStartedProp = telemetryHttpModuleOptionsType?.GetProperty("OnRequestStartedCallback") ?? throw new NotSupportedException("TelemetryHttpModuleOptions.OnRequestStartedCallback property not found");

// Get the parameter types from the callback property type itself to avoid hardcoded type loading
var callbackType = onRequestStartedProp.PropertyType;
var invokeMethod = callbackType.GetMethod("Invoke");
var parameterTypes = invokeMethod!.GetParameters().Select(p => p.ParameterType).ToArray();
var returnType = invokeMethod.ReturnType;

// Parameters for the new combined callback (use actual parameter types from the callback)
var httpContextParam = Expression.Parameter(parameterTypes[0], "httpContext");
var activityContextParam = Expression.Parameter(parameterTypes[1], "activityContext");

// Get the existing callback value
var options = Expression.Property(null, telemetryHttpModuleType, "Options");
var existingCallback = Expression.Property(options, onRequestStartedProp);

// Create conditional logic: if existingCallback != null, call it, otherwise return null
var nullCheck = Expression.NotEqual(existingCallback, Expression.Constant(null, existingCallback.Type));

// Call existing callback if it exists
var callExistingCallback = Expression.Call(
existingCallback,
invokeMethod,
httpContextParam,
activityContextParam);

// If no existing callback, return null
var nullActivity = Expression.Constant(null, returnType);

// Choose between calling existing callback or returning null
var activityResult = Expression.Condition(nullCheck, callExistingCallback, nullActivity);

// Store the activity result in a variable
var activityVariable = Expression.Variable(returnType, "activity");
var assignActivity = Expression.Assign(activityVariable, activityResult);

// Check if activity is not null before calling OnRequestStarted
var activityNotNull = Expression.NotEqual(activityVariable, Expression.Constant(null, returnType));

// Call OnRequestStarted method - convert HttpContextBase to object for compatibility
var onRequestStartedMethod = typeof(AspNetParentSpanCorrector).GetMethod(nameof(OnRequestStarted), BindingFlags.Static | BindingFlags.NonPublic)!;
var callOnRequestStarted = Expression.Call(onRequestStartedMethod, activityVariable, Expression.Convert(httpContextParam, typeof(object)));

// Conditional call to OnRequestStarted
var conditionalCall = Expression.IfThen(activityNotNull, callOnRequestStarted);

// Return the activity
var returnActivity = activityVariable;

// Create the method body
var methodBody = Expression.Block(
[activityVariable],
assignActivity,
conditionalCall,
returnActivity
);

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (ubuntu-22.04, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net8.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net9.0)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net462)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net462)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net462)

Check failure on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / build-test-instrumentation-wcf / build-test (windows-latest, net462)

Check warning on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / lint-dotnet-format / run-dotnet-format

Closing parenthesis should be on line of last parameter

Check warning on line 164 in src/OpenTelemetry.Instrumentation.Wcf/Implementation/AspNetParentSpanCorrector.cs

View workflow job for this annotation

GitHub Actions / lint-dotnet-format / run-dotnet-format

Closing parenthesis should not be preceded by a space

// Create the combined callback lambda
var combinedCallbackLambda = Expression.Lambda(callbackType, methodBody, httpContextParam, activityContextParam);

// Create assignment: Options.OnRequestStartedCallback = combinedCallback
var callbackProperty = Expression.Property(options, onRequestStartedProp);
var combinedDelegate = Expression.Call(Expression.Constant(addOurCallbackToDelegate.Target), addOurCallbackToDelegate.Method, callbackProperty);
var subscribeExpression = Expression.Assign(callbackProperty, Expression.Convert(combinedDelegate, onRequestStartedProp.PropertyType));
var subscribeExpression = Expression.Assign(callbackProperty, combinedCallbackLambda);

return (Func<object>)Expression.Lambda(subscribeExpression).Compile();
}

Expand Down
Loading