-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add "baggage" policy to tailsamplingprocessor #18462
Comments
Pinging code owners:
See Adding Labels via Comments if you do not have permissions to add labels yourself. |
@jpkrohling Hi! What would be the best place to start discussion for the way to "force" sampling on initial request? I am not sure if we will be able to come up with a standard, but at least maybe we could provide a recommended approach. Alternative way to achieve it I considered is:
This approach has an advantage from the one with "passing via attributes" I described above, because it could be used in head-sampling configuration as well. The only thing that is missing to make this approach work for head-sampling is a custom sampler which will check for |
Do you think this discussion can wait a bit? I'll be AFK for a couple of weeks starting tomorrow, and unfortunately, I cannot give this one here a proper thought. |
Sure, no problem👍 |
After further testing, I've decided to use the second approach. It is much more robust and ensures that class ForceSampler(sampling.Sampler):
"""
Sampler that runs base_sampler and checks 'baggage' header for 'force_sample=1'.
If force_sample=1 is present add 'internal=fs:1' to 'tracestate' header and sets
SamplingResult.decision to RECORD_AND_SAMPLE.
Else in samples like base_sampler.
This way we ensure that this approach will work for both head-sampling and
tail-sampling. To check for 'tracestate' in tail-sampling configuration use
'trace_state' policy in tailsamplingprocessor
{
name: force-sample-policy,
type: trace_state,
trace_state: { key: internal, values: ["fs:1"] },
},
"""
def __init__(self, base_sampler: sampling.Sampler = None):
if base_sampler is None:
base_sampler = sampling._get_from_env_or_default()
self.base_sampler = base_sampler
super().__init__()
def should_sample(
self,
parent_context: Context | None,
trace_id: int,
name: str,
kind: SpanKind = None,
attributes: Attributes = None,
links: Sequence[Link] = None,
trace_state: TraceState = None,
) -> sampling.SamplingResult:
base_sampling_result = self.base_sampler.should_sample(
parent_context=parent_context,
trace_id=trace_id,
name=name,
kind=kind,
attributes=attributes,
links=links,
)
trace_state = base_sampling_result.trace_state
# apply sampling based on baggage
force_sample = baggage.get_baggage("force_sample", parent_context)
if force_sample == "1":
if trace_state is None:
trace_state = TraceState()
trace_state = trace_state.update(key="internal", value="fs:1")
# return new result that is Sampled in case of head-sampling and
# has 'internal=fs:1' added to 'tracestate' to check in tail-sampling
return sampling.SamplingResult(
decision=sampling.Decision.RECORD_AND_SAMPLE,
attributes=base_sampling_result.attributes,
trace_state=trace_state,
)
def get_description(self) -> str:
return "ForceSampler" Usage:
Make a request by passing |
Alright, if we need to come back to this, let me know and I'll reopen this. |
@jpkrohling Hi. I think there was some confusion because the feature request and the reason for this request were not quite aligned. I still think having an option to create a "baggage" policy in Can we keep this issue open? If my questions about Also, I wanted to start a separate discussion about |
The reason I closed is that you seem to have been able to accomplish your needs without us having to implement a new feature. Unless there's something you couldn't otherwise do, I would not implement a new sampling policy. About forcing a trace to be sampled: I know we had a debug flag in Jaeger (https://github.com/jaegertracing/jaeger-client-java#debug-traces-forced-sampling), and I would have thought that the trace parent's sampled flag would be equivalent: https://www.w3.org/TR/trace-context/#sampled-flag . Did you try that and confirm that it doesn't work? If it doesn't, perhaps you could check first with the language-specific SDK you are using. |
If we add "baggage" policy for the
Thanks, I will check this out.
I also hopped that Let's say my backend is instrumented and frontend is not. This means if I wanted to rely on |
Not sure I'm following it entirely, but if you are sending a custom HTTP header with the sampling flag, surely you can also generate a UUID as the trace ID and send it along? You don't have to instrument your frontend for that. |
We could, but it will require ForceSample users to generate UUID manually before setting the header. Also, it is quite cumbersome to set self-generated trace_id when using SDKs' for web frameworks like django. |
Got it. I'm still not sure the proper solution involves baggage items, but perhaps you could start a thread on the #otel-collector Slack channel or join one of our SIG Collector meetings, so that we can have a wider discussion about the possible solutions? |
Sure, I will create a discussion in the Slack channel |
This issue has been inactive for 60 days. It will be closed in 60 days if there is no activity. To ping code owners by adding a component label, see Adding Labels via Comments, or if you are unsure of which component this issue relates to, please ping Pinging code owners:
See Adding Labels via Comments if you do not have permissions to add labels yourself. |
Sorry for the delay, https://cloud-native.slack.com/archives/CJFCJHG4Q/p1685526853777769 |
Closing this issue for now. I hope discussion in slack will help us with finding a general solution for ForceSample feature |
Component(s)
processor/tailsampling
Is your feature request related to a problem? Please describe.
As far as I know, there is no existing mechanism to "force" span creation (sampling) on initial request, before trace context is created. For example, by setting a header or a cookie in the browser before making a request to the page.
I've spent a couple of days trying to see what parts of OpenTelemetry's specification and w3c's specs (i.e., https://www.w3.org/TR/trace-context/ and https://www.w3.org/TR/baggage/) I could reuse to get desired functionality. My current idea is to set
baggage: force_sample=1
header on the initial request and configuretailsamplingprocessor
to sample based on this parameter. But due totailsamplingprocessor
not havingbaggage
policy, I will have to set custom span attribute ifbaggage: force_sample=1
header is present via sdk and then enablenumeric_attribute
policy on collector withtailsamplingprocessor
.Maybe the way for "forcing" sampling on initial request should be discussed separately, but nonetheless, I think
baggage
policy may be useful intailsamplingprocessor
Describe the solution you'd like
I think having
baggage
policy would be useful intailsamplingprocessor
for many usecases.Describe alternatives you've considered
No response
Additional context
open-telemetry/opentelemetry-go#2651
The text was updated successfully, but these errors were encountered: