Skip to content

Commit bc09cd5

Browse files
committed
Only send frame and construct JSON array in receiver
1 parent ce6a239 commit bc09cd5

File tree

3 files changed

+16
-48
lines changed

3 files changed

+16
-48
lines changed

datadog-crashtracker/src/collector/emitters.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,7 @@ fn emit_runtime_stack_by_frames(w: &mut impl Write) -> Result<(), EmitterError>
253253
writeln!(w, "{DD_CRASHTRACK_BEGIN_RUNTIME_STACK_FRAME}")?;
254254

255255
// JSON array for frames
256-
write!(w, "[")?;
257256
unsafe { invoke_runtime_callback_with_writer(w)? };
258-
write!(w, "]")?;
259-
260-
writeln!(w)?;
261257
writeln!(w, "{DD_CRASHTRACK_END_RUNTIME_STACK_FRAME}")?;
262258
w.flush()?;
263259
Ok(())
@@ -268,7 +264,6 @@ fn emit_runtime_stack_by_stacktrace_string(w: &mut impl Write) -> Result<(), Emi
268264

269265
// Emit the stacktrace string
270266
unsafe { invoke_runtime_callback_with_writer(w)? };
271-
272267
writeln!(w, "{DD_CRASHTRACK_END_RUNTIME_STACK_STRING}")?;
273268
w.flush()?;
274269
Ok(())

datadog-crashtracker/src/receiver/receive_report.rs

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub(crate) enum StdinState {
5757
Waiting,
5858
// StackFrame is always emitted as one stream of all the frames but StackString
5959
// may have lines that we need to accumulate depending on runtime (e.g. Python)
60-
RuntimeStackFrame,
60+
RuntimeStackFrame(Vec<RuntimeFrame>),
6161
RuntimeStackString(Vec<String>),
6262
}
6363

@@ -135,41 +135,29 @@ fn process_line(
135135
builder.with_proc_info(proc_info)?;
136136
StdinState::ProcInfo
137137
}
138-
StdinState::RuntimeStackFrame
138+
StdinState::RuntimeStackFrame(frames)
139139
if line.starts_with(DD_CRASHTRACK_END_RUNTIME_STACK_FRAME) =>
140140
{
141+
let runtime_stack = RuntimeStack {
142+
format: "Datadog Runtime Callback 1.0".to_string(),
143+
frames,
144+
stacktrace_string: None,
145+
};
146+
builder.with_experimental_runtime_stack(runtime_stack)?;
141147
StdinState::Waiting
142148
}
143-
StdinState::RuntimeStackFrame => {
144-
// Try to parse as frames array
145-
if let Ok(runtime_frames) = serde_json::from_str::<Vec<RuntimeFrame>>(line) {
146-
if !runtime_frames.is_empty() {
147-
let runtime_stack = RuntimeStack {
148-
format: "Datadog Runtime Callback 1.0".to_string(),
149-
frames: runtime_frames,
150-
stacktrace_string: None,
151-
};
152-
builder.with_experimental_runtime_stack(runtime_stack)?;
153-
}
154-
} else {
155-
builder.with_log_message(
156-
format!("Unable to parse runtime stack frames: {line}"),
157-
true,
158-
)?;
159-
}
160-
StdinState::RuntimeStackFrame
149+
StdinState::RuntimeStackFrame(mut frames) => {
150+
let frame = serde_json::from_str(line)?;
151+
frames.push(frame);
152+
StdinState::RuntimeStackFrame(frames)
161153
}
162154
StdinState::RuntimeStackString(lines)
163155
if line.starts_with(DD_CRASHTRACK_END_RUNTIME_STACK_STRING) =>
164156
{
165-
// Join all accumulated lines with newlines to reconstruct the full stack trace
166-
// This is necessary because although the stacktrace string is sent as a single string,
167-
// there may be newlines in the string
168-
let stacktrace_string = lines.join("\n");
169157
let runtime_stack = RuntimeStack {
170158
format: "Datadog Runtime Callback 1.0".to_string(),
171159
frames: vec![],
172-
stacktrace_string: Some(stacktrace_string),
160+
stacktrace_string: Some(lines.join("\n")),
173161
};
174162
builder.with_experimental_runtime_stack(runtime_stack)?;
175163
StdinState::Waiting
@@ -254,7 +242,7 @@ fn process_line(
254242
StdinState::RuntimeStackString(vec![])
255243
}
256244
StdinState::Waiting if line.starts_with(DD_CRASHTRACK_BEGIN_RUNTIME_STACK_FRAME) => {
257-
StdinState::RuntimeStackFrame
245+
StdinState::RuntimeStackFrame(vec![])
258246
}
259247
StdinState::Waiting if line.starts_with(DD_CRASHTRACK_BEGIN_TRACE_IDS) => {
260248
StdinState::TraceIds

datadog-crashtracker/src/runtime_callback.rs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -259,18 +259,13 @@ pub(crate) unsafe fn invoke_runtime_callback_with_writer<W: std::io::Write>(
259259
// the vtable for its impls, so we need to store both.
260260
static CURRENT_WRITER_DATA: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
261261
static CURRENT_WRITER_VTABLE: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
262-
static CURRENT_FRAME_COUNT: AtomicPtr<usize> = AtomicPtr::new(ptr::null_mut());
263-
264-
let mut frame_count = 0usize;
265262

266263
let writer_trait_obj: *mut dyn std::io::Write = writer;
267264
let writer_parts: (*mut (), *mut ()) = unsafe { std::mem::transmute(writer_trait_obj) };
268-
let frame_count_ptr = &mut frame_count as *mut usize;
269265

270266
// Store components atomically
271267
CURRENT_WRITER_DATA.store(writer_parts.0, Ordering::SeqCst);
272268
CURRENT_WRITER_VTABLE.store(writer_parts.1, Ordering::SeqCst);
273-
CURRENT_FRAME_COUNT.store(frame_count_ptr, Ordering::SeqCst);
274269

275270
// Define the emit functions that read from the atomic storage
276271
unsafe extern "C" fn emit_frame_collector(frame: *const RuntimeStackFrame) {
@@ -280,28 +275,19 @@ pub(crate) unsafe fn invoke_runtime_callback_with_writer<W: std::io::Write>(
280275

281276
let writer_data = CURRENT_WRITER_DATA.load(Ordering::SeqCst);
282277
let writer_vtable = CURRENT_WRITER_VTABLE.load(Ordering::SeqCst);
283-
let frame_count_ptr = CURRENT_FRAME_COUNT.load(Ordering::SeqCst);
284278

285-
if writer_data.is_null() || writer_vtable.is_null() || frame_count_ptr.is_null() {
279+
if writer_data.is_null() || writer_vtable.is_null() {
286280
return;
287281
}
288282

289283
// Reconstruct fat pointer
290284
let writer_trait_obj: *mut dyn std::io::Write =
291285
std::mem::transmute((writer_data, writer_vtable));
292286
let writer = &mut *writer_trait_obj;
293-
let frame_count = &mut *frame_count_ptr;
294-
295-
// Add comma separator for frames after the first
296-
if *frame_count > 0 {
297-
let _ = write!(writer, ", ");
298-
}
299287

300288
// Write the frame as JSON
301289
let _ = emit_frame_as_json(writer, frame);
302290
let _ = writer.flush();
303-
304-
*frame_count += 1;
305291
}
306292

307293
unsafe extern "C" fn emit_stacktrace_string_collector(stacktrace_string: *const c_char) {
@@ -339,7 +325,6 @@ pub(crate) unsafe fn invoke_runtime_callback_with_writer<W: std::io::Write>(
339325
// Clear atomic storage
340326
CURRENT_WRITER_DATA.store(ptr::null_mut(), Ordering::SeqCst);
341327
CURRENT_WRITER_VTABLE.store(ptr::null_mut(), Ordering::SeqCst);
342-
CURRENT_FRAME_COUNT.store(ptr::null_mut(), Ordering::SeqCst);
343328

344329
Ok(())
345330
}
@@ -411,7 +396,7 @@ unsafe fn emit_frame_as_json(
411396
write!(writer, "\"column\": {}", frame_ref.column_number)?;
412397
}
413398

414-
write!(writer, "}}")?;
399+
writeln!(writer, "}}")?;
415400
Ok(())
416401
}
417402

0 commit comments

Comments
 (0)