Skip to content

Conversation

@etilite
Copy link
Contributor

@etilite etilite commented Oct 26, 2025

Which problem is this PR solving?

Resolves #3653
Resolves #691

Description of the changes

  • Added option WithAttributesOn which adds jaeger.sampler.param and jaeger.sampler.type attributes for sampled spans

@etilite etilite requested a review from a team as a code owner October 26, 2025 19:07
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Oct 26, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@github-actions github-actions bot requested a review from yurishkuro October 26, 2025 19:07
@flc1125
Copy link
Member

flc1125 commented Oct 27, 2025

cc code owner: @yurishkuro PTAL

Copy link
Member

@dmathieu dmathieu left a comment

Choose a reason for hiding this comment

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

Those attributes don't match anything defined in semantic conventions.

Copy link
Member

@yurishkuro yurishkuro left a comment

Choose a reason for hiding this comment

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

I suggest writing a test in a different package like jaegerremote_test, to make sure you got the visibility of new functions / types correctly


type samplerOptionFunc func(*samplerOptions)

func withAttributesOn() samplerOptionFunc {
Copy link
Member

Choose a reason for hiding this comment

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

I would make then on by default, and have this option to turn off. The function needs to be public in order to be used from a different package.

Suggested change
func withAttributesOn() samplerOptionFunc {
func WithAttributesDisabled() samplerOptionFunc {

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 wasn't sure that we want to change current default behavior - jaegerremote does not set any attributes.

This is supposed to be an internal option for creating and updating samplers which constructors also aren't exported.

For external usage I added WithAttributesOn option.

Copy link
Member

Choose a reason for hiding this comment

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

I do want to change the current behavior. The current behavior is useless, the sampler does not actually work with Jaeger's adaptive backend. And the change itself is additive, it's backwards compatible (especially since the new attributes are prefixed with jaeger.).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

do we need an option to disable these attributes in that case? If not implementation will be simple and no need for internal sampler options too

Copy link
Member

Choose a reason for hiding this comment

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

Personally I would argue you don't even need the opt-out option, OTEL SDK is already extremely verbose in terms of how many attributes it captures, having two extra ones on root span only seems irrelevant. But for 100% backwards compat you would provide an option to opt-out.

samplingRate float64
sampler trace.Sampler
attributes []attribute.KeyValue
attributesOn bool
Copy link
Member

Choose a reason for hiding this comment

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

I think this flag is only used at initialization, you don't really need to store it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When probabilisticSampler or ratelimitngSampler are being updated its init method is also called, so I not sure if we can omit this flag.

Comment on lines 39 to 42
samplerTypeKey = "sampler.type"
samplerTypeValueProbabilistic = "probabilistic"
samplerTypeValueRateLimiting = "ratelimiting"
samplerParamKey = "sampler.param"
Copy link
Member

Choose a reason for hiding this comment

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

I think it would make sense to prefix with jaeger., This may require small change in the backend to recognize, but it separates custom attributes into clear namespace.

Suggested change
samplerTypeKey = "sampler.type"
samplerTypeValueProbabilistic = "probabilistic"
samplerTypeValueRateLimiting = "ratelimiting"
samplerParamKey = "sampler.param"
samplerTypeKey = "jaeger.sampler.type"
samplerParamKey = "jaeger.sampler.param"
samplerTypeValueProbabilistic = "probabilistic"
samplerTypeValueRateLimiting = "ratelimiting"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, this is reasonable but I see some difficulties when using in mixed environments (jaeger and otel services) where will be different sampler attributes in that case. Not sure if backend can support more that one key.

Copy link
Member

Choose a reason for hiding this comment

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

this is a Jaeger-specific functionality and a Jaeger-specific sampler. Since it's not setting any attributes now then nothing is depending on them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So can we keep canonical keys? I did small research and using new keys will require some overhead on collector to transform these attributes.

Copy link
Member

Choose a reason for hiding this comment

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

Since those are jaeger specific, prefixing them with jaeger definitely makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added prefix

@yurishkuro
Copy link
Member

Thank you for this PR! Originally when I looked at this problem there was no way in the API to pass back attributes (I think I even had an option issue about that).

@etilite
Copy link
Contributor Author

etilite commented Oct 27, 2025

Those attributes don't match anything defined in semantic conventions.

Can we do anything about it? Those attributes provide back-compatibility with jaeger-remote-sampler and can be turned only by an option. So yeah it is kinda jaeger attributes.

@dmathieu dmathieu dismissed their stale review October 28, 2025 08:37

Wrong assessment.

@etilite
Copy link
Contributor Author

etilite commented Oct 28, 2025

@dmathieu @yurishkuro If you’re okay with it, I could try a different approach - add two new options - functions that create attributes for probabilistic/ratelimiting samplers, so user can define their own attributes to solve this issue.
This solution does not interfere with the semantic convention.

@dmathieu
Copy link
Member

Sorry, my assessment was wrong. As these are jaeger specific, they shouldn't need semantic conventions.

@codecov
Copy link

codecov bot commented Nov 2, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.8%. Comparing base (6342fe6) to head (6cccfd9).
⚠️ Report is 12 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##            main   #8073     +/-   ##
=======================================
+ Coverage   80.9%   81.8%   +0.8%     
=======================================
  Files        194     194             
  Lines      13073   13380    +307     
=======================================
+ Hits       10588   10949    +361     
+ Misses      2107    2033     -74     
- Partials     378     398     +20     
Files with missing lines Coverage Δ
samplers/jaegerremote/sampler.go 92.0% <100.0%> (+1.0%) ⬆️
samplers/jaegerremote/sampler_remote.go 90.4% <100.0%> (ø)
samplers/jaegerremote/sampler_remote_options.go 98.0% <100.0%> (+<0.1%) ⬆️

... and 8 files with indirect coverage changes

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

@etilite
Copy link
Contributor Author

etilite commented Nov 2, 2025

@yurishkuro I added new test in different package and answered on all comments. Review pls

@flc1125
Copy link
Member

flc1125 commented Nov 3, 2025

@yurishkuro I added new test in different package and answered on all comments. Review pls

We can fix the CI errors before entering the review to reduce some trivial checks. 😁

@etilite etilite force-pushed the jaegerremote-attributes branch from 9cc7fce to 8e6fd09 Compare November 3, 2025 12:38
@flc1125
Copy link
Member

flc1125 commented Nov 3, 2025

@etilite please add a CHANGELOG

@flc1125
Copy link
Member

flc1125 commented Nov 4, 2025

@etilite There are currently some conflicts; please fix them.

@etilite
Copy link
Contributor Author

etilite commented Nov 4, 2025

@flc1125 resolved conflicts but now ci/cd failing. Probably need just to retry these jobs, can't do it myself.

samplerTypeValueRateLimiting = "ratelimiting"
)

type samplerOptions struct {
Copy link
Member

Choose a reason for hiding this comment

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

this is redundant. The package already has the functional options mechanism

func New(
        serviceName string,
        opts ...Option,
) *Sampler {
        options := newConfig(opts...)

So WithAttributesOn() should be implemented as Option just like other options, and should set a flag on the config struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the idea behind these internal options is to have different behavior when creating samplers without need to change every test to add new argument in constructor.
I can use flag arg in sampler's constructors if it is ok with you.

Copy link
Member

Choose a reason for hiding this comment

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

without need to change every test to add new argument in constructor.

a) why do you need to change every test? do they all compare attributes?
b) even if you need to, it seems like a trivial task for a Copilot

Copy link
Contributor Author

@etilite etilite Nov 6, 2025

Choose a reason for hiding this comment

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

a) cause a lot of tests call these constructors
b) yeah but it is harder to review a lot of small changes
nvm I'll change to flag argument 👍


type samplerOptionFunc func(*samplerOptions)

func withAttributesOn() samplerOptionFunc {
Copy link
Member

Choose a reason for hiding this comment

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

I do want to change the current behavior. The current behavior is useless, the sampler does not actually work with Jaeger's adaptive backend. And the change itself is additive, it's backwards compatible (especially since the new attributes are prefixed with jaeger.).

// Sampler invokes the updaters while holding a lock on the main sampler.
type samplerUpdater interface {
Update(sampler trace.Sampler, strategy any) (modified trace.Sampler, err error)
Update(sampler trace.Sampler, strategy any, attributesDisabled bool) (modified trace.Sampler, err error)
Copy link
Member

Choose a reason for hiding this comment

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

It is not necessary to change this interface to pass attributesDisabled. When individual updaters are created the value of this flag is known and can be captured in the updaters themselves. This way we separate configuration information from the execution information (only sampler and strategy are variable at runtime)

Copy link
Contributor Author

@etilite etilite Nov 6, 2025

Choose a reason for hiding this comment

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

Good point! Can I remove withUpdaters option then? Cause it makes harder to properly create updaters and pass attributesDisabled to them. Anyway withUpdaters is not needed for tests now (can be safely removed) and seems to be an old arfifact

Copy link
Member

Choose a reason for hiding this comment

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

withUpdaters is private, safe to remove if not needed. These APIs used to be public for extensibility.

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.

Missing sampler.type & sampler.param attributes/ tags in Jaeger samplers

4 participants