Skip to content

Commit

Permalink
Merge branch 'main' into dsn/profiler-use-macros
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsn authored Dec 10, 2024
2 parents 1374f98 + 373b778 commit 6680602
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 64 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions data-pipeline-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ cbindgen = ["build_common/cbindgen", "ddcommon-ffi/cbindgen"]
[build-dependencies]
build_common = { path = "../build-common" }

[dev-dependencies]
httpmock = "0.7.0"
rmp-serde = "1.1.1"
datadog-trace-utils = { path = "../trace-utils" }

[dependencies]
data-pipeline = { path = "../data-pipeline" }
ddcommon-ffi = { path = "../ddcommon-ffi", default-features = false }
Expand Down
120 changes: 120 additions & 0 deletions data-pipeline-ffi/src/trace_exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ mod tests {
use super::*;
use crate::error::ddog_trace_exporter_error_free;
use crate::trace_exporter::AgentResponse;
use datadog_trace_utils::span_v04::Span;
use httpmock::prelude::*;
use httpmock::MockServer;
use std::{borrow::Borrow, mem::MaybeUninit};

#[test]
Expand Down Expand Up @@ -608,4 +611,121 @@ mod tests {
assert_eq!(error.unwrap().code, ErrorCode::InvalidInput);
}
}

#[test]
// Ignore because it seems, at least in the version we're currently using, miri can't emulate
// libc::socket function.
#[cfg_attr(miri, ignore)]
fn exporter_send_check_rate_test() {
unsafe {
let server = MockServer::start();

let _mock = server.mock(|when, then| {
when.method(POST)
.header("Content-type", "application/msgpack")
.path("/v0.4/traces");
then.status(200).body(
r#"{
"rate_by_service": {
"service:foo,env:staging": 1.0,
"service:,env:": 0.8
}
}"#,
);
});

let cfg = TraceExporterConfig {
url: Some(server.url("/")),
tracer_version: Some("0.1".to_string()),
language: Some("lang".to_string()),
language_version: Some("0.1".to_string()),
language_interpreter: Some("interpreter".to_string()),
hostname: Some("hostname".to_string()),
env: Some("env-test".to_string()),
version: Some("1.0".to_string()),
service: Some("test-service".to_string()),
input_format: TraceExporterInputFormat::V04,
output_format: TraceExporterOutputFormat::V04,
compute_stats: false,
};

let mut ptr: MaybeUninit<Box<TraceExporter>> = MaybeUninit::uninit();
let mut ret =
ddog_trace_exporter_new(NonNull::new_unchecked(&mut ptr).cast(), Some(&cfg));

let exporter = ptr.assume_init();

assert_eq!(ret, None);

let data = rmp_serde::to_vec_named::<Vec<Vec<Span>>>(&vec![vec![]]).unwrap();
let traces = ByteSlice::new(&data);
let mut response = AgentResponse { rate: 0.0 };

ret = ddog_trace_exporter_send(Some(exporter.as_ref()), traces, 0, Some(&mut response));
assert_eq!(ret, None);
assert_eq!(response.rate, 0.8);

ddog_trace_exporter_free(exporter);
}
}

#[test]
// Ignore because it seems, at least in the version we're currently using, miri can't emulate
// libc::socket function.
#[cfg_attr(miri, ignore)]
fn exporter_send_empty_array_test() {
// Test added due to ensure the exporter is able to send empty arrays because some tracers
// (.NET) ping the agent with the aforementioned data type.
unsafe {
let server = MockServer::start();

let mock_traces = server.mock(|when, then| {
when.method(POST)
.header("Content-type", "application/msgpack")
.path("/v0.4/traces");
then.status(200).body(
r#"{
"rate_by_service": {
"service:foo,env:staging": 1.0,
"service:,env:": 0.8
}
}"#,
);
});

let cfg = TraceExporterConfig {
url: Some(server.url("/")),
tracer_version: Some("0.1".to_string()),
language: Some("lang".to_string()),
language_version: Some("0.1".to_string()),
language_interpreter: Some("interpreter".to_string()),
hostname: Some("hostname".to_string()),
env: Some("env-test".to_string()),
version: Some("1.0".to_string()),
service: Some("test-service".to_string()),
input_format: TraceExporterInputFormat::V04,
output_format: TraceExporterOutputFormat::V04,
compute_stats: false,
};

let mut ptr: MaybeUninit<Box<TraceExporter>> = MaybeUninit::uninit();
let mut ret =
ddog_trace_exporter_new(NonNull::new_unchecked(&mut ptr).cast(), Some(&cfg));

let exporter = ptr.assume_init();

assert_eq!(ret, None);

let data = vec![0x90];
let traces = ByteSlice::new(&data);
let mut response = AgentResponse { rate: 0.0 };

ret = ddog_trace_exporter_send(Some(exporter.as_ref()), traces, 0, Some(&mut response));
mock_traces.assert();
assert_eq!(ret, None);
assert_eq!(response.rate, 0.8);

ddog_trace_exporter_free(exporter);
}
}
}
42 changes: 35 additions & 7 deletions data-pipeline/src/trace_exporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,13 +590,6 @@ impl TraceExporter {
}
};

if traces.is_empty() {
error!("No traces deserialized from the request body.");
return Err(TraceExporterError::Io(std::io::Error::from(
std::io::ErrorKind::InvalidInput,
)));
}

let num_traces = traces.len();

self.emit_metric(
Expand Down Expand Up @@ -1531,6 +1524,41 @@ mod tests {
assert_eq!(result, AgentResponse::from(0.8));
}

#[test]
#[cfg_attr(miri, ignore)]
fn agent_response_empty_array() {
let server = MockServer::start();
let _agent = server.mock(|_, then| {
then.status(200)
.header("content-type", "application/json")
.body(
r#"{
"rate_by_service": {
"service:foo,env:staging": 1.0,
"service:,env:": 0.8
}
}"#,
);
});

let exporter = TraceExporterBuilder::default()
.set_url(&server.url("/"))
.set_service("foo")
.set_env("foo-env")
.set_tracer_version("v0.1")
.set_language("nodejs")
.set_language_version("1.0")
.set_language_interpreter("v8")
.build()
.unwrap();

let traces = vec![0x90];
let bytes = tinybytes::Bytes::from(traces);
let result = exporter.send(bytes, 1).unwrap();

assert_eq!(result, AgentResponse::from(0.8));
}

#[test]
#[cfg_attr(miri, ignore)]
fn builder_error() {
Expand Down
20 changes: 0 additions & 20 deletions ddcommon/src/entity_id/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,3 @@ pub fn get_external_env() -> Option<&'static str> {
}
DD_EXTERNAL_ENV.as_deref()
}

/// Set the path to cgroup file to mock it during tests
/// # Safety
/// Must not be called in multi-threaded contexts
pub unsafe fn set_cgroup_file(_file: String) {
#[cfg(unix)]
{
unix::set_cgroup_file(_file)
}
}

/// Set cgroup mount path to mock during tests
/// # Safety
/// Must not be called in multi-threaded contexts
pub unsafe fn set(_path: String) {
#[cfg(unix)]
{
unix::set_cgroup_mount_path(_path)
}
}
35 changes: 2 additions & 33 deletions ddcommon/src/entity_id/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ const DEFAULT_CGROUP_MOUNT_PATH: &str = "/sys/fs/cgroup";
/// the base controller used to identify the cgroup v1 mount point in the cgroupMounts map.
const CGROUP_V1_BASE_CONTROLLER: &str = "memory";

/// stores overridable cgroup path - used in end-to-end testing to "stub" cgroup values
static mut TESTING_CGROUP_PATH: Option<String> = None;
/// stores overridable cgroup mount path
static mut TESTING_CGROUP_MOUNT_PATH: Option<String> = None;

#[derive(Debug, Clone, PartialEq)]
pub enum CgroupFileParsingError {
ContainerIdNotFound,
Expand Down Expand Up @@ -58,37 +53,11 @@ fn compute_entity_id(
}

fn get_cgroup_path() -> &'static str {
// Safety: we assume set_cgroup_file is not called when it shouldn't
#[allow(static_mut_refs)]
unsafe {
TESTING_CGROUP_PATH
.as_deref()
.unwrap_or(DEFAULT_CGROUP_PATH)
}
DEFAULT_CGROUP_PATH
}

fn get_cgroup_mount_path() -> &'static str {
// Safety: we assume set_cgroup_file is not called when it shouldn't
#[allow(static_mut_refs)]
unsafe {
TESTING_CGROUP_MOUNT_PATH
.as_deref()
.unwrap_or(DEFAULT_CGROUP_MOUNT_PATH)
}
}

/// Set the path to cgroup file to mock it during tests
/// # Safety
/// Must not be called in multi-threaded contexts
pub unsafe fn set_cgroup_file(file: String) {
TESTING_CGROUP_PATH = Some(file)
}

/// Set cgroup mount path to mock during tests
/// # Safety
/// Must not be called in multi-threaded contexts
pub unsafe fn set_cgroup_mount_path(path: String) {
TESTING_CGROUP_MOUNT_PATH = Some(path)
DEFAULT_CGROUP_MOUNT_PATH
}

/// Returns the `container_id` if available in the cgroup file, otherwise returns `None`
Expand Down
8 changes: 4 additions & 4 deletions tinybytes/src/bytes_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,14 @@ mod tests {
}

#[test]
fn from_string() {
fn test_from_string() {
let string = String::from("hello");
let bytes_string = BytesString::from(string);
assert_eq!(bytes_string.as_str(), "hello")
}

#[test]
fn from_static_str() {
fn test_from_static_str() {
let static_str = "hello";
let bytes_string = BytesString::from(static_str);
assert_eq!(bytes_string.as_str(), "hello")
Expand All @@ -245,13 +245,13 @@ mod tests {
}

#[test]
fn hash() {
fn test_hash() {
let bytes_string = BytesString::from_slice(b"test hash").unwrap();
assert_eq!(calculate_hash(&bytes_string), calculate_hash(&"test hash"));
}

#[test]
fn copy_to_string() {
fn test_copy_to_string() {
let bytes_string = BytesString::from("hello");
assert_eq!(bytes_string.copy_to_string(), "hello")
}
Expand Down

0 comments on commit 6680602

Please sign in to comment.