Skip to content

Conversation

@martincostello
Copy link
Member

Changes

Possible approach to allow Grafana.OpenTelemetry.Base to work in a native AoT application.

Extends #356. Not yet validated the trimmer retains all the appropriate functionality.

Relates to #97.

Merge requirement checklist

  • Unit tests added/updated
  • CHANGELOG.md updated
  • Changes in public API reviewed (if applicable)

- Mark Grafana.OpenTelemetry.Base as explicitly not AoT compatible due to extensive use of reflection.
- Add AoT attribute to `ReflectionHelper` to move warnings to the callers of `CallStaticMethod()`.
- Mark Grafana.OpenTelemetry as AoT compatible.

Relates to #97.
Enable the use of collection expressions.
Mark various internal classes as `sealed`.
Use some modern C# features.
Attempt to enable native AoT compatibility by using `[DynamicDependency]` to have the trimmer retain the static methods that are called.

Not yet tested in an actual native AoT application.
Copilot AI review requested due to automatic review settings November 24, 2025 12:09
Copilot finished reviewing on behalf of martincostello November 24, 2025 12:13
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables native Ahead-of-Time (AoT) compilation compatibility for the Grafana.OpenTelemetry.Base and Grafana.OpenTelemetry packages targeting .NET 8.0 and above. The changes add necessary AoT metadata attributes while modernizing the codebase to use C# collection expression syntax.

Key changes:

  • Adds IsAotCompatible property to project files for .NET 8.0+ targets
  • Introduces DynamicDependency and UnconditionalSuppressMessage attributes to preserve reflection-accessed members during trimming
  • Modernizes array initialization syntax using collection expressions throughout the codebase

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Directory.Build.props Sets LangVersion to latest enabling modern C# features including collection expressions
src/Grafana.OpenTelemetry.Base/Grafana.OpenTelemetry.Base.csproj Adds IsAotCompatible property for net8.0+ targets
src/Grafana.OpenTelemetry/Grafana.OpenTelemetry.csproj Adds IsAotCompatible property for net8.0+ targets
src/Grafana.OpenTelemetry.Base/TrimWarnings.cs New helper class centralizing trim warning constants for consistent AoT attribute usage
src/Grafana.OpenTelemetry.Base/ReflectionHelper.cs Adds RequiresUnreferencedCode attribute and modernizes to collection expression syntax
src/Grafana.OpenTelemetry.Base/ResourceDetectors/*.cs Adds sealed keyword and DynamicDependency attributes to detector initializers; converts to collection expressions
src/Grafana.OpenTelemetry.Base/Instrumentations/*.cs Adds sealed keyword and DynamicDependency attributes to instrumentation initializers; converts to collection expressions
src/Grafana.OpenTelemetry.Base/GrafanaOpenTelemetryResourceDetector.cs Adds sealed keyword and modernizes to collection expression syntax
src/Grafana.OpenTelemetry.Base/GrafanaOpenTelemetrySettings.cs Converts array initialization to collection expression syntax
src/Grafana.OpenTelemetry.Base/ExporterSettings/GrafanaCloudConfigurationHelper.cs Adds sealed keyword to class
tests/Grafana.OpenTelemetry.Tests/ReflectionHelperTest.cs Updates test arrays to use collection expression syntax

Fix copy-paste fail.
@martincostello
Copy link
Member Author

Doing some hacking around with the example app locally, this doesn't work.

I removed MVC and EFCore from the sample app and then set PublishAot=true. Running dotnet publish then outputs the following errors of interest:

    ILC : error IL2035: Grafana.OpenTelemetry.MySqlDataInitializer.InitializeTracing(TracerProviderBuilder): Unresolved assembly 'MySQL.Data.OpenTelemetry' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.MySqlDataInitializer.InitializeTracing(TracerProviderBuilder): Unresolved assembly 'OpenTelemetry.Instrumentation.MySqlData' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AzureContainerAppsDetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.Azure' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AzureVMDetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.Azure' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AzureAppServiceDetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.Azure' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AWSEKSDetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.AWS' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AWSECSDetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.AWS' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AWSEC2DetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.AWS' in 'DynamicDependencyAttribute'.
    ILC : error IL2035: Grafana.OpenTelemetry.AWSEBSDetectorInitializer.InitializeResourceDetector(ResourceBuilder): Unresolved assembly 'OpenTelemetry.Resources.AWS' in 'DynamicDependencyAttribute'.
    D:\packages\nuget\opentelemetry.instrumentation.entityframeworkcore\1.14.0-beta.2\lib\net10.0\OpenTelemetry.Instrumentation.EntityFrameworkCore.dll : error IL2104: Assembly 'OpenTelemetry.Instrumentation.EntityFrameworkCore' produced trim warnings. For more information see https://aka.ms/il2104
    D:\packages\nuget\opentelemetry.instrumentation.quartz\1.14.0-beta.2\lib\net10.0\OpenTelemetry.Instrumentation.Quartz.dll : error IL2104: Assembly 'OpenTelemetry.Instrumentation.Quartz' produced trim warnings. For more information see https://aka.ms/il2104
    D:\packages\nuget\opentelemetry.instrumentation.elasticsearchclient\1.14.0-beta.1\lib\netstandard2.0\OpenTelemetry.Instrumentation.ElasticsearchClient.dll : error IL2104: Assembly 'OpenTelemetry.Instrumentation.ElasticsearchClient' produced trim warnings. For more information see https://aka.ms/il2104
    D:\packages\nuget\hangfire.core\1.7.0\lib\netstandard2.0\Hangfire.Core.dll : error IL2104: Assembly 'Hangfire.Core' produced trim warnings. For more information see https://aka.ms/il2104
    D:\packages\nuget\opentelemetry.instrumentation.elasticsearchclient\1.14.0-beta.1\lib\netstandard2.0\OpenTelemetry.Instrumentation.ElasticsearchClient.dll : error IL3053: Assembly 'OpenTelemetry.Instrumentation.ElasticsearchClient' produced AOT analysis warnings.
    D:\packages\nuget\hangfire.core\1.7.0\lib\netstandard2.0\Hangfire.Core.dll : error IL3053: Assembly 'Hangfire.Core' produced AOT analysis warnings.
  1. Any dynamic dependency where the assembly isn't in the compiled output will generate an IL2035 error. Given that no realistic application will contain every single instrumentation library we support, there will always be an error (e.g. you wouldn't use MySQL.Data.OpenTelemetry and OpenTelemetry.Instrumentation.MySqlData and are unlikely to use both OpenTelemetry.Resources.AWS and OpenTelemetry.Resources.Azure).
  2. Assemblies that are present, but are not AoT-compatible themselves, then introduce errors through the types included as dynamic dependencies (e.g. OpenTelemetry.Instrumentation.EntityFrameworkCore, OpenTelemetry.Instrumentation.Quartz, OpenTelemetry.Instrumentation.ElasticsearchClient and Hangfire.Core).

Without a radical redesign, that would undercut the "plug-and-play" design philosophy, I think the most reasonable path forward would be to instead just bubble the "not supported" nature all the way up to the top-most public API surface area that's relevant then we could mark the assembly as AoT-compatible. This wouldn't actually make the library AoT compatible, but it would make it explicit in the relevant code paths and users could potentially use compile-time checks to conditionally include the relevant code paths (or not) in the consuming apps.

I'll have a quick look at that in a separate PR now to see if it's trivial enough to do and makes sense. If it's too viral, then we can just leave the explicit "not supported" from #97 present and document it as not supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant