Skip to content

Commit eba955f

Browse files
authored
Merge branch 'main' into cijothomas/fixperiodicreaderpanic
2 parents 54c1c0a + a81ad24 commit eba955f

File tree

4 files changed

+115
-68
lines changed

4 files changed

+115
-68
lines changed

opentelemetry-otlp/CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@
1313
- Remove unnecessarily public trait `opentelemetry_otlp::metrics::MetricsClient`
1414
and `MetricExporter::new(..)` method. Use
1515
`MetricExporter::builder()...build()` to obtain `MetricExporter`.
16+
- The HTTP clients (reqwest, reqwest-blocking, hyper) now support the
17+
timeout internal configured in below order
18+
- Signal specific env variable `OTEL_EXPORTER_OTLP_TRACES_TIMEOUT`,
19+
`OTEL_EXPORTER_OTLP_LOGS_TIMEOUT` or `OTEL_EXPORTER_OTLP_TIMEOUT`.
20+
- `OTEL_EXPORTER_OTLP_TIMEOUT` env variable.
21+
- `with_http().with_timeout()` API method of
22+
`LogExporterBuilder` and `SpanExporterBuilder` and `MetricsExporterBuilder`.
23+
- The default interval of 10sec is used if none is configured.
24+
1625

1726
## 0.27.0
1827

opentelemetry-otlp/src/exporter/http/mod.rs

+51-52
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,7 @@ mod trace;
4444
use opentelemetry_http::hyper::HyperClient;
4545

4646
/// Configuration of the http transport
47-
#[derive(Debug)]
48-
#[cfg_attr(
49-
all(
50-
not(feature = "reqwest-client"),
51-
not(feature = "reqwest-blocking-client"),
52-
not(feature = "hyper-client")
53-
),
54-
derive(Default)
55-
)]
47+
#[derive(Debug, Default)]
5648
pub struct HttpConfig {
5749
/// Select the HTTP client
5850
client: Option<Arc<dyn HttpClient>>,
@@ -61,44 +53,6 @@ pub struct HttpConfig {
6153
headers: Option<HashMap<String, String>>,
6254
}
6355

64-
#[cfg(any(
65-
feature = "reqwest-blocking-client",
66-
feature = "reqwest-client",
67-
feature = "hyper-client"
68-
))]
69-
impl Default for HttpConfig {
70-
fn default() -> Self {
71-
#[cfg(feature = "reqwest-blocking-client")]
72-
let default_client = std::thread::spawn(|| {
73-
Some(Arc::new(reqwest::blocking::Client::new()) as Arc<dyn HttpClient>)
74-
})
75-
.join()
76-
.expect("creating reqwest::blocking::Client on a new thread not to fail");
77-
#[cfg(all(not(feature = "reqwest-blocking-client"), feature = "reqwest-client"))]
78-
let default_client = Some(Arc::new(reqwest::Client::new()) as Arc<dyn HttpClient>);
79-
#[cfg(all(
80-
not(feature = "reqwest-client"),
81-
not(feature = "reqwest-blocking-client"),
82-
feature = "hyper-client"
83-
))]
84-
// TODO - support configuring custom connector and executor
85-
let default_client = Some(Arc::new(HyperClient::with_default_connector(
86-
Duration::from_secs(10),
87-
None,
88-
)) as Arc<dyn HttpClient>);
89-
#[cfg(all(
90-
not(feature = "reqwest-client"),
91-
not(feature = "reqwest-blocking-client"),
92-
not(feature = "hyper-client")
93-
))]
94-
let default_client = None;
95-
HttpConfig {
96-
client: default_client,
97-
headers: None,
98-
}
99-
}
100-
}
101-
10256
/// Configuration for the OTLP HTTP exporter.
10357
///
10458
/// ## Examples
@@ -171,11 +125,56 @@ impl HttpExporterBuilder {
171125
},
172126
None => self.exporter_config.timeout,
173127
};
174-
let http_client = self
175-
.http_config
176-
.client
177-
.take()
178-
.ok_or(crate::Error::NoHttpClient)?;
128+
129+
#[allow(unused_mut)] // TODO - clippy thinks mut is not needed, but it is
130+
let mut http_client = self.http_config.client.take();
131+
132+
if http_client.is_none() {
133+
#[cfg(all(
134+
not(feature = "reqwest-client"),
135+
not(feature = "reqwest-blocking-client"),
136+
feature = "hyper-client"
137+
))]
138+
{
139+
// TODO - support configuring custom connector and executor
140+
http_client = Some(Arc::new(HyperClient::with_default_connector(timeout, None))
141+
as Arc<dyn HttpClient>);
142+
}
143+
#[cfg(all(
144+
not(feature = "hyper-client"),
145+
not(feature = "reqwest-blocking-client"),
146+
feature = "reqwest-client"
147+
))]
148+
{
149+
http_client = Some(Arc::new(
150+
reqwest::Client::builder()
151+
.timeout(timeout)
152+
.build()
153+
.unwrap_or_default(),
154+
) as Arc<dyn HttpClient>);
155+
}
156+
#[cfg(all(
157+
not(feature = "hyper-client"),
158+
not(feature = "reqwest-client"),
159+
feature = "reqwest-blocking-client"
160+
))]
161+
{
162+
let timeout_clone = timeout;
163+
http_client = Some(Arc::new(
164+
std::thread::spawn(move || {
165+
reqwest::blocking::Client::builder()
166+
.timeout(timeout_clone)
167+
.build()
168+
.unwrap_or_else(|_| reqwest::blocking::Client::new())
169+
})
170+
.join()
171+
.unwrap(), // Unwrap thread result
172+
) as Arc<dyn HttpClient>);
173+
}
174+
}
175+
176+
let http_client = http_client.ok_or(crate::Error::NoHttpClient)?;
177+
179178
#[allow(clippy::mutable_key_type)] // http headers are not mutated
180179
let mut headers: HashMap<HeaderName, HeaderValue> = self
181180
.http_config

opentelemetry-sdk/CHANGELOG.md

+33
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,39 @@ limit.
304304
`opentelemetry_sdk::trace::{InMemorySpanExporter, InMemorySpanExporterBuilder};`
305305
`opentelemetry_sdk::metrics::{InMemoryMetricExporter, InMemoryMetricExporterBuilder};`
306306

307+
- *Breaking*: The `BatchLogProcessor` no longer supports configuration of `max_export_timeout`
308+
or the `OTEL_BLRP_EXPORT_TIMEOUT` environment variable. Timeout handling is now the
309+
responsibility of the exporter.
310+
For example, in the OTLP Logs exporter, the export timeout can be configured using:
311+
- The environment variables `OTEL_EXPORTER_OTLP_TIMEOUT` or `OTEL_EXPORTER_OTLP_LOGS_TIMEOUT`.
312+
- The opentelemetry_otlp API, via `.with_tonic().with_timeout()` or `.with_http().with_timeout()`.
313+
Before:
314+
```rust
315+
let processor = BatchLogProcessor::builder(exporter)
316+
.with_batch_config(
317+
BatchConfigBuilder::default()
318+
.with_max_queue_size(2048)
319+
.with_max_export_batch_size(512)
320+
.with_scheduled_delay(Duration::from_secs(5))
321+
.with_max_export_timeout(Duration::from_secs(30)) // Previously configurable
322+
.build(),
323+
)
324+
.build();
325+
```
326+
327+
After:
328+
```rust
329+
let processor = BatchLogProcessor::builder(exporter)
330+
.with_batch_config(
331+
BatchConfigBuilder::default()
332+
.with_max_queue_size(2048)
333+
.with_max_export_batch_size(512)
334+
.with_scheduled_delay(Duration::from_secs(5)) // No `max_export_timeout`
335+
.build(),
336+
)
337+
.build();
338+
```
339+
307340
## 0.27.1
308341

309342
Released 2024-Nov-27

opentelemetry-sdk/src/logs/log_processor.rs

+22-16
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ pub(crate) const OTEL_BLRP_SCHEDULE_DELAY: &str = "OTEL_BLRP_SCHEDULE_DELAY";
5757
/// Default delay interval between two consecutive exports.
5858
pub(crate) const OTEL_BLRP_SCHEDULE_DELAY_DEFAULT: u64 = 1_000;
5959
/// Maximum allowed time to export data.
60+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
6061
pub(crate) const OTEL_BLRP_EXPORT_TIMEOUT: &str = "OTEL_BLRP_EXPORT_TIMEOUT";
6162
/// Default maximum allowed time to export data.
63+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
6264
pub(crate) const OTEL_BLRP_EXPORT_TIMEOUT_DEFAULT: u64 = 30_000;
6365
/// Maximum queue size.
6466
pub(crate) const OTEL_BLRP_MAX_QUEUE_SIZE: &str = "OTEL_BLRP_MAX_QUEUE_SIZE";
@@ -229,7 +231,6 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>;
229231
/// - This processor supports the following configurations:
230232
/// - **Queue size**: Maximum number of log records that can be buffered.
231233
/// - **Batch size**: Maximum number of log records to include in a single export.
232-
/// - **Export timeout**: Maximum duration allowed for an export operation.
233234
/// - **Scheduled delay**: Frequency at which the batch is exported.
234235
///
235236
/// When using this processor with the OTLP Exporter, the following exporter
@@ -255,7 +256,6 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>;
255256
/// .with_max_queue_size(2048)
256257
/// .with_max_export_batch_size(512)
257258
/// .with_scheduled_delay(Duration::from_secs(5))
258-
/// .with_max_export_timeout(Duration::from_secs(30))
259259
/// .build(),
260260
/// )
261261
/// .build();
@@ -525,12 +525,7 @@ impl BatchLogProcessor {
525525
let count_of_logs = logs.len(); // Count of logs that will be exported
526526
total_exported_logs += count_of_logs;
527527

528-
result = export_with_timeout_sync(
529-
config.max_export_timeout,
530-
exporter,
531-
logs,
532-
last_export_time,
533-
); // This method clears the logs vec after exporting
528+
result = export_batch_sync(exporter, logs, last_export_time); // This method clears the logs vec after exporting
534529

535530
current_batch_size.fetch_sub(count_of_logs, Ordering::Relaxed);
536531
}
@@ -656,8 +651,7 @@ impl BatchLogProcessor {
656651
}
657652

658653
#[allow(clippy::vec_box)]
659-
fn export_with_timeout_sync<E>(
660-
_: Duration, // TODO, enforcing timeout in exporter.
654+
fn export_batch_sync<E>(
661655
exporter: &E,
662656
batch: &mut Vec<Box<(LogRecord, InstrumentationScope)>>,
663657
last_export_time: &mut Instant,
@@ -733,6 +727,7 @@ pub struct BatchConfig {
733727
pub(crate) max_export_batch_size: usize,
734728

735729
/// The maximum duration to export a batch of data.
730+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
736731
pub(crate) max_export_timeout: Duration,
737732
}
738733

@@ -748,6 +743,7 @@ pub struct BatchConfigBuilder {
748743
max_queue_size: usize,
749744
scheduled_delay: Duration,
750745
max_export_batch_size: usize,
746+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
751747
max_export_timeout: Duration,
752748
}
753749

@@ -764,6 +760,7 @@ impl Default for BatchConfigBuilder {
764760
max_queue_size: OTEL_BLRP_MAX_QUEUE_SIZE_DEFAULT,
765761
scheduled_delay: Duration::from_millis(OTEL_BLRP_SCHEDULE_DELAY_DEFAULT),
766762
max_export_batch_size: OTEL_BLRP_MAX_EXPORT_BATCH_SIZE_DEFAULT,
763+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
767764
max_export_timeout: Duration::from_millis(OTEL_BLRP_EXPORT_TIMEOUT_DEFAULT),
768765
}
769766
.init_from_env_vars()
@@ -791,6 +788,7 @@ impl BatchConfigBuilder {
791788
/// Set max_export_timeout for [`BatchConfigBuilder`].
792789
/// It's the maximum duration to export a batch of data.
793790
/// The default value is 30000 milliseconds.
791+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
794792
pub fn with_max_export_timeout(mut self, max_export_timeout: Duration) -> Self {
795793
self.max_export_timeout = max_export_timeout;
796794
self
@@ -816,6 +814,7 @@ impl BatchConfigBuilder {
816814
BatchConfig {
817815
max_queue_size: self.max_queue_size,
818816
scheduled_delay: self.scheduled_delay,
817+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
819818
max_export_timeout: self.max_export_timeout,
820819
max_export_batch_size,
821820
}
@@ -843,6 +842,7 @@ impl BatchConfigBuilder {
843842
self.scheduled_delay = Duration::from_millis(scheduled_delay);
844843
}
845844

845+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
846846
if let Some(max_export_timeout) = env::var(OTEL_BLRP_EXPORT_TIMEOUT)
847847
.ok()
848848
.and_then(|s| u64::from_str(&s).ok())
@@ -946,6 +946,7 @@ mod tests {
946946
config.scheduled_delay,
947947
Duration::from_millis(OTEL_BLRP_SCHEDULE_DELAY_DEFAULT)
948948
);
949+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
949950
assert_eq!(
950951
config.max_export_timeout,
951952
Duration::from_millis(OTEL_BLRP_EXPORT_TIMEOUT_DEFAULT)
@@ -969,6 +970,7 @@ mod tests {
969970
let config = temp_env::with_vars(env_vars, BatchConfig::default);
970971

971972
assert_eq!(config.scheduled_delay, Duration::from_millis(2000));
973+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
972974
assert_eq!(config.max_export_timeout, Duration::from_millis(60000));
973975
assert_eq!(config.max_queue_size, 4096);
974976
assert_eq!(config.max_export_batch_size, 1024);
@@ -989,6 +991,7 @@ mod tests {
989991
config.scheduled_delay,
990992
Duration::from_millis(OTEL_BLRP_SCHEDULE_DELAY_DEFAULT)
991993
);
994+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
992995
assert_eq!(
993996
config.max_export_timeout,
994997
Duration::from_millis(OTEL_BLRP_EXPORT_TIMEOUT_DEFAULT)
@@ -997,15 +1000,18 @@ mod tests {
9971000

9981001
#[test]
9991002
fn test_batch_config_with_fields() {
1000-
let batch = BatchConfigBuilder::default()
1003+
let batch_builder = BatchConfigBuilder::default()
10011004
.with_max_export_batch_size(1)
10021005
.with_scheduled_delay(Duration::from_millis(2))
1003-
.with_max_export_timeout(Duration::from_millis(3))
1004-
.with_max_queue_size(4)
1005-
.build();
1006+
.with_max_queue_size(4);
1007+
1008+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
1009+
let batch_builder = batch_builder.with_max_export_timeout(Duration::from_millis(3));
1010+
let batch = batch_builder.build();
10061011

10071012
assert_eq!(batch.max_export_batch_size, 1);
10081013
assert_eq!(batch.scheduled_delay, Duration::from_millis(2));
1014+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
10091015
assert_eq!(batch.max_export_timeout, Duration::from_millis(3));
10101016
assert_eq!(batch.max_queue_size, 4);
10111017
}
@@ -1029,6 +1035,8 @@ mod tests {
10291035
builder.config.max_queue_size,
10301036
OTEL_BLRP_MAX_QUEUE_SIZE_DEFAULT
10311037
);
1038+
1039+
#[cfg(feature = "experimental_logs_batch_log_processor_with_async_runtime")]
10321040
assert_eq!(
10331041
builder.config.max_export_timeout,
10341042
Duration::from_millis(2046)
@@ -1049,7 +1057,6 @@ mod tests {
10491057
let expected = BatchConfigBuilder::default()
10501058
.with_max_export_batch_size(1)
10511059
.with_scheduled_delay(Duration::from_millis(2))
1052-
.with_max_export_timeout(Duration::from_millis(3))
10531060
.with_max_queue_size(4)
10541061
.build();
10551062

@@ -1059,7 +1066,6 @@ mod tests {
10591066
let actual = &builder.config;
10601067
assert_eq!(actual.max_export_batch_size, 1);
10611068
assert_eq!(actual.scheduled_delay, Duration::from_millis(2));
1062-
assert_eq!(actual.max_export_timeout, Duration::from_millis(3));
10631069
assert_eq!(actual.max_queue_size, 4);
10641070
}
10651071

0 commit comments

Comments
 (0)