Skip to content

Commit 59ff734

Browse files
committed
For testing with test tracer in staging
1 parent 8baf78b commit 59ff734

File tree

8 files changed

+279
-333
lines changed

8 files changed

+279
-333
lines changed

src/native/Cargo.lock

Lines changed: 233 additions & 138 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/native/Cargo.toml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@ profiling = ["dep:datadog-profiling-ffi"]
1616

1717
[dependencies]
1818
anyhow = { version = "1.0", optional = true }
19-
datadog-crashtracker = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349", optional = true }
20-
datadog-ddsketch = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349" }
21-
datadog-library-config = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349" }
22-
datadog-log = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349" }
23-
data-pipeline = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349" }
24-
datadog-profiling-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349", optional = true, features = [
19+
datadog-crashtracker = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb", optional = true }
20+
libdd-ddsketch = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb" }
21+
libdd-library-config = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb" }
22+
libdd-log = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb" }
23+
data-pipeline = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb" }
24+
datadog-profiling-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb", optional = true, features = [
2525
"cbindgen",
2626
] }
27-
ddcommon = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349" }
27+
ddcommon = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb" }
28+
ddcommon-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb" }
29+
libc = "0.2.177"
2830
pyo3 = { version = "0.25", features = ["extension-module", "anyhow"] }
2931
tracing = { version = "0.1", default-features = false }
3032
pyo3-ffi = "0.25"
@@ -34,7 +36,7 @@ cc = "1.2.39"
3436
pyo3-build-config = "0.25"
3537
pyo3-ffi = "0.25"
3638
cc = "1.2.39"
37-
build_common = { git = "https://github.com/DataDog/libdatadog", rev = "538a7f1c236f9c70ab91de6230b716807c721349", features = [
39+
build_common = { git = "https://github.com/DataDog/libdatadog", rev = "bcfd16a5ba7709f3ad6e2591c948de08c65fe4cb", features = [
3840
"cbindgen",
3941
] }
4042

src/native/crashtracker.rs

Lines changed: 23 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::sync::Once;
77
use std::time::Duration;
88

99
use datadog_crashtracker::{
10-
is_runtime_callback_registered, register_runtime_stack_callback, CallbackError, CallbackType,
10+
is_runtime_callback_registered, register_runtime_frame_callback, register_runtime_stacktrace_string_callback, CallbackError,
1111
CrashtrackerConfiguration, CrashtrackerReceiverConfig, Metadata, RuntimeStackFrame,
1212
StacktraceCollection,
1313
};
@@ -322,66 +322,12 @@ pub fn crashtracker_receiver() -> anyhow::Result<()> {
322322
#[derive(Debug, PartialEq, Eq)]
323323
pub enum CallbackResult {
324324
Ok,
325-
NullCallback,
326-
UnknownError,
325+
Error,
327326
}
328327

329328
impl From<CallbackError> for CallbackResult {
330-
fn from(error: CallbackError) -> Self {
331-
match error {
332-
CallbackError::NullCallback => CallbackResult::NullCallback,
333-
}
334-
}
335-
}
336-
337-
/// Runtime-specific stack frame representation for FFI
338-
///
339-
/// This struct is used to pass runtime stack frame information from language
340-
/// runtimes to the crashtracker during crash handling.
341-
#[pyclass(name = "RuntimeStackFrame", module = "datadog.internal._native")]
342-
#[derive(Debug, Clone)]
343-
pub struct RuntimeStackFramePy {
344-
pub function_name: Option<String>,
345-
pub file_name: Option<String>,
346-
pub line_number: u32,
347-
pub column_number: u32,
348-
}
349-
350-
#[pymethods]
351-
impl RuntimeStackFramePy {
352-
#[new]
353-
fn new(
354-
function_name: Option<String>,
355-
file_name: Option<String>,
356-
line_number: u32,
357-
column_number: u32,
358-
) -> Self {
359-
Self {
360-
function_name,
361-
file_name,
362-
line_number,
363-
column_number,
364-
}
365-
}
366-
367-
#[getter]
368-
fn get_function_name(&self) -> Option<String> {
369-
self.function_name.clone()
370-
}
371-
372-
#[getter]
373-
fn get_file_name(&self) -> Option<String> {
374-
self.file_name.clone()
375-
}
376-
377-
#[getter]
378-
fn get_line_number(&self) -> u32 {
379-
self.line_number
380-
}
381-
382-
#[getter]
383-
fn get_column_number(&self) -> u32 {
384-
self.column_number
329+
fn from(_error: CallbackError) -> Self {
330+
CallbackResult::Error
385331
}
386332
}
387333

@@ -471,117 +417,6 @@ fn parse_traceback_line(
471417
0
472418
}
473419

474-
// Parse traceback text and emit frames
475-
unsafe fn parse_and_emit_traceback(
476-
traceback_text: &str,
477-
emit_frame: unsafe extern "C" fn(*const RuntimeStackFrame),
478-
) {
479-
let lines: Vec<&str> = traceback_text.lines().collect();
480-
let mut frame_count = 0;
481-
482-
for line in lines {
483-
if frame_count >= MAX_FRAMES {
484-
break;
485-
}
486-
487-
// Look for lines that start with " File " - these are stack frame lines
488-
if line.trim_start().starts_with("File ") {
489-
let mut function_buf = StackBuffer::new();
490-
let mut file_buf = StackBuffer::new();
491-
492-
let line_number = parse_traceback_line(line, &mut function_buf, &mut file_buf);
493-
494-
let c_frame = RuntimeStackFrame {
495-
function_name: function_buf.as_ptr(),
496-
file_name: file_buf.as_ptr(),
497-
line_number,
498-
column_number: 0,
499-
};
500-
501-
emit_frame(&c_frame);
502-
frame_count += 1;
503-
}
504-
}
505-
}
506-
507-
unsafe fn dump_python_traceback_via_cpython_api(
508-
emit_frame: unsafe extern "C" fn(*const RuntimeStackFrame),
509-
) {
510-
let mut pipefd: [c_int; 2] = [0, 0];
511-
if pipe(&mut pipefd as *mut [c_int; 2]) != 0 {
512-
emit_fallback_frame(emit_frame, "<pipe_creation_failed>");
513-
return;
514-
}
515-
516-
let read_fd = pipefd[0];
517-
let write_fd = pipefd[1];
518-
519-
// Make the read end non-blocking
520-
fcntl(read_fd, F_SETFL, O_NONBLOCK);
521-
522-
// Get the current thread state safely - same approach as CPython's faulthandler
523-
// SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and
524-
// are thus delivered to the thread that caused the fault.
525-
let current_tstate = crashtracker_get_current_tstate();
526-
527-
// Call the CPython internal API via our C wrapper
528-
// Pass NULL for interpreter state since _Py_DumpTracebackThreads handle it internally
529-
let error_msg = crashtracker_dump_traceback_threads(write_fd, ptr::null_mut(), current_tstate);
530-
531-
close(write_fd);
532-
533-
if !error_msg.is_null() {
534-
close(read_fd);
535-
let error_str = std::ffi::CStr::from_ptr(error_msg);
536-
if let Ok(error_string) = error_str.to_str() {
537-
emit_fallback_frame(emit_frame, error_string);
538-
} else {
539-
emit_fallback_frame(emit_frame, "<cpython_api_error>");
540-
}
541-
return;
542-
}
543-
544-
let mut buffer = vec![0u8; MAX_TRACEBACK_SIZE];
545-
let bytes_read = read(
546-
read_fd,
547-
buffer.as_mut_ptr() as *mut c_void,
548-
MAX_TRACEBACK_SIZE,
549-
);
550-
551-
close(read_fd);
552-
553-
if bytes_read > 0 {
554-
buffer.truncate(bytes_read as usize);
555-
if let Ok(traceback_text) = std::str::from_utf8(&buffer) {
556-
parse_and_emit_traceback(traceback_text, emit_frame);
557-
return;
558-
}
559-
}
560-
561-
// If we get here, something went wrong with reading the output
562-
emit_fallback_frame(emit_frame, "<traceback_read_failed>");
563-
}
564-
565-
// Helper function to emit a fallback frame with error information
566-
unsafe fn emit_fallback_frame(
567-
emit_frame: unsafe extern "C" fn(*const RuntimeStackFrame),
568-
error_msg: &str,
569-
) {
570-
let mut function_buf = StackBuffer::new();
571-
let mut file_buf = StackBuffer::new();
572-
function_buf.set_from_str(error_msg);
573-
file_buf.set_from_str("<crashtracker_fallback>");
574-
575-
let fallback_frame = RuntimeStackFrame {
576-
function_name: function_buf.as_ptr(),
577-
file_name: file_buf.as_ptr(),
578-
line_number: 0,
579-
column_number: 0,
580-
};
581-
582-
emit_frame(&fallback_frame);
583-
}
584-
585420
/// Dump Python traceback as a complete string
586421
///
587422
/// This function captures the Python traceback via CPython's internal API
@@ -645,30 +480,42 @@ unsafe fn dump_python_traceback_as_string(
645480
}
646481

647482
unsafe extern "C" fn native_runtime_stack_callback(
648-
_emit_frame: unsafe extern "C" fn(*const RuntimeStackFrame),
649483
emit_stacktrace_string: unsafe extern "C" fn(*const c_char),
650484
) {
651485
dump_python_traceback_as_string(emit_stacktrace_string);
652-
// dump_python_traceback_via_cpython_api(emit_frame);
653486
}
654487

655-
/// Register the native runtime stack collection callback
488+
/// Frame-based callback implementation for runtime stack collection
489+
///
490+
/// This callback collects Python stack frames individually and emits them
491+
/// one by one for detailed stack trace information.
492+
// unsafe extern "C" fn native_runtime_frame_callback(
493+
// emit_frame: unsafe extern "C" fn(*const RuntimeStackFrame),
494+
// ) {
495+
// dump_python_traceback_via_cpython_api(emit_frame);
496+
// }
497+
498+
/// Register the native runtime stack collection callback (string-based)
656499
///
657500
/// This function registers a native callback that directly collects Python runtime
658-
/// stack traces without requiring Python callback functions. It uses frame-by-frame
659-
/// collection for detailed stack information.
501+
/// stack traces as complete strings without requiring Python callback functions.
660502
///
661503
/// # Returns
662504
/// - `CallbackResult::Ok` if registration succeeds (replaces any existing callback)
663505
#[pyfunction(name = "crashtracker_register_native_runtime_callback")]
664506
pub fn crashtracker_register_native_runtime_callback() -> CallbackResult {
665-
match register_runtime_stack_callback(
507+
match register_runtime_stacktrace_string_callback(
666508
native_runtime_stack_callback,
667-
CallbackType::StacktraceString,
668509
) {
669510
Ok(()) => CallbackResult::Ok,
670511
Err(e) => e.into(),
671512
}
513+
// match register_runtime_frame_callback(
514+
// native_runtime_frame_callback,
515+
// ) {
516+
// Ok(()) => CallbackResult::Ok,
517+
// Err(e) => e.into(),
518+
// }
672519
}
673520

674521
/// Check if a runtime callback is currently registered

src/native/data_pipeline/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,14 @@ impl TraceExporterBuilderPy {
148148
heartbeat_ms: u64,
149149
runtime_id: String,
150150
) -> PyResult<Py<Self>> {
151-
slf.try_as_mut()?.enable_telemetry(Some(TelemetryConfig {
152-
heartbeat: heartbeat_ms,
153-
runtime_id: Some(runtime_id),
154-
debug_enabled: true,
155-
}));
151+
slf.try_as_mut()?.enable_telemetry(
152+
Some(TelemetryConfig {
153+
heartbeat: heartbeat_ms,
154+
runtime_id: Some(runtime_id),
155+
debug_enabled: true,
156+
})
157+
.unwrap(),
158+
);
156159
Ok(slf.into())
157160
}
158161

src/native/ddsketch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use pyo3::exceptions::PyValueError;
22
use pyo3::prelude::*;
33
use pyo3::types::PyBytes;
44

5-
use datadog_ddsketch::DDSketch;
5+
use libdd_ddsketch::DDSketch;
66

77
#[pyclass(name = "DDSketch", module = "ddtrace.internal._native")]
88
pub struct DDSketchPy {

src/native/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ fn _native(m: &Bound<'_, PyModule>) -> PyResult<()> {
2727
m.add_class::<crashtracker::CrashtrackerMetadataPy>()?;
2828
m.add_class::<crashtracker::CrashtrackerStatus>()?;
2929
m.add_class::<crashtracker::CallbackResult>()?;
30-
m.add_class::<crashtracker::RuntimeStackFramePy>()?;
3130
m.add_function(wrap_pyfunction!(crashtracker::crashtracker_init, m)?)?;
3231
m.add_function(wrap_pyfunction!(crashtracker::crashtracker_on_fork, m)?)?;
3332
m.add_function(wrap_pyfunction!(crashtracker::crashtracker_status, m)?)?;

src/native/library_config.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use datadog_library_config::{
1+
use libdd_library_config::{
22
tracer_metadata::{store_tracer_metadata, AnonymousFileHandle, TracerMetadata},
33
Configurator, ProcessInfo,
44
};
@@ -42,7 +42,7 @@ impl PyConfigurator {
4242
&ProcessInfo::detect_global("python".to_string()),
4343
);
4444
match res_config {
45-
datadog_library_config::LoggedResult::Ok(config, logs) => {
45+
libdd_library_config::LoggedResult::Ok(config, logs) => {
4646
// Previously, `libdatadog` printed debug logs to stderr. However,
4747
// in v21.0.0, we changed the behavior to buffer them and return
4848
// them in the logs returned by this `LoggedResult`.
@@ -60,7 +60,7 @@ impl PyConfigurator {
6060
}
6161
Ok(list.into())
6262
}
63-
datadog_library_config::LoggedResult::Err(e) => {
63+
libdd_library_config::LoggedResult::Err(e) => {
6464
let err_msg = format!("Failed to get configuration: {e:?}");
6565
Err(PyException::new_err(err_msg))
6666
}

src/native/log.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub mod logger {
66
use pyo3::types::PyDict;
77
use pyo3::{exceptions::PyValueError, PyResult};
88

9-
use datadog_log::logger::{
9+
use libdd_log::logger::{
1010
logger_configure_file, logger_configure_std, logger_disable_file, logger_disable_std,
1111
logger_set_log_level, FileConfig, LogEventLevel, StdConfig, StdTarget,
1212
};

0 commit comments

Comments
 (0)