mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
242 lines
9.3 KiB
Python
242 lines
9.3 KiB
Python
from symbolic.exceptions import SymbolicError
|
|
|
|
from sentry.utils.rust import merge_rust_info_frames, starts_with, strip_symbol
|
|
|
|
STACKTRACE = """
|
|
stacktrace: stack backtrace:
|
|
0: 0x111e51cf4 - backtrace::backtrace::trace::h38e3b1de9f341e04
|
|
at /.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.9/src/backtrace/mod.rs:42
|
|
1: 0x111e4a3be - failure::backtrace::Backtrace::new::h2abf3908d09948f1
|
|
at /.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/backtrace/mod.rs:111
|
|
2: 0x11163e27c - <failure::error::Error as core::convert::From<F>>::from::h5ae4b38f39150cb2
|
|
at /.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.3/src/error/mod.rs:36
|
|
- <T as core::convert::Into<U>>::into::h58e05f056150874e
|
|
at libcore/convert.rs:456
|
|
3: 0x11163a9b7 - symbolic::debuginfo::symbolic_normalize_debug_id::{{closure}}::he767b4111eb41a33
|
|
at /symbolic/cabi/src/debuginfo.rs:160
|
|
4: 0x111e7f5de - ___rust_maybe_catch_panic
|
|
at /rustc/da5f414c2c0bfe5198934493f04c676e2b23ff2e/src/libpanic_unwind/lib.rs:103
|
|
5: 0x111618fcb - std::panic::catch_unwind::h66eea40447da0e66
|
|
at /symbolic/cabi/libstd/panic.rs:392
|
|
6: 0x11160b9c1 - symbolic::utils::landingpad::h3cd528225184a301
|
|
at /symbolic/cabi/src/utils.rs:55
|
|
7: 0x111632f43 - _symbolic_normalize_debug_id
|
|
at /symbolic/cabi/src/utils.rs:74
|
|
8: 0x7fff69609f6b - _ffi_call_unix64
|
|
9: 0x7fff6960a786 - _ffi_call
|
|
10: 0x10fab19d6 - _cdata_call
|
|
11: 0x10efc014f - _PyObject_Call
|
|
12: 0x10f069f43 - _Py_Main
|
|
"""
|
|
|
|
STACKTRACE_SEMAPHORE_LINUX = """
|
|
stacktrace: stack backtrace:
|
|
0: failure::backtrace::internal::InternalBacktrace::new::hc23de41c89e8c745 (0x7f2d0af481ba)
|
|
at /home/parallels/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.5/src/backtrace/internal.rs:44
|
|
1: <T as core::convert::Into<U>>::into::hd4b72738b7e18e92 (0x7f2d0b070e3a)
|
|
at /home/parallels/.cargo/registry/src/github.com-1ecc6299db9ec823/failure-0.1.5/src/backtrace/mod.rs:111
|
|
semaphore::utils::set_panic_hook::{{closure}}::hacec55cb6b285e6a
|
|
at src/utils.rs:45
|
|
2: std::panicking::rust_panic_with_hook::h3c82d7c1012a629a (0x7f2d0b3d6fb6)
|
|
at src/libstd/panicking.rs:477
|
|
3: std::panicking::begin_panic::h3db9895361250d80 (0x7f2d0b06ba94)
|
|
at /rustc/224f0bc90c010b88ca6ec600c9b02f6e3638d78e/src/libstd/panicking.rs:407
|
|
4: semaphore::processing::semaphore_test_panic::{{closure}}::hb800a646d3f454a4 (0x7f2d0b06e999)
|
|
at src/processing.rs:119
|
|
5: std::panic::catch_unwind::hdc352a616e262d7e (0x7f2d0b03c59a)
|
|
at /rustc/224f0bc90c010b88ca6ec600c9b02f6e3638d78e/src/libstd/panicking.rs:292
|
|
semaphore_test_panic
|
|
at src/utils.rs:53
|
|
6: ffi_call_unix64 (0x7f2d0b839df0)
|
|
7: ffi_call (0x7f2d0b839858)
|
|
at ../src/x86/ffi64.c:525
|
|
8: cdata_call (0x7f2d0ba57d64)
|
|
at c/_cffi_backend.c:3025
|
|
9: PyObject_Call (0x459eee)
|
|
10: _PyEval_EvalFrameDefault (0x552c49)
|
|
11: <unknown> (0x54fbe1)
|
|
12: <unknown> (0x54fe6d)
|
|
13: _PyEval_EvalFrameDefault (0x5546cf)
|
|
14: <unknown> (0x54f0e8)
|
|
15: <unknown> (0x550116)
|
|
16: _PyEval_EvalFrameDefault (0x5546cf)
|
|
17: <unknown> (0x54fbe1)
|
|
18: PyEval_EvalCode (0x550b93)
|
|
19: <unknown> (0x42ca41)
|
|
20: PyRun_InteractiveLoopFlags (0x42ccb6)
|
|
21: PyRun_AnyFileExFlags (0x42ce5c)
|
|
22: Py_Main (0x442143)
|
|
23: main (0x421ff4)
|
|
24: __libc_start_main (0x7f2d0e8beb97)
|
|
25: _start (0x4220aa)
|
|
26: <unknown> (0x0)
|
|
"""
|
|
|
|
|
|
def get_event(stacktrace):
|
|
return {
|
|
"event_id": "fe628bfa48064c9b97ce7e75a19e6197",
|
|
"level": "error",
|
|
"platform": "python",
|
|
"logentry": {"formatted": "invalid debug identifier\n\n%s" % stacktrace},
|
|
"exception": {
|
|
"values": [
|
|
{
|
|
"type": "ParseDebugIdError",
|
|
"value": "invalid debug identifier\n\n%s" % stacktrace,
|
|
"stacktrace": {
|
|
"frames": [
|
|
{
|
|
"abs_path": "/symbolic/py/symbolic/utils.py",
|
|
"filename": "symbolic/utils.py",
|
|
"function": "rustcall",
|
|
"in_app": True,
|
|
"lineno": 93,
|
|
"module": "symbolic.utils",
|
|
}
|
|
]
|
|
},
|
|
}
|
|
]
|
|
},
|
|
}
|
|
|
|
|
|
def get_exc_info(rust_info):
|
|
exc = SymbolicError("hello world")
|
|
if rust_info is not None:
|
|
exc.rust_info = rust_info
|
|
return type(exc), exc, None
|
|
|
|
|
|
def test_merge_rust_info():
|
|
event = get_event(STACKTRACE)
|
|
exc_info = get_exc_info(STACKTRACE)
|
|
|
|
merge_rust_info_frames(event, {"exc_info": exc_info})
|
|
|
|
assert event["platform"] == "native"
|
|
assert event["logentry"]["formatted"] == "invalid debug identifier"
|
|
|
|
exception = event["exception"]["values"][0]
|
|
assert exception["value"] == "invalid debug identifier"
|
|
|
|
frames = exception["stacktrace"]["frames"]
|
|
assert len(frames) == 8
|
|
assert frames[0]["platform"] == "python"
|
|
|
|
# Top frame
|
|
assert frames[7]["instruction_addr"] == "0x11163e27c"
|
|
assert frames[7]["function"] == "<failure::error::Error as core::convert::From<F>>::from"
|
|
assert frames[7]["package"] == "failure"
|
|
assert frames[7]["in_app"] is False
|
|
assert frames[7]["filename"] == "mod.rs"
|
|
assert frames[7]["lineno"] == 36
|
|
|
|
# Inlined frame, same address
|
|
assert frames[7]["instruction_addr"] == "0x11163e27c"
|
|
assert frames[6]["function"] == "<T as core::convert::Into<U>>::into"
|
|
assert frames[6]["package"] == "core"
|
|
assert frames[6]["in_app"] is False
|
|
assert frames[6]["filename"] == "convert.rs"
|
|
assert frames[6]["lineno"] == 456
|
|
|
|
|
|
def test_merge_rust_info_linux():
|
|
event = get_event(STACKTRACE_SEMAPHORE_LINUX)
|
|
exc_info = get_exc_info(STACKTRACE_SEMAPHORE_LINUX)
|
|
|
|
merge_rust_info_frames(event, {"exc_info": exc_info})
|
|
|
|
assert event["platform"] == "native"
|
|
assert event["logentry"]["formatted"] == "invalid debug identifier"
|
|
|
|
exception = event["exception"]["values"][0]
|
|
assert exception["value"] == "invalid debug identifier"
|
|
|
|
frames = exception["stacktrace"]["frames"]
|
|
assert len(frames) == 4
|
|
assert frames[0]["platform"] == "python"
|
|
|
|
# Top frame
|
|
assert frames[-1]["instruction_addr"] == "0x7f2d0b06e999"
|
|
assert frames[-1]["function"] == "semaphore::processing::semaphore_test_panic::{{closure}}"
|
|
|
|
# Inlined frame, same address
|
|
assert frames[-2]["instruction_addr"] == "0x7f2d0b03c59a"
|
|
assert frames[-2]["function"] == "std::panic::catch_unwind"
|
|
|
|
|
|
def test_without_exc_info():
|
|
event = get_event(STACKTRACE)
|
|
merge_rust_info_frames(event, {})
|
|
assert event["platform"] == "python"
|
|
|
|
|
|
def test_without_rust_info():
|
|
event = get_event(STACKTRACE)
|
|
exc_info = get_exc_info(None)
|
|
|
|
merge_rust_info_frames(event, {"exc_info": exc_info})
|
|
assert event["platform"] == "python"
|
|
|
|
|
|
def test_without_stacktrace():
|
|
stacktrace = "stacktrace: stack backtrace:\n\n"
|
|
event = get_event(stacktrace)
|
|
exc_info = get_exc_info(stacktrace)
|
|
|
|
merge_rust_info_frames(event, {"exc_info": exc_info})
|
|
|
|
assert event["platform"] == "native"
|
|
assert event["logentry"]["formatted"] == "invalid debug identifier"
|
|
|
|
exception = event["exception"]["values"][0]
|
|
assert exception["value"] == "invalid debug identifier"
|
|
|
|
frames = exception["stacktrace"]["frames"]
|
|
assert len(frames) == 1
|
|
|
|
|
|
def test_without_exception():
|
|
event = get_event(STACKTRACE)
|
|
exc_info = get_exc_info(STACKTRACE)
|
|
|
|
del event["exception"]
|
|
merge_rust_info_frames(event, {"exc_info": exc_info})
|
|
assert event["platform"] == "python"
|
|
|
|
|
|
def test_starts_with():
|
|
# Basic functions
|
|
assert starts_with("__rust_maybe_catch_panic", "__rust")
|
|
assert starts_with("futures::task_impl::std::set", "futures::")
|
|
assert not starts_with("futures::task_impl::std::set", "tokio::")
|
|
|
|
# Generics
|
|
assert starts_with("_<futures..task_impl..Spawn<T>>::enter::_{{closure}}", "futures::")
|
|
assert not starts_with("_<futures..task_impl..Spawn<T>>::enter::_{{closure}}", "tokio::")
|
|
assert starts_with("<futures::task_impl::Spawn<T>>::enter::{{closure}}", "futures::")
|
|
assert not starts_with("<futures::task_impl::Spawn<T>>::enter::{{closure}}", "tokio::")
|
|
|
|
# Trait implementations
|
|
assert starts_with("<failure::error::Error as core::convert::From<F>>::from", "failure::")
|
|
assert starts_with("_<failure::error::Error as core::convert::From<F>>::from", "failure::")
|
|
|
|
# Blanket implementations
|
|
assert starts_with("<T as core::convert::Into<U>>::into", "core::")
|
|
|
|
|
|
def test_strip_symbol():
|
|
assert strip_symbol("") == ""
|
|
assert strip_symbol("_ffi_call_unix64") == "_ffi_call_unix64"
|
|
assert (
|
|
strip_symbol("backtrace::backtrace::trace::h1c213d29ba950696")
|
|
== "backtrace::backtrace::trace"
|
|
)
|
|
assert (
|
|
strip_symbol("<T as core::convert::Into<U>>::into::h58e05f056150874e")
|
|
== "<T as core::convert::Into<U>>::into"
|
|
)
|
|
assert strip_symbol("symbolic_symcache_from_object") == "symbolic_symcache_from_object"
|