-
Notifications
You must be signed in to change notification settings - Fork 731
Add experimental composite sampler #4714
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
Open
anuraaga
wants to merge
7
commits into
open-telemetry:main
Choose a base branch
from
anuraaga:consistent-sampler
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,120
−0
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
49a5351
Add experimental consistent sampler
anuraaga da6d90e
Fix import
anuraaga 3af3709
Fix lint
anuraaga 38305dc
CHANGELOG
anuraaga 3c11c99
Fix test name
anuraaga 9890ddf
Cleanup and match spec better
anuraaga 35a2eff
Format
anuraaga File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
opentelemetry-sdk/src/opentelemetry/sdk/trace/_sampling_experimental/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
__all__ = [ | ||
"ComposableSampler", | ||
"SamplingIntent", | ||
"composable_always_off", | ||
"composable_always_on", | ||
"composable_parent_threshold", | ||
"composable_traceid_ratio_based", | ||
"composite_sampler", | ||
] | ||
|
||
|
||
from ._always_off import composable_always_off | ||
from ._always_on import composable_always_on | ||
from ._composable import ComposableSampler, SamplingIntent | ||
from ._parent_threshold import composable_parent_threshold | ||
from ._sampler import composite_sampler | ||
from ._traceid_ratio import composable_traceid_ratio_based |
55 changes: 55 additions & 0 deletions
55
opentelemetry-sdk/src/opentelemetry/sdk/trace/_sampling_experimental/_always_off.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from __future__ import annotations | ||
|
||
from typing import Sequence | ||
|
||
from opentelemetry.context import Context | ||
from opentelemetry.trace import Link, SpanKind, TraceState | ||
from opentelemetry.util.types import Attributes | ||
|
||
from ._composable import ComposableSampler, SamplingIntent | ||
from ._util import INVALID_THRESHOLD | ||
|
||
_intent = SamplingIntent(threshold=INVALID_THRESHOLD, threshold_reliable=False) | ||
|
||
|
||
class _ComposableAlwaysOffSampler(ComposableSampler): | ||
def sampling_intent( | ||
self, | ||
parent_ctx: Context | None, | ||
name: str, | ||
span_kind: SpanKind | None, | ||
attributes: Attributes, | ||
links: Sequence[Link] | None, | ||
trace_state: TraceState | None = None, | ||
) -> SamplingIntent: | ||
return _intent | ||
|
||
def get_description(self) -> str: | ||
return "ComposableAlwaysOff" | ||
|
||
|
||
_always_off = _ComposableAlwaysOffSampler() | ||
|
||
|
||
def composable_always_off() -> ComposableSampler: | ||
"""Returns a composable sampler that does not sample any span. | ||
|
||
- Always returns a SamplingIntent with no threshold, indicating all spans should be dropped | ||
- Sets threshold_reliable to false | ||
- Does not add any attributes | ||
""" | ||
return _always_off |
55 changes: 55 additions & 0 deletions
55
opentelemetry-sdk/src/opentelemetry/sdk/trace/_sampling_experimental/_always_on.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from __future__ import annotations | ||
|
||
from typing import Sequence | ||
|
||
from opentelemetry.context import Context | ||
from opentelemetry.trace import Link, SpanKind, TraceState | ||
from opentelemetry.util.types import Attributes | ||
|
||
from ._composable import ComposableSampler, SamplingIntent | ||
from ._util import MIN_THRESHOLD | ||
|
||
_intent = SamplingIntent(threshold=MIN_THRESHOLD) | ||
|
||
|
||
class _ComposableAlwaysOnSampler(ComposableSampler): | ||
def sampling_intent( | ||
self, | ||
parent_ctx: Context | None, | ||
name: str, | ||
span_kind: SpanKind | None, | ||
attributes: Attributes, | ||
links: Sequence[Link] | None, | ||
trace_state: TraceState | None = None, | ||
) -> SamplingIntent: | ||
return _intent | ||
|
||
def get_description(self) -> str: | ||
return "ComposableAlwaysOn" | ||
|
||
|
||
_always_on = _ComposableAlwaysOnSampler() | ||
|
||
|
||
def composable_always_on() -> ComposableSampler: | ||
"""Returns a composable sampler that samples all spans. | ||
|
||
- Always returns a SamplingIntent with threshold set to sample all spans (threshold = 0) | ||
- Sets threshold_reliable to true | ||
- Does not add any attributes | ||
""" | ||
return _always_on |
59 changes: 59 additions & 0 deletions
59
opentelemetry-sdk/src/opentelemetry/sdk/trace/_sampling_experimental/_composable.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass, field | ||
from typing import Callable, Protocol, Sequence | ||
|
||
from opentelemetry.context import Context | ||
from opentelemetry.trace import Link, SpanKind, TraceState | ||
from opentelemetry.util.types import Attributes | ||
|
||
|
||
@dataclass(frozen=True) | ||
class SamplingIntent: | ||
"""Information to make a consistent sampling decision.""" | ||
|
||
threshold: int | ||
"""The sampling threshold value. A lower threshold increases the likelihood of sampling.""" | ||
|
||
threshold_reliable: bool = field(default=True) | ||
"""Indicates whether the threshold is reliable for Span-to-Metrics estimation.""" | ||
|
||
attributes: Attributes = field(default=None) | ||
"""Any attributes to be added to a sampled span.""" | ||
|
||
update_trace_state: Callable[[TraceState], TraceState] = field( | ||
default=lambda ts: ts | ||
) | ||
"""Any updates to be made to trace state.""" | ||
|
||
|
||
class ComposableSampler(Protocol): | ||
"""A sampler that can be composed to make a final sampling decision.""" | ||
|
||
def sampling_intent( | ||
self, | ||
parent_ctx: Context | None, | ||
name: str, | ||
span_kind: SpanKind | None, | ||
attributes: Attributes, | ||
links: Sequence[Link] | None, | ||
trace_state: TraceState | None, | ||
) -> SamplingIntent: | ||
"""Returns information to make a sampling decision.""" | ||
|
||
def get_description(self) -> str: | ||
"""Returns a description of the sampler.""" |
89 changes: 89 additions & 0 deletions
89
opentelemetry-sdk/src/opentelemetry/sdk/trace/_sampling_experimental/_parent_threshold.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Copyright The OpenTelemetry Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from __future__ import annotations | ||
|
||
from typing import Sequence | ||
|
||
from opentelemetry.context import Context | ||
from opentelemetry.trace import Link, SpanKind, TraceState, get_current_span | ||
from opentelemetry.util.types import Attributes | ||
|
||
from ._composable import ComposableSampler, SamplingIntent | ||
from ._trace_state import OtelTraceState | ||
from ._util import ( | ||
INVALID_THRESHOLD, | ||
MIN_THRESHOLD, | ||
is_valid_threshold, | ||
) | ||
|
||
|
||
class _ComposableParentThreshold(ComposableSampler): | ||
def __init__(self, root_sampler: ComposableSampler): | ||
self._root_sampler = root_sampler | ||
self._description = f"ComposableParentThreshold{{root={root_sampler.get_description()}}}" | ||
|
||
def sampling_intent( | ||
self, | ||
parent_ctx: Context | None, | ||
name: str, | ||
span_kind: SpanKind | None, | ||
attributes: Attributes, | ||
links: Sequence[Link] | None, | ||
trace_state: TraceState | None = None, | ||
) -> SamplingIntent: | ||
parent_span = get_current_span(parent_ctx) | ||
parent_span_ctx = parent_span.get_span_context() | ||
is_root = not parent_span_ctx.is_valid | ||
if is_root: | ||
return self._root_sampler.sampling_intent( | ||
parent_ctx, name, span_kind, attributes, links, trace_state | ||
) | ||
|
||
ot_trace_state = OtelTraceState.parse(trace_state) | ||
|
||
if is_valid_threshold(ot_trace_state.threshold): | ||
return SamplingIntent( | ||
threshold=ot_trace_state.threshold, | ||
threshold_reliable=True, | ||
) | ||
|
||
threshold = ( | ||
MIN_THRESHOLD | ||
if parent_span_ctx.trace_flags.sampled | ||
else INVALID_THRESHOLD | ||
) | ||
return SamplingIntent(threshold=threshold, threshold_reliable=False) | ||
|
||
def get_description(self) -> str: | ||
return self._description | ||
|
||
|
||
def composable_parent_threshold( | ||
root_sampler: ComposableSampler, | ||
) -> ComposableSampler: | ||
"""Returns a consistent sampler that respects the sampling decision of | ||
the parent span or falls-back to the given sampler if it is a root span. | ||
|
||
- For spans without a parent context, delegate to the root sampler | ||
- For spans with a parent context, returns a SamplingIntent that propagates the parent's sampling decision | ||
- Returns the parent's threshold if available; otherwise, if the parent's sampled flag is set, | ||
returns threshold=0; otherwise, if the parent's sampled flag is not set, no threshold is returned. | ||
- Sets threshold_reliable to match the parent’s reliability, which is true if the parent had a threshold. | ||
- Does not add any attributes | ||
|
||
Args: | ||
root_sampler: The root sampler to use for spans without a parent context. | ||
""" | ||
return _ComposableParentThreshold(root_sampler) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.