Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public TraceContextEnrichedActorRemotingProviderAttribute()
/// </summary>
public int RemotingExceptionDepth { get; set; }

internal static Func<FabricTransportRemotingSettings?> RemotingSettingsLoader { get; set; } = LoadRemotingSettings;

internal static Func<string, FabricTransportRemotingListenerSettings?> ListenerSettingsLoader { get; set; } = LoadListenerSettings;

/// <summary>
/// Creates a service remoting listener for remoting the actor interfaces.
/// </summary>.
Expand All @@ -59,7 +63,7 @@ public override Dictionary<string, Func<ActorService, IServiceRemotingListener>>
{
var actorServiceRemotingDispatcher = new ActorServiceRemotingDispatcher(actorService, serviceRemotingRequestMessageBodyFactory: null);
var dispatcherAdapter = new ServiceRemotingMessageDispatcherAdapter(actorServiceRemotingDispatcher);
var listenerSettings = this.InitializeListenerSettings(actorService);
var listenerSettings = this.GetListenerSettings(actorService.ActorTypeInformation.ImplementationType);

return new FabricTransportActorServiceRemotingListener(
actorService,
Expand All @@ -81,11 +85,7 @@ public override Dictionary<string, Func<ActorService, IServiceRemotingListener>>
/// <returns> An <see cref="IServiceRemotingClientFactory"/>.</returns>
public override IServiceRemotingClientFactory CreateServiceRemotingClientFactory(IServiceRemotingCallbackMessageHandler? callbackMessageHandler)
{
var settings = new FabricTransportRemotingSettings();
settings.MaxMessageSize = this.GetAndValidateMaxMessageSize(settings.MaxMessageSize);
settings.OperationTimeout = this.GetAndValidateOperationTimeout(settings.OperationTimeout);
settings.KeepAliveTimeout = this.GetAndValidateKeepAliveTimeout(settings.KeepAliveTimeout);
settings.ConnectTimeout = this.GetConnectTimeout(settings.ConnectTimeout);
var settings = this.GetRemotingSettings();

var fabricTransportActorRemotingClientFactory = new FabricTransportActorRemotingClientFactory(
settings,
Expand All @@ -99,6 +99,39 @@ public override IServiceRemotingClientFactory CreateServiceRemotingClientFactory
return new TraceContextEnrichedServiceRemotingClientFactoryAdapter(fabricTransportActorRemotingClientFactory);
}

internal FabricTransportRemotingListenerSettings GetListenerSettings(Type actorImplementationType)
{
// Mirror Service Fabric's own FabricTransportActorRemotingProviderAttribute: use the actor-specific section if it
// exists, then the shared TransportSettings section, and only then the defaults, so that the transport security
// credentials configured for the application are never silently dropped.
var sectionName = ActorNameFormat.GetFabricServiceTransportSettingsSectionName(actorImplementationType);

var settings =
ListenerSettingsLoader(sectionName) ??
ListenerSettingsLoader(ServiceFabricRemotingUtils.DefaultTransportSettingsSectionName) ??
new FabricTransportRemotingListenerSettings();

settings.MaxMessageSize = this.GetAndValidateMaxMessageSize(settings.MaxMessageSize);
settings.OperationTimeout = this.GetAndValidateOperationTimeout(settings.OperationTimeout);
settings.KeepAliveTimeout = this.GetAndValidateKeepAliveTimeout(settings.KeepAliveTimeout);
settings.RemotingExceptionDepth = this.GetRemotingExceptionDepth(settings.RemotingExceptionDepth);

return settings;
}

internal FabricTransportRemotingSettings GetRemotingSettings()
{
// Like Service Fabric's own provider, the client uses the shared TransportSettings section when it exists.
var settings = RemotingSettingsLoader() ?? new FabricTransportRemotingSettings();

settings.MaxMessageSize = this.GetAndValidateMaxMessageSize(settings.MaxMessageSize);
settings.OperationTimeout = this.GetAndValidateOperationTimeout(settings.OperationTimeout);
settings.KeepAliveTimeout = this.GetAndValidateKeepAliveTimeout(settings.KeepAliveTimeout);
settings.ConnectTimeout = this.GetConnectTimeout(settings.ConnectTimeout);

return settings;
}

/// <summary>
/// Gets the exception convertors that the remoting listener uses to convert the exceptions thrown by the actor
/// implementation into a serializable form. Override this method to support custom exception types.
Expand All @@ -119,30 +152,17 @@ public override IServiceRemotingClientFactory CreateServiceRemotingClientFactory
/// <returns>The exception convertors to register with the client factory, or <see langword="null"/> to register none.</returns>
protected virtual IEnumerable<ClientExceptionConvertor>? GetClientExceptionConvertors() => null;

private static FabricTransportRemotingListenerSettings GetActorListenerSettings(ActorService actorService)
{
var sectionName = ActorNameFormat.GetFabricServiceTransportSettingsSectionName(actorService.ActorTypeInformation.ImplementationType);

var succeeded = FabricTransportRemotingListenerSettings.TryLoadFrom(sectionName, out var listenerSettings);
if (!succeeded)
{
listenerSettings = new FabricTransportRemotingListenerSettings();
}

return listenerSettings;
}

private FabricTransportRemotingListenerSettings InitializeListenerSettings(ActorService actorService)
{
var listenerSettings = GetActorListenerSettings(actorService);

listenerSettings.MaxMessageSize = this.GetAndValidateMaxMessageSize(listenerSettings.MaxMessageSize);
listenerSettings.OperationTimeout = this.GetAndValidateOperationTimeout(listenerSettings.OperationTimeout);
listenerSettings.KeepAliveTimeout = this.GetAndValidateKeepAliveTimeout(listenerSettings.KeepAliveTimeout);
listenerSettings.RemotingExceptionDepth = this.GetRemotingExceptionDepth(listenerSettings.RemotingExceptionDepth);

return listenerSettings;
}
private static FabricTransportRemotingSettings? LoadRemotingSettings() =>
ServiceFabricRemotingUtils.TryLoadTransportSettings(() =>
FabricTransportRemotingSettings.TryLoadFrom(ServiceFabricRemotingUtils.DefaultTransportSettingsSectionName, out var settings, filepath: null, configPackageName: null)
? settings
: null);

private static FabricTransportRemotingListenerSettings? LoadListenerSettings(string sectionName) =>
ServiceFabricRemotingUtils.TryLoadTransportSettings(() =>
FabricTransportRemotingListenerSettings.TryLoadFrom(sectionName, out var settings, configPackageName: null)
? settings
: null);

private long GetAndValidateMaxMessageSize(long maxMessageSizeDefault)
=> (this.MaxMessageSize > 0) ? this.MaxMessageSize : maxMessageSizeDefault;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
* Updated OpenTelemetry core component version(s) to `1.19.1`.
([#5329](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/5329))

* Fixed `TraceContextEnrichedActorRemotingProviderAttribute` ignoring the
`TransportSettings` configuration section. Actor remoting clients now load their
settings from `TransportSettings`, and actor remoting listeners fall back to
`TransportSettings` when no actor-specific section is configured, matching the
behaviour of Service Fabric's `FabricTransportActorRemotingProviderAttribute`.
([#5450](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/5450))

## 1.19.0-beta.1

Released 2026-Sep-18
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,36 @@ namespace OpenTelemetry.Instrumentation.ServiceFabricRemoting;

internal static class ServiceFabricRemotingUtils
{
/// <summary>
/// The name of the configuration section that Service Fabric reads the default transport settings,
/// including the transport security credentials, from.
/// </summary>
internal const string DefaultTransportSettingsSectionName = "TransportSettings";

/// <summary>
/// Invokes a loader for Service Fabric transport settings, returning <see langword="null"/>
/// if the native Service Fabric runtime that loading settings from configuration requires is not available.
/// </summary>
/// <typeparam name="T">The type of the settings.</typeparam>
/// <param name="loader">The delegate that loads the settings.</param>
/// <returns>The loaded settings, or <see langword="null"/> if no settings could be loaded.</returns>
internal static T? TryLoadTransportSettings<T>(Func<T?> loader)
where T : class
{
try
{
return loader();
}
catch (DllNotFoundException)
{
return null;
}
catch (TypeInitializationException ex) when (IsServiceFabricRuntimeUnavailable(ex))
{
return null;
}
}

internal static void InjectTraceContextIntoServiceRemotingRequestMessageHeader(IServiceRemotingRequestMessageHeader requestMessageHeader, string key, string value)
{
if (!requestMessageHeader.TryGetHeaderValue(key, out var _))
Expand All @@ -29,4 +59,20 @@ internal static IEnumerable<string> ExtractTraceContextFromRequestMessageHeader(

return [];
}

private static bool IsServiceFabricRuntimeUnavailable(TypeInitializationException exception)
{
// How a missing runtime surfaces depends on the platform: on Windows the native library is not
// found, but on Linux the interop module's type initializer fails to load a type it depends on,
// and either may be wrapped in several type initialization exceptions.
for (var inner = exception.InnerException; inner != null; inner = inner.InnerException)
{
if (inner is DllNotFoundException or TypeLoadException)
{
return true;
}
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ namespace OpenTelemetry.Instrumentation.ServiceFabricRemoting;
public class TraceContextEnrichedServiceRemotingProviderAttribute : FabricTransportServiceRemotingProviderAttribute
{
private const string DefaultV2listenerName = "V2Listener";
private const string DefaultTransportSettingsSectionName = "TransportSettings";

/// <summary>
/// Initializes a new instance of the <see cref="TraceContextEnrichedServiceRemotingProviderAttribute"/> class.
Expand Down Expand Up @@ -149,34 +148,17 @@ internal FabricTransportRemotingSettings GetRemotingSettings()
protected virtual IEnumerable<ClientExceptionConvertor>? GetClientExceptionConvertors() => null;

private static FabricTransportRemotingSettings? LoadRemotingSettings() =>
TryLoadSettings(() =>
FabricTransportRemotingSettings.TryLoadFrom(DefaultTransportSettingsSectionName, out var settings, filepath: null, configPackageName: null)
ServiceFabricRemotingUtils.TryLoadTransportSettings(() =>
FabricTransportRemotingSettings.TryLoadFrom(ServiceFabricRemotingUtils.DefaultTransportSettingsSectionName, out var settings, filepath: null, configPackageName: null)
? settings
: null);

private static FabricTransportRemotingListenerSettings? LoadListenerSettings() =>
TryLoadSettings(() =>
FabricTransportRemotingListenerSettings.TryLoadFrom(DefaultTransportSettingsSectionName, out var settings, configPackageName: null)
ServiceFabricRemotingUtils.TryLoadTransportSettings(() =>
FabricTransportRemotingListenerSettings.TryLoadFrom(ServiceFabricRemotingUtils.DefaultTransportSettingsSectionName, out var settings, configPackageName: null)
? settings
: null);

private static T? TryLoadSettings<T>(Func<T?> loader)
where T : class
{
try
{
return loader();
}
catch (DllNotFoundException)
{
return null;
}
catch (TypeInitializationException ex) when (ex.InnerException is DllNotFoundException)
{
return null;
}
}

private long GetAndValidateMaxMessageSize(long maxMessageSizeDefault)
=> (this.MaxMessageSize > 0) ? this.MaxMessageSize : maxMessageSizeDefault;

Expand Down
Loading
Loading