Skip to content

Commit 2a72da1

Browse files
committed
WIP ddcommon-net crate + profiling updated
1 parent 1224be0 commit 2a72da1

File tree

9 files changed

+660
-268
lines changed

9 files changed

+660
-268
lines changed

Diff for: Cargo.lock

+140-95
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ members = [
3737
"data-pipeline-ffi",
3838
"ddsketch",
3939
"tinybytes",
40-
"dogstatsd-client",
40+
"dogstatsd-client", "ddcommon-net",
4141
]
4242

4343
# https://doc.rust-lang.org/cargo/reference/resolver.html#feature-resolver-version-2

Diff for: ddcommon-net/Cargo.toml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
[package]
5+
name = "ddcommon-net"
6+
rust-version.workspace = true
7+
edition.workspace = true
8+
version.workspace = true
9+
license.workspace = true
10+
11+
[dependencies]
12+
ddcommon = { path = "../ddcommon" }
13+
hex = { version = "0.4" }
14+
http = { version = "1" }
15+
hyper = { version = "1", default-features = false }
16+
hyper-util = { version = "0.1", default-features = false, features = ["tokio"] }
17+
hyperlocal = { version = "0.9" }
18+
serde = { version = "1.0", features = ["derive"] }
19+
thiserror = { version = "2" }
20+
tokio = { version = "1.41" }
21+
tokio-rustls = { version = "0.26" }
22+
tokio-util = { version = "0.7" }

Diff for: ddcommon-net/src/compat.rs

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright 2021-Present Datadog, Inc. https://www.datadoghq.com/
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use ddcommon::entity_id;
5+
use http::request::Builder as HttpRequestBuilder;
6+
use http::{HeaderValue, Uri};
7+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
8+
use std::borrow::Cow;
9+
use std::ops::Deref;
10+
11+
// todo: why do we need to serialize and deserialize endpoints?
12+
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
13+
pub struct Endpoint {
14+
#[serde(serialize_with = "serialize_uri", deserialize_with = "deserialize_uri")]
15+
pub url: Uri,
16+
pub api_key: Option<Cow<'static, str>>,
17+
pub timeout_ms: u64,
18+
/// Sets X-Datadog-Test-Session-Token header on any request
19+
pub test_token: Option<Cow<'static, str>>,
20+
}
21+
22+
#[derive(serde::Deserialize, serde::Serialize)]
23+
struct SerializedUri<'a> {
24+
scheme: Option<Cow<'a, str>>,
25+
authority: Option<Cow<'a, str>>,
26+
path_and_query: Option<Cow<'a, str>>,
27+
}
28+
29+
fn serialize_uri<S>(uri: &Uri, serializer: S) -> Result<S::Ok, S::Error>
30+
where
31+
S: Serializer,
32+
{
33+
let parts = uri.clone().into_parts();
34+
let uri = SerializedUri {
35+
scheme: parts.scheme.as_ref().map(|s| Cow::Borrowed(s.as_str())),
36+
authority: parts.authority.as_ref().map(|s| Cow::Borrowed(s.as_str())),
37+
path_and_query: parts
38+
.path_and_query
39+
.as_ref()
40+
.map(|s| Cow::Borrowed(s.as_str())),
41+
};
42+
uri.serialize(serializer)
43+
}
44+
45+
fn deserialize_uri<'de, D>(deserializer: D) -> Result<Uri, D::Error>
46+
where
47+
D: Deserializer<'de>,
48+
{
49+
let uri = SerializedUri::deserialize(deserializer)?;
50+
let mut builder = hyper::Uri::builder();
51+
if let Some(v) = uri.authority {
52+
builder = builder.authority(v.deref());
53+
}
54+
if let Some(v) = uri.scheme {
55+
builder = builder.scheme(v.deref());
56+
}
57+
if let Some(v) = uri.path_and_query {
58+
builder = builder.path_and_query(v.deref());
59+
}
60+
61+
builder.build().map_err(serde::de::Error::custom)
62+
}
63+
64+
impl Endpoint {
65+
/// Default value for the timeout field in milliseconds.
66+
pub const DEFAULT_TIMEOUT: u64 = 3_000;
67+
68+
/// Return a request builder with the following headers:
69+
/// - User agent
70+
/// - Api key
71+
/// - Container Id/Entity Id
72+
pub fn into_request_builder(
73+
&self,
74+
user_agent: &str,
75+
) -> Result<HttpRequestBuilder, http::Error> {
76+
let mut builder = hyper::Request::builder()
77+
.uri(self.url.clone())
78+
.header(hyper::header::USER_AGENT, user_agent);
79+
80+
// Add the Api key header if available
81+
if let Some(api_key) = &self.api_key {
82+
builder = builder.header(header::DATADOG_API_KEY, HeaderValue::from_str(api_key)?);
83+
}
84+
85+
// Add the test session token if available
86+
if let Some(token) = &self.test_token {
87+
builder = builder.header(
88+
header::X_DATADOG_TEST_SESSION_TOKEN,
89+
HeaderValue::from_str(token)?,
90+
);
91+
}
92+
93+
// Add the Container Id header if available
94+
if let Some(container_id) = entity_id::get_container_id() {
95+
builder = builder.header(header::DATADOG_CONTAINER_ID, container_id);
96+
}
97+
98+
// Add the Entity Id header if available
99+
if let Some(entity_id) = entity_id::get_entity_id() {
100+
builder = builder.header(header::DATADOG_ENTITY_ID, entity_id);
101+
}
102+
103+
// Add the External Env header if available
104+
if let Some(external_env) = entity_id::get_external_env() {
105+
builder = builder.header(header::DATADOG_EXTERNAL_ENV, external_env);
106+
}
107+
108+
Ok(builder)
109+
}
110+
}
111+
112+
impl From<Uri> for Endpoint {
113+
fn from(uri: Uri) -> Self {
114+
Self {
115+
url: uri,
116+
api_key: None,
117+
timeout_ms: 0,
118+
test_token: None,
119+
}
120+
}
121+
}
122+
123+
pub mod header {
124+
#![allow(clippy::declare_interior_mutable_const)]
125+
use hyper::{header::HeaderName, http::HeaderValue};
126+
pub const DATADOG_CONTAINER_ID: HeaderName = HeaderName::from_static("datadog-container-id");
127+
pub const DATADOG_ENTITY_ID: HeaderName = HeaderName::from_static("datadog-entity-id");
128+
pub const DATADOG_EXTERNAL_ENV: HeaderName = HeaderName::from_static("datadog-external-env");
129+
pub const DATADOG_TRACE_COUNT: HeaderName = HeaderName::from_static("x-datadog-trace-count");
130+
pub const DATADOG_API_KEY: HeaderName = HeaderName::from_static("dd-api-key");
131+
pub const APPLICATION_JSON: HeaderValue = HeaderValue::from_static("application/json");
132+
pub const APPLICATION_MSGPACK: HeaderValue = HeaderValue::from_static("application/msgpack");
133+
pub const X_DATADOG_TEST_SESSION_TOKEN: HeaderName =
134+
HeaderName::from_static("x-datadog-test-session-token");
135+
}

0 commit comments

Comments
 (0)