-
Notifications
You must be signed in to change notification settings - Fork 440
refactor(crashtracker): use PyO3 for crashtracker module and crashtracker_exe #12690
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
taegyunkim
wants to merge
99
commits into
main
Choose a base branch
from
taegyunkim/prof-11491-crasht-pyo3
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,270
−1,269
Open
Changes from all commits
Commits
Show all changes
99 commits
Select commit
Hold shift + click to select a range
e6c3101
conditional compile
taegyunkim 8e17854
crashtracker receiver
taegyunkim 889e680
builds
taegyunkim e2b38de
python script for crahstracker_exe
taegyunkim 1b44820
fix rust ci
taegyunkim 370217b
fix lint:fmt
taegyunkim 0dff240
update module path for crashtracker_exe
taegyunkim a24b457
atomic init and status func
taegyunkim 8c99a8c
add defs in .pyi
taegyunkim 59a32bd
Use rust crashtracker
taegyunkim effc567
fix mypy errors
taegyunkim de926e7
fix tests
taegyunkim cdc2732
make crashtracker a feature
taegyunkim 609316d
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 89d0917
bypass sccache for better error messages
taegyunkim 63a14c7
try except for importing crashtracker
taegyunkim a7e5ea1
also handle the case from crashtracker_exe
taegyunkim 1be2faf
reduce CARGO_BUILD_JOBS as jobs are killed with -9 from hatch based jobs
taegyunkim d4b8a6c
add timeout_ms in telemetry
taegyunkim 4df5f66
revive tests
taegyunkim 1e85d45
optimize for size
taegyunkim cfad44e
remove type annotation to pass test on windows
taegyunkim 674e02b
fix fmt
taegyunkim 68e73e0
set CARGO_BUILD_JOBS=4 for some hatch based test suites
taegyunkim 93e29bf
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 3c5f779
set CARGO_BUILD_JOBS=4 for some hatch based test suites
taegyunkim 1919acb
just set it to 4 from gitlab.yml
taegyunkim c286ed7
try this?
taegyunkim b352e28
reduce to 4
taegyunkim 4d257ef
try setting rustc_flags
taegyunkim fd09afc
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim ad20fe2
Squashed commit of the following:
taegyunkim b613854
try opt-level "z"
taegyunkim 552b9a7
mac specific rustc_flags
taegyunkim 615fcb8
cmake format
taegyunkim 94ac23f
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 10d8870
Revert "Squashed commit of the following:"
taegyunkim 2cab420
set codegen-units=1 for further optimization in binary size
taegyunkim 5dd34ef
Discard changes to hatch.toml
taegyunkim f996c9a
Discard changes to .gitlab/tests.yml
taegyunkim 4ba5b19
cleanup
taegyunkim 28de979
enable sccache
taegyunkim d61a480
simple wrap with sccache
taegyunkim a2861b6
format
taegyunkim 80a2367
update crashtracker_exe finding logic
taegyunkim 9042a8c
typo
taegyunkim b1f7ac3
remove anyhow
taegyunkim 23b77ef
use interior mutability and Option<Box<T>>
taegyunkim ff878d7
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 92654db
format
taegyunkim 1a614c5
py_limited_api=cp38 in src/native
taegyunkim 8fb4b35
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 3fe212b
remove Box<_>
taegyunkim d2b1faf
use try_borrow_mut from on_fork
taegyunkim 05418e9
use try_borrow_mut in init
taegyunkim f57180a
remove not(unix) cfg
taegyunkim f81da06
typo
taegyunkim b854d33
error handling
taegyunkim 3ea4cf2
wrap the module with unix
taegyunkim e05f0c2
fix compile
taegyunkim 60f435a
use anyhow feature
taegyunkim c158be7
adjust types
taegyunkim 8383012
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 471062f
format
taegyunkim 1349486
minor changes
taegyunkim ede9ae3
keep opt-level as is
taegyunkim 2155624
remove implementation detail
taegyunkim 629aff5
format rust
taegyunkim 1a733a1
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim fab0087
dont expose crashtracker_exe
taegyunkim 6133fb5
just copy all
taegyunkim 20a5539
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim e34a368
enable test
taegyunkim d2336f3
format
taegyunkim b61d3e5
check for availability
taegyunkim 3a62c76
add line back
taegyunkim 87a580d
disable vpa for now
taegyunkim 7a7c4c2
update flags
taegyunkim 0f19c8b
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 98efaeb
Discard changes to .gitlab-ci.yml
taegyunkim 834e417
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 1a8f639
wrap with try
taegyunkim b0dcd39
format
taegyunkim 159973c
back to command
taegyunkim f944c90
revert back
taegyunkim 911d7ef
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim fca2740
strip even more
taegyunkim 498fe69
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim d336c9e
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 3c8e32a
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 2a740cf
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 6d1601a
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim d6010ac
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim f14f2b1
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 43f0b73
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim c53401a
check for availability
taegyunkim b1e4436
Merge branch 'main' into taegyunkim/prof-11491-crasht-pyo3
taegyunkim 4c36b80
try installing command
taegyunkim 4e58e3a
try opt-level s
taegyunkim 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
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,17 @@ | ||
#!/usr/bin/env python3 | ||
# -*- encoding: utf-8 -*- | ||
|
||
try: | ||
from ddtrace.internal.native._native import crashtracker_receiver | ||
except ImportError: | ||
|
||
def crashtracker_receiver() -> None: | ||
print("Crashtracker receiver not available.") | ||
|
||
|
||
def main(): | ||
crashtracker_receiver() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
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,68 +1,158 @@ | ||
from typing import Callable | ||
import platform | ||
import shutil | ||
from typing import Dict | ||
from typing import Optional | ||
|
||
from ddtrace import config | ||
from ddtrace import version | ||
from ddtrace.internal.datadog.profiling import crashtracker | ||
from ddtrace.internal import forksafe | ||
from ddtrace.internal.compat import ensure_text | ||
from ddtrace.internal.runtime import get_runtime_id | ||
from ddtrace.internal.runtime import on_runtime_id_change | ||
from ddtrace.settings._agent import config as agent_config | ||
from ddtrace.settings.crashtracker import config as crashtracker_config | ||
from ddtrace.settings.profiling import config as profiling_config | ||
from ddtrace.settings.profiling import config_str | ||
|
||
|
||
is_available: bool = crashtracker.is_available | ||
failure_msg: str = crashtracker.failure_msg | ||
is_started: Callable[[], bool] = crashtracker.is_started | ||
is_available = True | ||
try: | ||
from ddtrace.internal.native._native import CrashtrackerConfiguration | ||
from ddtrace.internal.native._native import CrashtrackerMetadata | ||
from ddtrace.internal.native._native import CrashtrackerReceiverConfig | ||
from ddtrace.internal.native._native import CrashtrackerStatus | ||
from ddtrace.internal.native._native import StacktraceCollection | ||
from ddtrace.internal.native._native import crashtracker_init | ||
from ddtrace.internal.native._native import crashtracker_on_fork | ||
from ddtrace.internal.native._native import crashtracker_status | ||
except ImportError: | ||
is_available = False | ||
|
||
|
||
@on_runtime_id_change | ||
def _update_runtime_id(runtime_id: str) -> None: | ||
crashtracker.set_runtime_id(runtime_id) | ||
def _get_tags(additional_tags: Optional[Dict[str, str]]) -> Dict[str, str]: | ||
tags = { | ||
"language": "python", | ||
"runtime": "CPython", | ||
"is_crash": "true", | ||
"severity": "crash", | ||
} | ||
|
||
# Here we check for the presence of each tags, as the underlying Metadata | ||
# object expects std::collections::HashMap<String, String> which doesn't | ||
# support None values. | ||
if config.env: | ||
tags["env"] = config.env | ||
if config.service: | ||
tags["service"] = config.service | ||
if config.version: | ||
tags["version"] = config.version | ||
runtime_id = get_runtime_id() | ||
if runtime_id: | ||
tags["runtime_id"] = runtime_id | ||
runtime_version = platform.python_version() | ||
if runtime_version: | ||
tags["runtime_version"] = runtime_version | ||
library_version = version.get_version() | ||
if library_version: | ||
tags["library_version"] = library_version | ||
|
||
def add_tag(key: str, value: str) -> None: | ||
if is_available: | ||
crashtracker.set_tag(key, value) | ||
for k, v in crashtracker_config.tags.items(): | ||
if k and v: | ||
tags[k] = v | ||
|
||
if additional_tags: | ||
for k, v in additional_tags.items(): | ||
if k and v: | ||
tags[k] = v | ||
|
||
def start() -> bool: | ||
if not is_available: | ||
return False | ||
if profiling_config.enabled: | ||
tags["profiler_config"] = config_str(profiling_config) | ||
|
||
import platform | ||
|
||
crashtracker.set_url(crashtracker_config.debug_url or agent_config.trace_agent_url) | ||
crashtracker.set_service(config.service) | ||
crashtracker.set_version(config.version) | ||
crashtracker.set_env(config.env) | ||
crashtracker.set_runtime_id(get_runtime_id()) | ||
crashtracker.set_runtime_version(platform.python_version()) | ||
crashtracker.set_library_version(version.get_version()) | ||
crashtracker.set_create_alt_stack(bool(crashtracker_config.create_alt_stack)) | ||
crashtracker.set_use_alt_stack(bool(crashtracker_config.use_alt_stack)) | ||
if crashtracker_config.stacktrace_resolver == "fast": | ||
crashtracker.set_resolve_frames_fast() | ||
elif crashtracker_config.stacktrace_resolver == "full": | ||
crashtracker.set_resolve_frames_full() | ||
# Another thing to note is that these tag keys and values can be bytes | ||
# objects, so we need to ensure that they are converted to strings as | ||
# PyO3 can't convert bytes objects to Rust String type. | ||
tags = {ensure_text(k): ensure_text(v) for k, v in tags.items()} | ||
|
||
return tags | ||
|
||
|
||
def _get_args(additional_tags: Optional[Dict[str, str]]): | ||
dd_crashtracker_receiver = shutil.which("dd_crashtracker_receiver") | ||
if dd_crashtracker_receiver is None: | ||
print("Failed to find dd_crashtracker_receiver") | ||
return (None, None, None) | ||
|
||
if crashtracker_config.stacktrace_resolver is None: | ||
stacktrace_resolver = StacktraceCollection.Disabled | ||
elif crashtracker_config.stacktrace_resolver == "fast": | ||
stacktrace_resolver = StacktraceCollection.WithoutSymbols | ||
elif crashtracker_config.stacktrace_resolver == "safe": | ||
crashtracker.set_resolve_frames_safe() | ||
stacktrace_resolver = StacktraceCollection.EnabledWithSymbolsInReceiver | ||
elif crashtracker_config.stacktrace_resolver == "full": | ||
stacktrace_resolver = StacktraceCollection.EnabledWithInprocessSymbols | ||
else: | ||
crashtracker.set_resolve_frames_disable() | ||
# This should never happen, as the value is validated in the crashtracker_config | ||
# module. | ||
print(f"Invalid stacktrace_resolver value: {crashtracker_config.stacktrace_resolver}") | ||
stacktrace_resolver = StacktraceCollection.EnabledWithInprocessSymbols | ||
|
||
if crashtracker_config.stdout_filename: | ||
crashtracker.set_stdout_filename(crashtracker_config.stdout_filename) | ||
if crashtracker_config.stderr_filename: | ||
crashtracker.set_stderr_filename(crashtracker_config.stderr_filename) | ||
# Create crashtracker configuration | ||
config = CrashtrackerConfiguration( | ||
[], # additional_files | ||
crashtracker_config.create_alt_stack, | ||
crashtracker_config.use_alt_stack, | ||
5000, # timeout_ms | ||
stacktrace_resolver, | ||
crashtracker_config.debug_url or agent_config.trace_agent_url, | ||
None, # unix_socket_path | ||
) | ||
|
||
# Add user tags | ||
for key, value in crashtracker_config.tags.items(): | ||
add_tag(key, value) | ||
# Create crashtracker receiver configuration | ||
receiver_config = CrashtrackerReceiverConfig( | ||
[], # args | ||
{}, # env | ||
dd_crashtracker_receiver, # path_to_receiver_binary | ||
crashtracker_config.stderr_filename, | ||
crashtracker_config.stdout_filename, | ||
) | ||
|
||
tags = _get_tags(additional_tags) | ||
|
||
metadata = CrashtrackerMetadata("dd-trace-py", version.get_version(), "python", tags) | ||
|
||
return config, receiver_config, metadata | ||
|
||
if profiling_config.enabled: | ||
add_tag("profiler_config", config_str(profiling_config)) | ||
|
||
# Only start if it is enabled | ||
if crashtracker_config.enabled: | ||
return crashtracker.start() | ||
return False | ||
def is_started() -> bool: | ||
if not is_available: | ||
return False | ||
return crashtracker_status() == CrashtrackerStatus.Initialized | ||
|
||
|
||
def start(additional_tags: Optional[Dict[str, str]] = None) -> bool: | ||
if not is_available: | ||
return False | ||
if not crashtracker_config.enabled: | ||
return False | ||
|
||
try: | ||
config, receiver_config, metadata = _get_args(additional_tags) | ||
taegyunkim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if config is None or receiver_config is None or metadata is None: | ||
print("Failed to start crashtracker: failed to construct crashtracker configuration") | ||
return False | ||
|
||
crashtracker_init(config, receiver_config, metadata) | ||
|
||
def crashtracker_fork_handler(): | ||
# We recreate the args here mainly to pass updated runtime_id after | ||
# fork | ||
config, receiver_config, metadata = _get_args(additional_tags) | ||
if config is None or receiver_config is None or metadata is None: | ||
print("Failed to restart crashtracker after fork: failed to construct crashtracker configuration") | ||
return | ||
crashtracker_on_fork(config, receiver_config, metadata) | ||
|
||
forksafe.register(crashtracker_fork_handler) | ||
except Exception as e: | ||
print(f"Failed to start crashtracker: {e}") | ||
return False | ||
return True |
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
116 changes: 0 additions & 116 deletions
116
ddtrace/internal/datadog/profiling/crashtracker/CMakeLists.txt
This file was deleted.
Oops, something went wrong.
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.