Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions datadog-sidecar-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,52 @@ pub unsafe extern "C" fn ddog_sidecar_send_trace_v04_bytes(
MaybeError::None
}

/// Sends a v0.4-encoded trace to the sidecar via shared memory; the sidecar will re-encode
/// it as a V1 msgpack payload before forwarding to the agent.
#[no_mangle]
#[allow(clippy::missing_safety_doc)]
pub unsafe extern "C" fn ddog_sidecar_send_trace_v1_shm(
transport: &mut Box<SidecarTransport>,
instance_id: &InstanceId,
shm_handle: Box<ShmHandle>,
len: usize,
tracer_header_tags: &TracerHeaderTags,
) -> MaybeError {
let tracer_header_tags = try_c!(tracer_header_tags.try_into());

try_c!(blocking::send_trace_v1_shm(
transport,
instance_id,
*shm_handle,
len,
tracer_header_tags,
));

MaybeError::None
}

/// Sends a v0.4-encoded trace as bytes to the sidecar; the sidecar will re-encode it as a
/// V1 msgpack payload before forwarding to the agent.
#[no_mangle]
#[allow(clippy::missing_safety_doc)]
pub unsafe extern "C" fn ddog_sidecar_send_trace_v1_bytes(
transport: &mut Box<SidecarTransport>,
instance_id: &InstanceId,
data: ffi::CharSlice,
tracer_header_tags: &TracerHeaderTags,
) -> MaybeError {
let tracer_header_tags = try_c!(tracer_header_tags.try_into());

try_c!(blocking::send_trace_v1_bytes(
transport,
instance_id,
data.as_bytes().to_vec(),
tracer_header_tags,
));

MaybeError::None
}

#[no_mangle]
#[allow(clippy::missing_safety_doc)]
#[allow(improper_ctypes_definitions)] // DebuggerPayload is just a pointer, we hide its internals
Expand Down
24 changes: 24 additions & 0 deletions datadog-sidecar/src/service/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,30 @@ pub fn send_trace_v04_shm(
Ok(())
}

/// Sends a v0.4-encoded trace as bytes; the sidecar re-encodes it as V1 before forwarding.
pub fn send_trace_v1_bytes(
transport: &mut SidecarTransport,
instance_id: &InstanceId,
data: Vec<u8>,
headers: SerializedTracerHeaderTags,
) -> io::Result<()> {
lock_sender(transport)?.send_trace_v1_bytes(instance_id.clone(), data, headers);
Ok(())
}

/// Sends a v0.4-encoded trace via shared memory; the sidecar re-encodes it as V1 before
/// forwarding.
pub fn send_trace_v1_shm(
transport: &mut SidecarTransport,
instance_id: &InstanceId,
handle: ShmHandle,
len: usize,
headers: SerializedTracerHeaderTags,
) -> io::Result<()> {
lock_sender(transport)?.send_trace_v1_shm(instance_id.clone(), handle, len, headers);
Ok(())
}

/// Sends raw data from shared memory to the debugger endpoint.
pub fn send_debugger_data_shm(
transport: &mut SidecarTransport,
Expand Down
27 changes: 27 additions & 0 deletions datadog-sidecar/src/service/sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,33 @@ impl SidecarSender {
.try_send_send_trace_v04_bytes(instance_id, data, headers);
}

pub fn send_trace_v1_shm(
&mut self,
instance_id: InstanceId,
handle: ShmHandle,
len: usize,
headers: SerializedTracerHeaderTags,
) {
if !self.try_drain_outbox() {
return;
}
self.channel
.try_send_send_trace_v1_shm(instance_id, handle, len, headers);
}

pub fn send_trace_v1_bytes(
&mut self,
instance_id: InstanceId,
data: Vec<u8>,
headers: SerializedTracerHeaderTags,
) {
if !self.try_drain_outbox() {
return;
}
self.channel
.try_send_send_trace_v1_bytes(instance_id, data, headers);
}

pub fn send_debugger_data_shm(
&mut self,
instance_id: InstanceId,
Expand Down
32 changes: 32 additions & 0 deletions datadog-sidecar/src/service/sidecar_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,38 @@ pub trait SidecarInterface {
headers: SerializedTracerHeaderTags,
);

/// Sends a v0.4-encoded trace via shared memory; the sidecar re-encodes it as a V1
/// msgpack payload before forwarding to the agent. Use this when the upstream SDK only
/// speaks v0.4 but the agent advertises `/v1.0/traces`.
///
/// # Arguments
///
/// * `instance_id` - The ID of the instance.
/// * `handle` - The handle to the shared memory.
/// * `len` - The size of the shared memory data.
/// * `headers` - The serialized headers from the tracer.
async fn send_trace_v1_shm(
instance_id: InstanceId,
#[SerializedHandle] handle: ShmHandle,
len: usize,
headers: SerializedTracerHeaderTags,
);

/// Sends a v0.4-encoded trace as bytes; the sidecar re-encodes it as a V1 msgpack payload
/// before forwarding to the agent. Use this when the upstream SDK only speaks v0.4 but
/// the agent advertises `/v1.0/traces`.
///
/// # Arguments
///
/// * `instance_id` - The ID of the instance.
/// * `data` - The v0.4 trace data serialized as bytes.
/// * `headers` - The serialized headers from the tracer.
async fn send_trace_v1_bytes(
instance_id: InstanceId,
data: Vec<u8>,
headers: SerializedTracerHeaderTags,
);

/// Transfers raw data to a live-debugger endpoint.
///
/// # Arguments
Expand Down
83 changes: 82 additions & 1 deletion datadog-sidecar/src/service/sidecar_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,30 @@ impl SidecarServer {
data: tinybytes::Bytes,
target: &Endpoint,
retry_interval: u64,
) {
self.send_trace(headers, data, target, retry_interval, TraceEncoding::V04)
}

/// Re-encode entry point for the V1 path. Input bytes are still v0.4 msgpack from the SDK;
/// the [`TraceEncoding::V1`] tag tells [`SendData`] to encode the wire payload as V1 before
/// forwarding to the agent.
fn send_trace_v1(
&self,
headers: &SerializedTracerHeaderTags,
data: tinybytes::Bytes,
target: &Endpoint,
retry_interval: u64,
) {
self.send_trace(headers, data, target, retry_interval, TraceEncoding::V1)
}

fn send_trace(
&self,
headers: &SerializedTracerHeaderTags,
data: tinybytes::Bytes,
target: &Endpoint,
retry_interval: u64,
encoding: TraceEncoding,
) {
let headers: TracerHeaderTags = match headers.try_into() {
Ok(headers) => headers,
Expand All @@ -265,7 +289,7 @@ impl SidecarServer {
headers
);

match decode_to_trace_chunks(data, TraceEncoding::V04) {
match decode_to_trace_chunks(data, encoding) {
Ok((payload, size)) => {
trace!("Parsed the trace payload and enqueuing it for sending: {payload:?}");
let mut data = SendData::new(
Expand Down Expand Up @@ -898,6 +922,63 @@ impl SidecarInterface for ConnectionSidecarHandler {
}
}

async fn send_trace_v1_shm(
&self,
_peer: PeerCredentials,
instance_id: InstanceId,
handle: ShmHandle,
_len: usize,
headers: SerializedTracerHeaderTags,
) {
self.track_instance(&instance_id);
let session = self.server.get_session(&instance_id.session_id);
let trace_config = session.get_trace_config();
if let Some(endpoint) = trace_config.endpoint.clone() {
let server = self.server.clone();
let retry_interval = trace_config.retry_interval;
tokio::spawn(async move {
match handle.map() {
Ok(mapped) => {
let bytes = tinybytes::Bytes::from(mapped);
server.send_trace_v1(&headers, bytes, &endpoint, retry_interval);
}
Err(e) => error!("Failed mapping shared trace data memory: {}", e),
}
});
} else {
warn!(
"Received trace data ({handle:?}) for missing session {}",
instance_id.session_id
);
}
}

async fn send_trace_v1_bytes(
&self,
_peer: PeerCredentials,
instance_id: InstanceId,
data: Vec<u8>,
headers: SerializedTracerHeaderTags,
) {
self.track_instance(&instance_id);
let session = self.server.get_session(&instance_id.session_id);
let trace_config = session.get_trace_config();

if let Some(endpoint) = trace_config.endpoint.clone() {
let server = self.server.clone();
let retry_interval = trace_config.retry_interval;
tokio::spawn(async move {
let bytes = tinybytes::Bytes::from(data);
server.send_trace_v1(&headers, bytes, &endpoint, retry_interval);
});
} else {
warn!(
"Received trace data for missing session {}",
instance_id.session_id
);
}
}

async fn send_debugger_data_shm(
&self,
_peer: PeerCredentials,
Expand Down
8 changes: 3 additions & 5 deletions libdd-data-pipeline/src/trace_exporter/trace_serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use libdd_trace_utils::msgpack_encoder;
use libdd_trace_utils::span::{v04::Span, TraceData};
use libdd_trace_utils::trace_utils::{self, TracerHeaderTags};
use libdd_trace_utils::tracer_metadata::TracerMetadata;
use libdd_trace_utils::tracer_payload::{self, TraceEncoding};
use libdd_trace_utils::tracer_payload::{self};

/// Minimal capacity of fresh buffers allocated to encode traces, in bytes.
const MIN_BUFFER_CAPACITY: usize = 1024;
Expand Down Expand Up @@ -79,11 +79,9 @@ impl TraceSerializer {
};
match output_format {
TraceExporterOutputFormat::V1 => Ok(tracer_payload::TraceChunks::V1(traces)),
TraceExporterOutputFormat::V04 => {
trace_utils::collect_trace_chunks(traces, TraceEncoding::V04).map_err(map_err)
}
TraceExporterOutputFormat::V04 => Ok(tracer_payload::TraceChunks::V04(traces)),
TraceExporterOutputFormat::V05 => {
trace_utils::collect_trace_chunks(traces, TraceEncoding::V05).map_err(map_err)
trace_utils::convert_trace_chunks_v04_to_v05(traces).map_err(map_err)
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions libdd-trace-utils/src/send_data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,29 @@ impl SendData {
endpoint.as_ref(),
));
}
// TracerPayloadCollection::V1(payload) => {
// // V0.4-shaped spans re-encoded as a V1 msgpack payload at send time. Used by
// // the sidecar when the upstream SDK only speaks v0.4 but the agent advertises
// // `/v1.0/traces`. `extract_payload_attrs` will pull env/hostname/app_version
// // from span meta tags since the SDK propagates them there for v0.4 payloads.
// #[allow(clippy::unwrap_used)]
// let chunks = u64::try_from(self.tracer_payloads.size()).unwrap();
// let mut headers = self.headers.clone();
// headers.reserve(2);
// headers.insert(DATADOG_TRACE_COUNT, chunks.into());
// headers.insert(CONTENT_TYPE, APPLICATION_MSGPACK);

// let metadata = crate::tracer_metadata::TracerMetadata::default();
// let payload = msgpack_encoder::v1::to_vec_from_payload_v1(payload);

// futures.push(self.send_payload(
// capabilities,
// chunks,
// payload,
// headers,
// endpoint.as_ref(),
// ));
// }
TracerPayloadCollection::V05(payload) => {
#[allow(clippy::unwrap_used)]
let chunks = u64::try_from(self.tracer_payloads.size()).unwrap();
Expand Down Expand Up @@ -537,6 +560,10 @@ mod tests {
msgpack_encoder::v04::to_encoded_byte_len(payloads) as usize
}
TracerPayloadCollection::V05(payloads) => rmp_serde::to_vec(payloads).unwrap().len(),
// TracerPayloadCollection::V1(payloads) => {
// let metadata = crate::tracer_metadata::TracerMetadata::default();
// msgpack_encoder::v1::to_encoded_byte_len(payloads, &metadata) as usize
// }
}
}

Expand Down
Loading
Loading