[OpenTelementry] Fix circular reference#7308
Conversation
Fix circular reference when `LoggerProvider` requires `ILogger`.
Add CHANGELOG entry.
Add PR number.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7308 +/- ##
==========================================
- Coverage 89.81% 89.72% -0.10%
==========================================
Files 276 276
Lines 14822 14838 +16
==========================================
Hits 13313 13313
- Misses 1509 1525 +16
Flags with carried forward coverage won't be shown. Click here to find out more.
|
Resolve an ILogger to force resolution of dependencies.
Fix test that stopped throwing `NotSupportedException` to resolve the `ILoggerProvider` and `LoggerFactory` due to deferred creation.
There was a problem hiding this comment.
Pull request overview
This PR addresses a circular dependency in the logging DI integration when LoggerProvider construction requires ILogger/ILoggerFactory (e.g., via dependencies like IHttpClientFactory). It does so by deferring LoggerProvider resolution until the first logger is actually created, avoiding a re-entrant LoggerProvider build.
Changes:
- Update
OpenTelemetryLoggingExtensionsto pass aFunc<LoggerProvider>intoOpenTelemetryLoggerProvider, delayingLoggerProviderresolution toCreateLogger. - Make
OpenTelemetryLoggerProviderlazily initialize and cache theLoggerProviderfrom the provided factory (thread-safe). - Update affected tests (and changelog) to trigger the new lazy behavior by creating a logger.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggingExtensions.cs |
Defers LoggerProvider resolution via a factory to avoid circular references during DI construction. |
src/OpenTelemetry/Logs/ILogger/OpenTelemetryLoggerProvider.cs |
Lazily resolves/caches LoggerProvider with synchronization to support deferred DI resolution. |
test/OpenTelemetry.Tests/Logs/OpenTelemetryLoggingExtensionsTests.cs |
Adjusts assertions and ensures circular-reference scenario is exercised by creating a logger. |
test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs |
Forces logger creation so configuration delegates are exercised under the new lazy-resolution behavior. |
test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpExporterHelperExtensionsTests.cs |
Updates the “throws on gRPC default factory” logging test to trigger failure via CreateLogger. |
src/OpenTelemetry/CHANGELOG.md |
Notes the circular reference fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Update test to assert that creating a logger from the logger provider throws `NotSupportedException`.
|
Asked Noah and Tarek to take a look at this PR. |
|
Thanks for digging this one out, nice find. The overall approach looks right to me: deferring the A few things worth considering before this goes in: 1. The deferred exception timing (your stated hesitation). I think this is the most important point to get explicit agreement on. Today a misconfiguration (like the OTLP gRPC default-factory 2. Memory model on the lazy field. The 3. Worth weighing 4. Does None of these block the direction, which I think is correct. Mostly want to make sure the exception-timing change is a conscious decision. Thanks again! |
|
I don't think I have anything to add to what @tarekgh already called out :) |
- Use `Volatile.Read/Write` to access provider. - Do not cache logging provider resolution failures. - Update CHANGELOG entry. - Add explanatory comments.
|
Comments should now be addressed. |
Updated [OpenTelemetry.Exporter.OpenTelemetryProtocol](https://github.com/open-telemetry/opentelemetry-dotnet) from 1.15.3 to 1.16.0. <details> <summary>Release notes</summary> _Sourced from [OpenTelemetry.Exporter.OpenTelemetryProtocol's releases](https://github.com/open-telemetry/opentelemetry-dotnet/releases)._ ## 1.16.0 For highlights and announcements pertaining to this release see: [Release Notes > 1.16.0](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/RELEASENOTES.md#1160). The following changes are from the previous release [1.16.0-rc.1](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.16.0-rc.1). * NuGet: [OpenTelemetry v1.16.0](https://www.nuget.org/packages/OpenTelemetry/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Api v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Api/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry.Api/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Api.ProviderBuilderExtensions v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Api.ProviderBuilderExtensions/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry.Api.ProviderBuilderExtensions/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Exporter.Console v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Exporter.Console/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry.Exporter.Console/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Exporter.InMemory v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Exporter.InMemory/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry.Exporter.InMemory/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Exporter.OpenTelemetryProtocol v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Exporter.OpenTelemetryProtocol/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Exporter.Zipkin v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Exporter.Zipkin/1.16.0) No notable changes. See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Extensions.Hosting v1.16.0](https://www.nuget.org/packages/OpenTelemetry.Extensions.Hosting/1.16.0) No notable changes. ... (truncated) ## 1.16.0-rc.1 The following changes are from the previous release [1.15.3](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/core-1.15.3). * NuGet: [OpenTelemetry v1.16.0-rc.1](https://www.nuget.org/packages/OpenTelemetry/1.16.0-rc.1) * Stop validating View-provided metric stream `Name` against the instrument name syntax, per [spec clarification](open-telemetry/opentelemetry-specification#5094). ([#7300](open-telemetry/opentelemetry-dotnet#7300)) * Fix incorrect validation of `OTEL_BSP_*` and `OTEL_BLRP_*` environment variables. ([#7187](open-telemetry/opentelemetry-dotnet#7187)) * Fix observable instrument callbacks running once per reader instead of once per collection cycle. ([#7188](open-telemetry/opentelemetry-dotnet#7188)) * Added exception safety for user-supplied `ExemplarReservoir` implementations. Exceptions thrown from `Offer` are now caught and logged rather than propagating out of `Counter.Add`/`Histogram.Record`. ([#7277](open-telemetry/opentelemetry-dotnet#7277)) * Update `OpenTelemetrySdkEventSource` to support the W3C randomness flag. ([#7301](open-telemetry/opentelemetry-dotnet#7301)) * Added `ObservedTimestamp` property to `LogRecord`. ([#6979](open-telemetry/opentelemetry-dotnet#6979)) * **Breaking Change** Explicit histogram boundaries no longer allow more than 10 million values. ([#7165](open-telemetry/opentelemetry-dotnet#7165)) * Fixed a circular reference which could cause a `LoggerProvider` to fail to resolve when one of its dependencies depends on `ILogger` or `ILoggerFactory`. As part of this fix the `LoggerProvider` resolved from dependency injection is now created lazily when the first logger is created rather than when `ILoggerProvider` or `ILoggerFactory` is resolved. A consequence is that any invalid configuration now surfaces when the first log record is written instead of when the logging services are resolved. ([#7308](open-telemetry/opentelemetry-dotnet#7308)) See [CHANGELOG](https://github.com/open-telemetry/opentelemetry-dotnet/blob/core-1.16.0-rc.1/src/OpenTelemetry/CHANGELOG.md) for details. * NuGet: [OpenTelemetry.Api v1.16.0-rc.1](https://www.nuget.org/packages/OpenTelemetry.Api/1.16.0-rc.1) * **Experimental (pre-release builds only):** Add support for using environment variables as context propagation carriers. ([#7174](open-telemetry/opentelemetry-dotnet#7174)) * Fix `BaggagePropagator` to correctly follow Key and Value Encoding rules as per ... (truncated) ## 1.16.0-beta.1 The following changes are from the previous release [1.15.3-beta.1](https://github.com/open-telemetry/opentelemetry-dotnet/releases/tag/coreunstable-1.15.3-beta.1). * NuGet: [OpenTelemetry.Exporter.Prometheus.AspNetCore v1.16.0-beta.1](https://www.nuget.org/packages/OpenTelemetry.Exporter.Prometheus.AspNetCore/1.16.0-beta.1) * Fixed scrape response cache freshness using monotonic time so it is not affected by NTP system clock adjustments. ([#7253](open-telemetry/opentelemetry-dotnet#7253)) * **Breaking Change** Removed `DisableTimestamp` property from `PrometheusAspNetCoreOptions`. ([#7176](open-telemetry/opentelemetry-dotnet#7176)) * Fixed the serialization of `NaN`, `PositiveInfinity`, and `NegativeInfinity` values in Prometheus metrics to be compliant with the specification. ([#7179](open-telemetry/opentelemetry-dotnet#7179)) * Fixed loss of precision when serializing `double` and `float` values in Prometheus metrics to be compliant with the specification by using 17 significant digits to represent such values. ([#7179](open-telemetry/opentelemetry-dotnet#7179)) * Fix non-ASCII characters in metric names and unit strings not being sanitized correctly during Prometheus serialization. ([#7184](open-telemetry/opentelemetry-dotnet#7184)) * Fix case where reader tracking could be reset while readers were still active. ([#7190](open-telemetry/opentelemetry-dotnet#7190)) * Improve `Accept` header handling for format negotiation so OpenMetrics is selected correctly by considering whitespace and `q` weights. ([#7208](open-telemetry/opentelemetry-dotnet#7208)) * Emit OpenMetrics exemplars for counters and histogram buckets. ([#7222](open-telemetry/opentelemetry-dotnet#7222)) * Fix incorrect handling of untyped metrics when using OpenMetrics format. ([#7219](open-telemetry/opentelemetry-dotnet#7219)) * Fix Prometheus/OpenMetrics serialization to emit metric and label names containing `_` instead of dropping them and prefixing leading digits. Invalid characters are replaced with `_` instead of being dropped. ([#7209](open-telemetry/opentelemetry-dotnet#7209)) * Add `escaping=underscores` to the `Accept` header handling for content negotiation so OpenMetrics are handled correctly. ([#7209](open-telemetry/opentelemetry-dotnet#7209)) * Omit histogram `_sum` and `_count` in OpenMetrics when negative bucket thresholds are present. ([#7221](open-telemetry/opentelemetry-dotnet#7221)) ... (truncated) Commits viewable in [compare view](open-telemetry/opentelemetry-dotnet@core-1.15.3...core-1.16.0). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Vitor M <4777793+vgmello@users.noreply.github.com>
Found in #6899.
Changes
Fix circular reference when
LoggerProviderrequiresILogger.My only hesitation on this change as-is is the fact that I've had to update two tests outside of OpenTelemetry.Tests to account for this change and that the exception is only now thrown at the point
ILoggeris resolved and notILoggerFactory. Thoughts?Merge requirement checklist
CHANGELOG.mdfiles updated for non-trivial changesChanges in public API reviewed (if applicable)