Fix AOT warnings for RuntimeContext (#4542)

This commit is contained in:
Utkarsh Umesan Pillai 2023-06-06 13:04:33 -07:00 committed by GitHub
parent 839de1ae19
commit a4575581f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 5 deletions

View File

@ -2,6 +2,15 @@
## Unreleased ## Unreleased
* **Breaking change** In order to make `RuntimeContext` compatible with
ahead-of-time compilation (AOT),
`RuntimeContext.ContextSlotType` can only be assigned one
of the following types: `AsyncLocalRuntimeContextSlot<>`,
`ThreadLocalRuntimeContextSlot<>`, and `RemotingRuntimeContextSlot<>`. A
`System.NotSupportedException` will be thrown if you try to assign any type
other than the three types mentioned.
([#4542](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4542))
## 1.5.0 ## 1.5.0
Released 2023-Jun-05 Released 2023-Jun-05

View File

@ -27,10 +27,38 @@ namespace OpenTelemetry.Context
{ {
private static readonly ConcurrentDictionary<string, object> Slots = new(); private static readonly ConcurrentDictionary<string, object> Slots = new();
private static Type contextSlotType = typeof(AsyncLocalRuntimeContextSlot<>);
/// <summary> /// <summary>
/// Gets or sets the actual context carrier implementation. /// Gets or sets the actual context carrier implementation.
/// </summary> /// </summary>
public static Type ContextSlotType { get; set; } = typeof(AsyncLocalRuntimeContextSlot<>); public static Type ContextSlotType
{
get => contextSlotType;
set
{
Guard.ThrowIfNull(value, nameof(value));
if (value == typeof(AsyncLocalRuntimeContextSlot<>))
{
contextSlotType = value;
}
else if (value == typeof(ThreadLocalRuntimeContextSlot<>))
{
contextSlotType = value;
}
#if NETFRAMEWORK
else if (value == typeof(RemotingRuntimeContextSlot<>))
{
contextSlotType = value;
}
#endif
else
{
throw new NotSupportedException($"{value} is not a supported type.");
}
}
}
/// <summary> /// <summary>
/// Register a named context slot. /// Register a named context slot.
@ -41,6 +69,7 @@ namespace OpenTelemetry.Context
public static RuntimeContextSlot<T> RegisterSlot<T>(string slotName) public static RuntimeContextSlot<T> RegisterSlot<T>(string slotName)
{ {
Guard.ThrowIfNullOrEmpty(slotName); Guard.ThrowIfNullOrEmpty(slotName);
RuntimeContextSlot<T> slot = null;
lock (Slots) lock (Slots)
{ {
@ -49,9 +78,22 @@ namespace OpenTelemetry.Context
throw new InvalidOperationException($"Context slot already registered: '{slotName}'"); throw new InvalidOperationException($"Context slot already registered: '{slotName}'");
} }
var type = ContextSlotType.MakeGenericType(typeof(T)); if (ContextSlotType == typeof(AsyncLocalRuntimeContextSlot<>))
var ctor = type.GetConstructor(new Type[] { typeof(string) }); {
var slot = (RuntimeContextSlot<T>)ctor.Invoke(new object[] { slotName }); slot = new AsyncLocalRuntimeContextSlot<T>(slotName);
}
else if (ContextSlotType == typeof(ThreadLocalRuntimeContextSlot<>))
{
slot = new ThreadLocalRuntimeContextSlot<T>(slotName);
}
#if NETFRAMEWORK
else if (ContextSlotType == typeof(RemotingRuntimeContextSlot<>))
{
slot = new RemotingRuntimeContextSlot<T>(slotName);
}
#endif
Slots[slotName] = slot; Slots[slotName] = slot;
return slot; return slot;
} }

View File

@ -85,7 +85,7 @@ namespace OpenTelemetry.AotCompatibility.Tests
Assert.True(process.ExitCode == 0, "Publishing the AotCompatibility app failed. See test output for more details."); Assert.True(process.ExitCode == 0, "Publishing the AotCompatibility app failed. See test output for more details.");
var warnings = expectedOutput.ToString().Split('\n', '\r').Where(line => line.Contains("warning IL")); var warnings = expectedOutput.ToString().Split('\n', '\r').Where(line => line.Contains("warning IL"));
Assert.Equal(43, warnings.Count()); Assert.Equal(40, warnings.Count());
} }
} }
} }