From cb03854ff51175bee2c7002741b8079fea7dd567 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Fri, 2 Jun 2023 14:57:19 -0700 Subject: [PATCH 1/5] Fix AOT warnings for RuntimeContext --- .../Context/RuntimeContext.cs | 57 +++++++++++++++++-- .../AotCompatibilityTests.cs | 2 +- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/OpenTelemetry.Api/Context/RuntimeContext.cs b/src/OpenTelemetry.Api/Context/RuntimeContext.cs index 6ff9699f9f6..4e539efa52a 100644 --- a/src/OpenTelemetry.Api/Context/RuntimeContext.cs +++ b/src/OpenTelemetry.Api/Context/RuntimeContext.cs @@ -27,10 +27,45 @@ public static class RuntimeContext { private static readonly ConcurrentDictionary Slots = new(); + private static Type contextSlotType = typeof(AsyncLocalRuntimeContextSlot<>); + /// /// Gets or sets the actual context carrier implementation. /// - public static Type ContextSlotType { get; set; } = typeof(AsyncLocalRuntimeContextSlot<>); + public static Type ContextSlotType + { + get => contextSlotType; + set + { + Guard.ThrowIfNull(value, nameof(value)); + + if (!value.IsGenericType || !value.IsGenericTypeDefinition || value.GetGenericArguments().Length != 1) + { + throw new NotSupportedException($"Type '{value}' must be generic with a single generic type argument"); + } + + 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."); + } + + contextSlotType = value; + } + } /// /// Register a named context slot. @@ -41,6 +76,7 @@ public static class RuntimeContext public static RuntimeContextSlot RegisterSlot(string slotName) { Guard.ThrowIfNullOrEmpty(slotName); + RuntimeContextSlot slot = null; lock (Slots) { @@ -49,9 +85,22 @@ public static RuntimeContextSlot RegisterSlot(string slotName) throw new InvalidOperationException($"Context slot already registered: '{slotName}'"); } - var type = ContextSlotType.MakeGenericType(typeof(T)); - var ctor = type.GetConstructor(new Type[] { typeof(string) }); - var slot = (RuntimeContextSlot)ctor.Invoke(new object[] { slotName }); + if (ContextSlotType == typeof(AsyncLocalRuntimeContextSlot<>)) + { + slot = new AsyncLocalRuntimeContextSlot(slotName); + } + else if (ContextSlotType == typeof(ThreadLocalRuntimeContextSlot<>)) + { + slot = new ThreadLocalRuntimeContextSlot(slotName); + } + +#if NETFRAMEWORK + else if (ContextSlotType == typeof(RemotingRuntimeContextSlot<>)) + { + slot = new RemotingRuntimeContextSlot(slotName); + } +#endif + Slots[slotName] = slot; return slot; } diff --git a/test/OpenTelemetry.AotCompatibility.Tests/AotCompatibilityTests.cs b/test/OpenTelemetry.AotCompatibility.Tests/AotCompatibilityTests.cs index 2b9cf77d9c3..4db5b903352 100644 --- a/test/OpenTelemetry.AotCompatibility.Tests/AotCompatibilityTests.cs +++ b/test/OpenTelemetry.AotCompatibility.Tests/AotCompatibilityTests.cs @@ -85,7 +85,7 @@ public void EnsureAotCompatibility() 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")); - Assert.Equal(43, warnings.Count()); + Assert.Equal(40, warnings.Count()); } } } From f5689c914ebf7f51b4559b87383c79c355ab007e Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:00:04 -0700 Subject: [PATCH 2/5] Code changes --- src/OpenTelemetry.Api/Context/RuntimeContext.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/OpenTelemetry.Api/Context/RuntimeContext.cs b/src/OpenTelemetry.Api/Context/RuntimeContext.cs index 4e539efa52a..5da621b2922 100644 --- a/src/OpenTelemetry.Api/Context/RuntimeContext.cs +++ b/src/OpenTelemetry.Api/Context/RuntimeContext.cs @@ -39,11 +39,6 @@ public static Type ContextSlotType { Guard.ThrowIfNull(value, nameof(value)); - if (!value.IsGenericType || !value.IsGenericTypeDefinition || value.GetGenericArguments().Length != 1) - { - throw new NotSupportedException($"Type '{value}' must be generic with a single generic type argument"); - } - if (value == typeof(AsyncLocalRuntimeContextSlot<>)) { contextSlotType = value; From 9d93a42f35a28279c76d6bf1681b8c38c2a66207 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:06:57 -0700 Subject: [PATCH 3/5] Update CHANGELOG --- src/OpenTelemetry.Api/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index bf1f3e6d3ef..d7cc1dae099 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -2,6 +2,13 @@ ## Unreleased +* **Breaking change** `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-rc.1 Released 2023-May-25 From c4c8e95602bb67dfa9bac37dd41aaa031aab9bf1 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:13:19 -0700 Subject: [PATCH 4/5] Update src/OpenTelemetry.Api/CHANGELOG.md Co-authored-by: Alan West <3676547+alanwest@users.noreply.github.com> --- src/OpenTelemetry.Api/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Api/CHANGELOG.md b/src/OpenTelemetry.Api/CHANGELOG.md index d7cc1dae099..5181c14deae 100644 --- a/src/OpenTelemetry.Api/CHANGELOG.md +++ b/src/OpenTelemetry.Api/CHANGELOG.md @@ -2,7 +2,9 @@ ## Unreleased -* **Breaking change** `RuntimeContext.ContextSlotType` can only be assigned one +* **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 From 5dea4c93d95bc9df7220840387e5cccc4d0553a3 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Tue, 6 Jun 2023 11:22:21 -0700 Subject: [PATCH 5/5] Remove unnecessary code --- src/OpenTelemetry.Api/Context/RuntimeContext.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/OpenTelemetry.Api/Context/RuntimeContext.cs b/src/OpenTelemetry.Api/Context/RuntimeContext.cs index 5da621b2922..a8f45c4052e 100644 --- a/src/OpenTelemetry.Api/Context/RuntimeContext.cs +++ b/src/OpenTelemetry.Api/Context/RuntimeContext.cs @@ -57,8 +57,6 @@ public static Type ContextSlotType { throw new NotSupportedException($"{value} is not a supported type."); } - - contextSlotType = value; } }