aboutsummaryrefslogtreecommitdiff
path: root/crates/arti
diff options
context:
space:
mode:
Diffstat (limited to 'crates/arti')
-rw-r--r--crates/arti/Cargo.toml4
-rw-r--r--crates/arti/src/cfg.rs3
-rw-r--r--crates/arti/src/logging.rs137
-rw-r--r--crates/arti/src/logging/otlp_file_exporter.rs83
4 files changed, 19 insertions, 208 deletions
diff --git a/crates/arti/Cargo.toml b/crates/arti/Cargo.toml
index cce45ad87..ad1f49aad 100644
--- a/crates/arti/Cargo.toml
+++ b/crates/arti/Cargo.toml
@@ -125,10 +125,12 @@ syslog = ["syslog-tracing"]
opentelemetry = [
"tracing-opentelemetry",
"dep:opentelemetry",
+ "dep:otlp-file-exporter",
"opentelemetry_sdk",
"opentelemetry-otlp",
"opentelemetry-appender-tracing",
"opentelemetry-proto",
+ "tor-config-shared/opentelemetry",
"__is_experimental",
]
@@ -200,6 +202,7 @@ opentelemetry-appender-tracing = { version = "0.32.0", optional = true }
opentelemetry-otlp = { version = "0.32.0", optional = true }
opentelemetry-proto = { version = "0.32.0", optional = true }
opentelemetry_sdk = { version = "0.32.1", features = ["rt-tokio"], optional = true } # TODO: what's up with this feature
+otlp-file-exporter = { path = "../otlp-file-exporter", version = "0.1.0", optional = true }
paste = "1.0.3"
pin-project = "1"
postage = { version = "0.5.0", default-features = false, features = ["futures-traits"] }
@@ -221,6 +224,7 @@ tor-basic-utils = { path = "../tor-basic-utils", version = "0.45.0" }
tor-cell = { path = "../tor-cell", version = "0.45.0", optional = true }
tor-config = { path = "../tor-config", version = "0.45.0" }
tor-config-path = { path = "../tor-config-path", version = "0.45.0" }
+tor-config-shared = { path = "../tor-config-shared", version = "0.45.0" }
tor-error = { path = "../tor-error", version = "0.45.0", default-features = false, features = ["tracing"] }
tor-general-addr = { path = "../tor-general-addr", version = "0.45.0" }
tor-hsclient = { path = "../tor-hsclient", version = "0.45.0", optional = true }
diff --git a/crates/arti/src/cfg.rs b/crates/arti/src/cfg.rs
index 181ab295d..50081c877 100644
--- a/crates/arti/src/cfg.rs
+++ b/crates/arti/src/cfg.rs
@@ -21,7 +21,8 @@ use arti_client::TorClientConfig;
#[cfg(feature = "onion-service-service")]
use tor_config::define_list_builder_accessors;
use tor_config::derive::prelude::*;
-pub(crate) use tor_config::{ConfigBuildError, Listen, MetricsConfig, MetricsConfigBuilder};
+pub(crate) use tor_config::{ConfigBuildError, Listen};
+pub(crate) use tor_config_shared::metrics::{MetricsConfig, MetricsConfigBuilder};
use crate::{LoggingConfig, LoggingConfigBuilder};
diff --git a/crates/arti/src/logging.rs b/crates/arti/src/logging.rs
index fde918b77..ad9347a0a 100644
--- a/crates/arti/src/logging.rs
+++ b/crates/arti/src/logging.rs
@@ -7,9 +7,9 @@ use serde::{Deserialize, Serialize};
use std::io::IsTerminal as _;
use std::path::Path;
use std::str::FromStr;
-use std::time::Duration;
use tor_basic_utils::PathExt as _;
use tor_config::ConfigBuildError;
+use tor_config_shared::opentelemetry::{OpentelemetryConfig, OpentelemetryConfigBuilder};
use tor_config::derive::prelude::*;
use tor_config_path::{CfgPath, CfgPathResolver};
use tor_error::warn_report;
@@ -20,8 +20,6 @@ use tracing_subscriber::prelude::*;
use tracing_subscriber::{Layer, filter::Targets, fmt, registry};
mod fields;
-#[cfg(feature = "opentelemetry")]
-mod otlp_file_exporter;
mod time;
/// Structure to hold our logging configuration options
@@ -149,109 +147,6 @@ pub(crate) enum LogRotation {
Never,
}
-/// Configuration for exporting spans with OpenTelemetry.
-#[derive(Debug, Deftly, Clone, Eq, PartialEq, Serialize, Deserialize)]
-#[derive_deftly(TorConfig)]
-#[cfg_attr(feature = "experimental-api", visibility::make(pub))]
-#[cfg_attr(feature = "experimental-api", deftly(tor_config(vis = "pub")))]
-pub(crate) struct OpentelemetryConfig {
- /// Write spans to a file in OTLP JSON format.
- #[deftly(tor_config(default))]
- file: Option<OpentelemetryFileExporterConfig>,
- /// Export spans via HTTP.
- #[deftly(tor_config(default))]
- http: Option<OpentelemetryHttpExporterConfig>,
-}
-
-/// Configuration for the OpenTelemetry HTTP exporter.
-#[derive(Debug, Deftly, Clone, Eq, PartialEq, Serialize, Deserialize)]
-#[derive_deftly(TorConfig)]
-#[deftly(tor_config(no_default_trait))]
-#[cfg_attr(feature = "experimental-api", visibility::make(pub))]
-#[cfg_attr(feature = "experimental-api", deftly(tor_config(vis = "pub")))]
-pub(crate) struct OpentelemetryHttpExporterConfig {
- /// HTTP(S) endpoint to send spans to.
- ///
- /// For Jaeger, this should be something like: `http://localhost:4318/v1/traces`
- #[deftly(tor_config(no_default))]
- endpoint: String,
- /// Configuration for how to batch exports.
- #[deftly(tor_config(sub_builder))]
- batch: OpentelemetryBatchConfig,
- /// Timeout for sending data.
- ///
- /// If this is set to [`None`], it will be left at the OpenTelemetry default, which is
- /// currently 10 seconds unless overridden with a environment variable.
- //
- // NOTE: there is no way to actually override this with None, so we have to say
- // "no magic" to tell dd(TorConfig) not to worry about that.
- #[deftly(tor_config(no_magic, default))]
- timeout: Option<Duration>,
- // TODO: Once opentelemetry-otlp supports more than one protocol over HTTP, add a config option
- // to choose protocol here.
-}
-
-/// Configuration for the OpenTelemetry HTTP exporter.
-#[derive(Debug, Deftly, Clone, Eq, PartialEq, Serialize, Deserialize)]
-#[derive_deftly(TorConfig)]
-#[deftly(tor_config(no_default_trait))]
-#[cfg_attr(feature = "experimental-api", visibility::make(pub))]
-#[cfg_attr(feature = "experimental-api", deftly(tor_config(vis = "pub")))]
-pub(crate) struct OpentelemetryFileExporterConfig {
- /// The path to write the JSON file to.
- #[deftly(tor_config(no_default))]
- path: CfgPath,
- /// Configuration for how to batch writes.
- #[deftly(tor_config(sub_builder))]
- batch: OpentelemetryBatchConfig,
-}
-
-/// Configuration for the Opentelemetry batch exporting.
-///
-/// This is a copy of [`opentelemetry_sdk::trace::BatchConfig`].
-#[derive(Debug, Deftly, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
-#[derive_deftly(TorConfig)]
-#[cfg_attr(feature = "experimental-api", visibility::make(pub))]
-#[cfg_attr(feature = "experimental-api", deftly(tor_config(vis = "pub")))]
-pub(crate) struct OpentelemetryBatchConfig {
- /// Maximum queue size. See [`opentelemetry_sdk::trace::BatchConfig::max_queue_size`].
- #[deftly(tor_config(default))]
- max_queue_size: Option<usize>,
- /// Maximum export batch size. See [`opentelemetry_sdk::trace::BatchConfig::max_export_batch_size`].
- #[deftly(tor_config(default))]
- max_export_batch_size: Option<usize>,
- /// Scheduled delay. See [`opentelemetry_sdk::trace::BatchConfig::scheduled_delay`].
- #[deftly(tor_config(no_magic, default))]
- scheduled_delay: Option<Duration>,
-}
-
-#[cfg(feature = "opentelemetry")]
-impl From<OpentelemetryBatchConfig> for opentelemetry_sdk::trace::BatchConfig {
- fn from(config: OpentelemetryBatchConfig) -> opentelemetry_sdk::trace::BatchConfig {
- let batch_config = opentelemetry_sdk::trace::BatchConfigBuilder::default();
-
- let batch_config = if let Some(max_queue_size) = config.max_queue_size {
- batch_config.with_max_queue_size(max_queue_size)
- } else {
- batch_config
- };
-
- let batch_config = if let Some(max_export_batch_size) = config.max_export_batch_size {
- batch_config.with_max_export_batch_size(max_export_batch_size)
- } else {
- batch_config
- };
-
- let batch_config = if let Some(scheduled_delay) = config.scheduled_delay {
- batch_config.with_scheduled_delay(scheduled_delay)
- } else {
- batch_config
- };
-
- batch_config.build()
- }
-}
-
/// Configuration for logging to the tokio console.
#[derive(Debug, Deftly, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
#[derive_deftly(TorConfig)]
@@ -372,7 +267,7 @@ where
use opentelemetry::trace::TracerProvider;
use opentelemetry_otlp::WithExportConfig;
- if config.opentelemetry.file.is_some() && config.opentelemetry.http.is_some() {
+ if config.opentelemetry.file().is_some() && config.opentelemetry.http().is_some() {
return Err(ConfigBuildError::Invalid {
field: "logging.opentelemetry".into(),
problem: "Only one OpenTelemetry exporter can be enabled at once.".into(),
@@ -384,21 +279,21 @@ where
.with_service_name("arti")
.build();
- let span_processor = if let Some(otel_file_config) = &config.opentelemetry.file {
+ let span_processor = if let Some(otel_file_config) = &config.opentelemetry.file() {
let file = std::fs::File::options()
.create(true)
.append(true)
- .open(otel_file_config.path.path(path_resolver)?)?;
+ .open(otel_file_config.path().path(path_resolver)?)?;
let exporter = otlp_file_exporter::FileExporter::new(file, resource.clone());
opentelemetry_sdk::trace::BatchSpanProcessor::builder(exporter)
- .with_batch_config(otel_file_config.batch.into())
+ .with_batch_config(otel_file_config.batch().clone().into())
.build()
- } else if let Some(otel_http_config) = &config.opentelemetry.http {
- if otel_http_config.endpoint.starts_with("http://")
- && !(otel_http_config.endpoint.starts_with("http://localhost")
- || otel_http_config.endpoint.starts_with("http://127.0.0.1"))
+ } else if let Some(otel_http_config) = &config.opentelemetry.http() {
+ if otel_http_config.endpoint().starts_with("http://")
+ && !(otel_http_config.endpoint().starts_with("http://localhost")
+ || otel_http_config.endpoint().starts_with("http://127.0.0.1"))
{
return Err(ConfigBuildError::Invalid {
field: "logging.opentelemetry.http.endpoint".into(),
@@ -408,18 +303,12 @@ where
}
let exporter = opentelemetry_otlp::SpanExporter::builder()
.with_http()
- .with_endpoint(otel_http_config.endpoint.clone());
-
- let exporter = if let Some(timeout) = otel_http_config.timeout {
- exporter.with_timeout(timeout)
- } else {
- exporter
- };
-
- let exporter = exporter.build()?;
+ .with_endpoint(otel_http_config.endpoint().clone())
+ .with_timeout(*otel_http_config.timeout())
+ .build()?;
opentelemetry_sdk::trace::BatchSpanProcessor::builder(exporter)
- .with_batch_config(otel_http_config.batch.into())
+ .with_batch_config(otel_http_config.batch().clone().into())
.build()
} else {
return Ok(None);
diff --git a/crates/arti/src/logging/otlp_file_exporter.rs b/crates/arti/src/logging/otlp_file_exporter.rs
deleted file mode 100644
index 19943b1e4..000000000
--- a/crates/arti/src/logging/otlp_file_exporter.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-//! Tracing exporter to write spans to a file in the OTLP JSON format.
-
-// TODO: If https://github.com/open-telemetry/opentelemetry-rust/issues/2602 gets fixed, we can
-// replace this entire file with whatever upstream has for doing this.
-
-use opentelemetry_proto::transform::common::tonic::ResourceAttributesWithSchema;
-use opentelemetry_proto::transform::trace::tonic::group_spans_by_resource_and_scope;
-use opentelemetry_sdk::{
- Resource,
- error::{OTelSdkError, OTelSdkResult},
- trace::SpanExporter,
-};
-use std::{
- fmt::Debug,
- io::{LineWriter, Write},
- sync::{Arc, Mutex},
-};
-
-/// Tracing exporter to write OTLP JSON to a file (or anything else that implements [`LineWriter`].
-#[derive(Debug)]
-pub(crate) struct FileExporter<W: Write + Send + Debug> {
- /// The [`LineWriter`] to write to.
- writer: Arc<Mutex<LineWriter<W>>>,
- /// The [`Resource`] to associate spans with.
- resource: Resource,
-}
-
-impl<W: Write + Send + Debug> FileExporter<W> {
- /// Create a new [`FileExporter`]
- pub(crate) fn new(writer: W, resource: Resource) -> Self {
- Self {
- writer: Arc::new(Mutex::new(LineWriter::new(writer))),
- resource,
- }
- }
-}
-
-// Note that OpenTelemetry can only represent events as children of spans, so this exporter only
-// works on spans. If you want a event to be exported, you need to make sure it exists within some
-// span.
-impl<W: Write + Send + Debug> SpanExporter for FileExporter<W> {
- fn export(
- &self,
- batch: Vec<opentelemetry_sdk::trace::SpanData>,
- ) -> impl futures::Future<
- Output = std::result::Result<(), opentelemetry_sdk::error::OTelSdkError>,
- > + std::marker::Send {
- let resource = ResourceAttributesWithSchema::from(&self.resource);
- let data = group_spans_by_resource_and_scope(batch, &resource);
- let mut writer = self.writer.lock().expect("Lock poisoned");
- Box::pin(std::future::ready('write: {
- // See https://opentelemetry.io/docs/specs/otel/protocol/file-exporter/ for format
-
- if let Err(err) = serde_json::to_writer(
- writer.get_mut(),
- &serde_json::json!({"resourceSpans": data}),
- ) {
- break 'write Err(OTelSdkError::InternalFailure(err.to_string()));
- }
-
- if let Err(err) = writer.write(b"\n") {
- break 'write Err(OTelSdkError::InternalFailure(err.to_string()));
- }
-
- Ok(())
- }))
- }
-
- fn force_flush(&self) -> OTelSdkResult {
- let mut writer = self
- .writer
- .lock()
- .map_err(|e| OTelSdkError::InternalFailure(e.to_string()))?;
-
- writer
- .flush()
- .map_err(|e| OTelSdkError::InternalFailure(e.to_string()))
- }
-
- fn set_resource(&mut self, res: &opentelemetry_sdk::Resource) {
- self.resource = res.clone();
- }
-}