Skip to content

Conversation

jade-guiton-dd
Copy link
Contributor

@jade-guiton-dd jade-guiton-dd commented Oct 8, 2025

Description

This PR splits the code handling component attribute injection, currently in internal/telemetry and internal/telemetry/componentattribute, into three parts:

  • the part meant to be called by components to drop unwanted injected attributes, which remains in internal/telemetry;
  • the part which handles copying Zap logs to an OTel LoggerProvider (where injected attributes are surfaced as instrumentation scope attributes), which is moved into service/telemetry/otelconftelemetry, since this "copying" behavior is specific to the otelconf-based telemetry provider;
  • the rest is moved into service/internal/componentattribute.

The main goals of this split are:

I also rewrote a lot of the attribute injection code along the way:

  • Instead of adding an unexported field in TelemetrySettings to store the current set of injected attributes, this set is now stored inside the provider wrappers (which was already partly the case). This allowed me to move the TelemetrySettings definition back into component, removing the dependency it had on componentattribute.

  • I completely changed the approach for injection in logs. Instead of a chain of custom core wrappers with a withAttributeSet method, injected attributes are now set through the standard zapcore.Core.With method. By introducing a custom ObjectMarshaler, we can make injected attributes act like regular Zap fields, while also allowing special handling in the otelzap wrapper core, which will set them as instrumentation scope attributes instead of log record attributes.

If I'm not mistaken, this PR should have no externally-visible changes, so no changelog should be necessary. (Except maybe the _ struct{} in TelemetrySettings, but there was no changelog when we added those elsewhere)

Link to tracking issue

Updates #13842

Testing

The large amounts of splitting and refactoring led me to abandon the existing tests, as they would be too hard to adapt. I wrote new tests for the code in service/telemetry/otelconftelemetry and service/internal/componentattribute, which hopefully should fill that gap appropriately.

Copy link

codecov bot commented Oct 9, 2025

Codecov Report

❌ Patch coverage is 86.12717% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.59%. Comparing base (5bdfd09) to head (9764fde).
⚠️ Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
internal/telemetry/telemetry.go 0.00% 11 Missing ⚠️
service/telemetry/otelconftelemetry/logger_tee.go 77.27% 10 Missing ⚠️
service/internal/componentattribute/logger_zap.go 91.89% 2 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (86.12%) is below the target coverage (95.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #13948      +/-   ##
==========================================
- Coverage   91.66%   91.59%   -0.08%     
==========================================
  Files         654      657       +3     
  Lines       42659    42744      +85     
==========================================
+ Hits        39104    39151      +47     
- Misses       2741     2774      +33     
- Partials      814      819       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jade-guiton-dd jade-guiton-dd added area:service collector-telemetry healthchecker and other telemetry collection issues Skip Changelog PRs that do not require a CHANGELOG.md entry labels Oct 9, 2025
@jade-guiton-dd jade-guiton-dd marked this pull request as ready for review October 9, 2025 13:23
@jade-guiton-dd jade-guiton-dd requested a review from atoulme October 9, 2025 13:23
@jade-guiton-dd
Copy link
Contributor Author

Regarding code coverage:

  • internal/telemetry/telemetry.go should be covered by service/internal/componentattribute/telemetry_test.go and service/telemetry/otelconftelemetry/logger_test.go
  • internal/telemetry/mock.go is a mock for testing purposes, used in receiver/otlpreceiver/factory_test.go and processor/memorylimiterprocessor/factory_test.go

CodeCov doesn't take these uses into account as they are in different modules.

@jade-guiton-dd
Copy link
Contributor Author

@axw I can't tag you as reviewer but I would appreciate a review from you, notably on how well this fits into the "bring your own SDK" initiative.

Copy link
Contributor

@atoulme atoulme left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Contributor

@axw axw left a comment

Choose a reason for hiding this comment

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

Thanks @jade-guiton-dd, only minor concerns from me.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be in a test package? I realise it doesn't bring in any extra deps, but I think it would be good hygiene to keep test code separate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved it into a internal/telemetry/telemetrytest package.

Comment on lines 52 to 53
if len(fields) == 1 && fields[0].Type == zapcore.InlineMarshalerType {
if saf, ok := fields[0].Interface.(componentattribute.ScopeAttributesField); ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe encapsulate this in the componentattribute package? e.g. have a top-level function called func ScopeAttributesFromFields(fields []zapcore.Field) []attribute.KeyValue. Then the ScopeAttributesField type could be unexported.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or keep the core in componentattribute where it was?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since instantiating an OTel SDK and copying logs to it from the Zap logger is unique to the otelconftelemetry implementation of telemetry.Factory, and since the otelzap dependency this introduces was one of the "problematic" dependencies we wanted to isolate, I'd rather keep this in otelconftelemetry so Collectors build with another telemetry.Factory don't have that dependency.

I can definitely encapsulate the logic better however.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I unexported the ScopeAttributesField type, and replaced it with a ExtractLogScopeAttributes function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Since instantiating an OTel SDK and copying logs to it from the Zap logger is unique to the otelconftelemetry implementation of telemetry.Factory, and since the otelzap dependency this introduces was one of the "problematic" dependencies we wanted to isolate, I'd rather keep this in otelconftelemetry so Collectors build with another telemetry.Factory don't have that dependency.

Ah yeah, thanks for the reminder. Makes sense.

I unexported the ScopeAttributesField type, and replaced it with a ExtractLogScopeAttributes function.

LGTM, thanks!

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

Labels

area:service collector-telemetry healthchecker and other telemetry collection issues Skip Changelog PRs that do not require a CHANGELOG.md entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants