0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-04 01:44:26 -05:00

feat(unstable): support https otlp endpoints (#27743)

Support HTTPS protocol for otel exporting. Includes support for
`OTEL_EXPORTER_OTLP_CERTIFICATE`, `OTEL_EXPORTER_OTLP_CLIENT_KEY`, and
`OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE`

Fixes: https://github.com/denoland/deno/issues/27703
This commit is contained in:
snek 2025-01-22 14:07:04 +01:00 committed by GitHub
parent f175b5b50f
commit 32eb991ef8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 7 deletions

2
Cargo.lock generated
View file

@ -2421,8 +2421,10 @@ dependencies = [
"async-trait", "async-trait",
"deno_core", "deno_core",
"deno_error", "deno_error",
"deno_tls",
"http-body-util", "http-body-util",
"hyper 1.4.1", "hyper 1.4.1",
"hyper-rustls",
"hyper-util", "hyper-util",
"log", "log",
"once_cell", "once_cell",

View file

@ -17,8 +17,10 @@ path = "lib.rs"
async-trait.workspace = true async-trait.workspace = true
deno_core.workspace = true deno_core.workspace = true
deno_error.workspace = true deno_error.workspace = true
deno_tls.workspace = true
http-body-util.workspace = true http-body-util.workspace = true
hyper.workspace = true hyper.workspace = true
hyper-rustls.workspace = true
hyper-util.workspace = true hyper-util.workspace = true
log.workspace = true log.workspace = true
once_cell.workspace = true once_cell.workspace = true

View file

@ -477,10 +477,17 @@ mod hyper_client {
use std::task::Poll; use std::task::Poll;
use std::task::{self}; use std::task::{self};
use deno_tls::create_client_config;
use deno_tls::load_certs;
use deno_tls::load_private_keys;
use deno_tls::SocketUse;
use deno_tls::TlsKey;
use deno_tls::TlsKeys;
use http_body_util::BodyExt; use http_body_util::BodyExt;
use http_body_util::Full; use http_body_util::Full;
use hyper::body::Body as HttpBody; use hyper::body::Body as HttpBody;
use hyper::body::Frame; use hyper::body::Frame;
use hyper_rustls::HttpsConnector;
use hyper_util::client::legacy::connect::HttpConnector; use hyper_util::client::legacy::connect::HttpConnector;
use hyper_util::client::legacy::Client; use hyper_util::client::legacy::Client;
use opentelemetry_http::Bytes; use opentelemetry_http::Bytes;
@ -494,14 +501,41 @@ mod hyper_client {
// same as opentelemetry_http::HyperClient except it uses OtelSharedRuntime // same as opentelemetry_http::HyperClient except it uses OtelSharedRuntime
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct HyperClient { pub struct HyperClient {
inner: Client<HttpConnector, Body>, inner: Client<HttpsConnector<HttpConnector>, Body>,
} }
impl HyperClient { impl HyperClient {
pub fn new() -> Self { pub fn new() -> deno_core::anyhow::Result<Self> {
Self { let ca_certs = match std::env::var("OTEL_EXPORTER_OTLP_CERTIFICATE") {
inner: Client::builder(OtelSharedRuntime).build(HttpConnector::new()), Ok(path) => vec![std::fs::read(path)?],
} _ => vec![],
};
let keys = match (
std::env::var("OTEL_EXPORTER_OTLP_CLIENT_KEY"),
std::env::var("OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE"),
) {
(Ok(key_path), Ok(cert_path)) => {
let key = std::fs::read(key_path)?;
let cert = std::fs::read(cert_path)?;
let certs = load_certs(&mut std::io::Cursor::new(cert))?;
let key = load_private_keys(&key)?.into_iter().next().unwrap();
TlsKeys::Static(TlsKey(certs, key))
}
_ => TlsKeys::Null,
};
let tls_config =
create_client_config(None, ca_certs, None, keys, SocketUse::Http)?;
let mut http_connector = HttpConnector::new();
http_connector.enforce_http(false);
let connector = HttpsConnector::from((http_connector, tls_config));
Ok(Self {
inner: Client::builder(OtelSharedRuntime).build(connector),
})
} }
} }
@ -628,7 +662,7 @@ pub fn init(
// `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable. Additional headers can // `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable. Additional headers can
// be specified using `OTEL_EXPORTER_OTLP_HEADERS`. // be specified using `OTEL_EXPORTER_OTLP_HEADERS`.
let client = hyper_client::HyperClient::new(); let client = hyper_client::HyperClient::new()?;
let span_exporter = HttpExporterBuilder::default() let span_exporter = HttpExporterBuilder::default()
.with_http_client(client.clone()) .with_http_client(client.clone())

View file

@ -8,6 +8,8 @@ const data = {
const server = Deno.serve( const server = Deno.serve(
{ {
key: Deno.readTextFileSync("../../../testdata/tls/localhost.key"),
cert: Deno.readTextFileSync("../../../testdata/tls/localhost.crt"),
port: 0, port: 0,
onListen({ port }) { onListen({ port }) {
const command = new Deno.Command(Deno.execPath(), { const command = new Deno.Command(Deno.execPath(), {
@ -16,7 +18,8 @@ const server = Deno.serve(
OTEL_DENO: "true", OTEL_DENO: "true",
DENO_UNSTABLE_OTEL_DETERMINISTIC: "1", DENO_UNSTABLE_OTEL_DETERMINISTIC: "1",
OTEL_EXPORTER_OTLP_PROTOCOL: "http/json", OTEL_EXPORTER_OTLP_PROTOCOL: "http/json",
OTEL_EXPORTER_OTLP_ENDPOINT: `http://localhost:${port}`, OTEL_EXPORTER_OTLP_ENDPOINT: `https://localhost:${port}`,
OTEL_EXPORTER_OTLP_CERTIFICATE: "../../../testdata/tls/RootCA.crt",
}, },
stdout: "null", stdout: "null",
}); });