generated from amazon-archives/__template_Apache-2.0
-
Notifications
You must be signed in to change notification settings - Fork 26
Support code attributes for client libraries #491
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
Merged
Merged
Changes from 6 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
6727782
improve quality of adding code attributes
wangzlei 7fea999
support code attributes for client libraries
wangzlei 378df97
fix spellcheck
wangzlei 48422a0
fix missing the first lib in 3rd.txt
wangzlei 66fd035
skip spellcheck for 3rd.txt
wangzlei 170c299
fix unit test
wangzlei 2fccdd2
fix comments
wangzlei 37c5f5e
fix lint
wangzlei 63cbf68
fix lint
wangzlei 696dcfb
Merge branch 'main' into main
wangzlei 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
[codespell] | ||
# skipping auto generated folders | ||
skip = ./.tox,./.mypy_cache,./target,*/LICENSE,./venv,*/sql_dialect_keywords.json | ||
ignore-words-list = afterall,assertIn, crate | ||
skip = ./.tox,./.mypy_cache,./target,*/LICENSE,./venv,*/sql_dialect_keywords.json,*/3rd.txt | ||
ignore-words-list = afterall,assertIn, crate |
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
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
117 changes: 117 additions & 0 deletions
117
...distro/src/amazon/opentelemetry/distro/code_correlation/code_attributes_span_processor.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,117 @@ | ||
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
""" | ||
Code Attributes Span Processor implementation for OpenTelemetry Python. | ||
|
||
This processor captures stack traces and attaches them to spans as attributes. | ||
It's based on the OpenTelemetry Java contrib StackTraceSpanProcessor. | ||
""" | ||
|
||
import sys | ||
import typing as t | ||
from types import FrameType | ||
from typing import Optional | ||
|
||
from opentelemetry.context import Context | ||
from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor | ||
from opentelemetry.trace import SpanKind | ||
|
||
from .constants import CODE_FUNCTION_NAME | ||
from .internal.packages import _build_package_mapping, _load_third_party_packages, is_user_code | ||
from .utils import add_code_attributes_to_span_from_frame | ||
|
||
|
||
class CodeAttributesSpanProcessor(SpanProcessor): | ||
""" | ||
A SpanProcessor that captures and attaches code attributes to spans. | ||
|
||
This processor adds stack trace information as span attributes, which can be | ||
useful for debugging and understanding the call flow that led to span creation. | ||
""" | ||
|
||
# Maximum number of stack frames to examine | ||
MAX_STACK_FRAMES = 50 | ||
|
||
@staticmethod | ||
def _iter_stack_frames(frame: FrameType) -> t.Iterator[FrameType]: | ||
"""Iterate through stack frames starting from the given frame.""" | ||
_frame: t.Optional[FrameType] = frame | ||
while _frame is not None: | ||
yield _frame | ||
_frame = _frame.f_back | ||
|
||
def __init__(self): | ||
"""Initialize the CodeAttributesSpanProcessor.""" | ||
# Pre-initialize expensive operations to avoid runtime performance overhead | ||
# These @execute_once methods are slow, so we call them during initialization | ||
# to cache their results ahead of time | ||
_build_package_mapping() | ||
_load_third_party_packages() | ||
|
||
def on_start( | ||
self, | ||
span: Span, | ||
parent_context: Optional[Context] = None, | ||
) -> None: | ||
""" | ||
Called when a span is started. Captures and attaches code attributes from stack trace. | ||
|
||
Args: | ||
span: The span that was started | ||
parent_context: The parent context (unused) | ||
""" | ||
# Skip if span should not be processed | ||
if not self._should_process_span(span): | ||
return | ||
|
||
# Capture code attributes from stack trace | ||
self._capture_code_attributes(span) | ||
|
||
@staticmethod | ||
def _should_process_span(span: Span) -> bool: | ||
""" | ||
Determine if span should be processed for code attributes. | ||
|
||
Returns False if: | ||
- Span already has code attributes | ||
- Span is not a client span | ||
""" | ||
# Skip if span already has code attributes | ||
if span.attributes is not None and CODE_FUNCTION_NAME in span.attributes: | ||
return False | ||
|
||
# Only process client spans | ||
return span.kind == SpanKind.CLIENT | ||
|
||
def _capture_code_attributes(self, span: Span) -> None: | ||
"""Capture and attach code attributes from current stack trace.""" | ||
try: | ||
current_frame = sys._getframe(1) | ||
|
||
for frame_index, frame in enumerate(self._iter_stack_frames(current_frame)): | ||
if frame_index >= self.MAX_STACK_FRAMES: | ||
break | ||
|
||
code = frame.f_code | ||
|
||
if is_user_code(code.co_filename): | ||
add_code_attributes_to_span_from_frame(frame, span) | ||
break # Only capture the first user code frame | ||
|
||
except (OSError, ValueError): | ||
# sys._getframe may not be available on all platforms | ||
pass | ||
|
||
def on_end(self, span: ReadableSpan) -> None: | ||
""" | ||
Called when a span is ended. Captures and attaches stack trace if conditions are met. | ||
""" | ||
|
||
def shutdown(self) -> None: | ||
"""Called when the processor is shutdown. No cleanup needed.""" | ||
# No cleanup needed for code attributes processor | ||
|
||
def force_flush(self, timeout_millis: int = 30000) -> bool: # pylint: disable=no-self-use,unused-argument | ||
"""Force flush any pending spans. Always returns True as no pending work.""" | ||
return True |
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.