Skip to content

Commit fa867e9

Browse files
committed
test(rust): execute logging / tracing tests as integration tests
Those tests need to be isolated since they set some global exporters
1 parent bb12f89 commit fa867e9

File tree

8 files changed

+208
-205
lines changed

8 files changed

+208
-205
lines changed

implementations/rust/ockam/ockam_api/src/cli_state/cli_state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl CliState {
155155
/// Low-level functions for creating / deleting CliState files
156156
impl CliState {
157157
/// Create a new CliState where the data is stored at a given path
158-
pub(super) async fn create(dir: PathBuf) -> Result<Self> {
158+
pub async fn create(dir: PathBuf) -> Result<Self> {
159159
std::fs::create_dir_all(&dir)?;
160160
let database = SqlxDatabase::create(Self::make_database_path(&dir)).await?;
161161
let application_database = SqlxDatabase::create_with_migration(

implementations/rust/ockam/ockam_api/src/cli_state/journeys/journeys.rs

-79
Original file line numberDiff line numberDiff line change
@@ -167,82 +167,3 @@ impl CliState {
167167
(opentelemetry_context, now)
168168
}
169169
}
170-
171-
#[cfg(test)]
172-
mod tests {
173-
use super::*;
174-
use crate::logs::{LoggingConfiguration, LoggingTracing};
175-
use crate::random_name;
176-
use ockam_node::Executor;
177-
use opentelemetry::trace::FutureExt;
178-
use opentelemetry_sdk::testing::logs::InMemoryLogsExporter;
179-
use opentelemetry_sdk::testing::trace::InMemorySpanExporter;
180-
use tempfile::NamedTempFile;
181-
182-
#[test]
183-
fn test_create_journey_event() {
184-
let spans_exporter = InMemorySpanExporter::default();
185-
let logs_exporter = InMemoryLogsExporter::default();
186-
187-
let tracing_guard = LoggingTracing::setup_with_exporters(
188-
spans_exporter.clone(),
189-
logs_exporter.clone(),
190-
None,
191-
LoggingConfiguration::off().set_crates(&["ockam_api"]),
192-
"test",
193-
);
194-
let tracer = global::tracer("ockam-test");
195-
let result = tracer.in_span("user event", |cx| {
196-
let _guard = cx.with_value(Utc::now()).attach();
197-
198-
Executor::execute_future(
199-
async move {
200-
let db_file = NamedTempFile::new().unwrap();
201-
let cli_state_directory = db_file.path().parent().unwrap().join(random_name());
202-
let cli = CliState::create(cli_state_directory)
203-
.await
204-
.unwrap()
205-
.set_tracing_enabled();
206-
207-
let mut map = HashMap::new();
208-
map.insert(USER_EMAIL, "[email protected]");
209-
map.insert(USER_NAME, "eric");
210-
cli.add_journey_event(JourneyEvent::Enrolled, map.clone())
211-
.await
212-
.unwrap();
213-
cli.add_journey_event(JourneyEvent::PortalCreated, map)
214-
.await
215-
.unwrap();
216-
}
217-
.with_current_context(),
218-
)
219-
});
220-
assert!(result.is_ok());
221-
222-
tracing_guard.force_flush();
223-
let mut spans = spans_exporter.get_finished_spans().unwrap();
224-
spans.sort_by_key(|s| s.start_time);
225-
assert_eq!(spans.len(), 4);
226-
227-
let span_names = spans.iter().map(|s| s.name.as_ref()).collect::<Vec<&str>>();
228-
assert_eq!(
229-
span_names,
230-
vec![
231-
"user event",
232-
"start host journey",
233-
"enrolled",
234-
"portal created"
235-
]
236-
);
237-
// remove the first event
238-
spans.remove(0);
239-
240-
// all user events have the same start/end times and have a duration of 1ms
241-
let first_span = spans.first().unwrap().clone();
242-
for span in spans {
243-
assert_eq!(span.start_time, first_span.start_time);
244-
assert_eq!(span.end_time, first_span.end_time);
245-
assert_eq!(span.start_time.add(Duration::from_millis(1)), span.end_time);
246-
}
247-
}
248-
}

implementations/rust/ockam/ockam_api/src/logs/logging_configuration.rs

+35-33
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub struct LoggingConfiguration {
1515
format: LogFormat,
1616
colored: Colored,
1717
log_dir: Option<PathBuf>,
18-
crates: Vec<String>,
18+
crates: Option<Vec<String>>,
1919
}
2020

2121
impl LoggingConfiguration {
@@ -28,7 +28,7 @@ impl LoggingConfiguration {
2828
format: LogFormat,
2929
colored: Colored,
3030
log_dir: Option<PathBuf>,
31-
crates: &[&str],
31+
crates: Option<&[&str]>,
3232
) -> LoggingConfiguration {
3333
LoggingConfiguration {
3434
level,
@@ -38,7 +38,7 @@ impl LoggingConfiguration {
3838
format,
3939
colored,
4040
log_dir,
41-
crates: crates.iter().map(|c| c.to_string()).collect(),
41+
crates: crates.map(|cs| cs.iter().map(|c| c.to_string()).collect()),
4242
}
4343
}
4444

@@ -70,7 +70,7 @@ impl LoggingConfiguration {
7070
self.log_dir.clone()
7171
}
7272

73-
pub fn crates(&self) -> Vec<String> {
73+
pub fn crates(&self) -> Option<Vec<String>> {
7474
self.crates.clone()
7575
}
7676

@@ -83,22 +83,27 @@ impl LoggingConfiguration {
8383

8484
pub fn set_crates(self, crates: &[&str]) -> LoggingConfiguration {
8585
LoggingConfiguration {
86-
crates: crates.iter().map(|c| c.to_string()).collect(),
86+
crates: Some(crates.iter().map(|c| c.to_string()).collect()),
8787
..self
8888
}
8989
}
9090

9191
pub fn env_filter(&self) -> EnvFilter {
92-
let builder = EnvFilter::builder();
93-
builder
94-
.with_default_directive(self.level().into())
95-
.parse_lossy(
96-
self.crates()
97-
.iter()
98-
.map(|c| format!("{c}={}", self.level()))
99-
.collect::<Vec<_>>()
100-
.join(","),
101-
)
92+
match &self.crates {
93+
Some(crates) => {
94+
let builder = EnvFilter::builder();
95+
builder
96+
.with_default_directive(self.level().into())
97+
.parse_lossy(
98+
crates
99+
.iter()
100+
.map(|c| format!("{c}={}", self.level()))
101+
.collect::<Vec<_>>()
102+
.join(","),
103+
)
104+
}
105+
None => EnvFilter::default().add_directive(self.level.into()),
106+
}
102107
}
103108

104109
pub fn off() -> LoggingConfiguration {
@@ -110,7 +115,7 @@ impl LoggingConfiguration {
110115
LogFormat::Default,
111116
Colored::Off,
112117
None,
113-
&[],
118+
None,
114119
)
115120
}
116121

@@ -123,20 +128,20 @@ impl LoggingConfiguration {
123128
log_format(),
124129
Colored::Off,
125130
log_dir,
126-
crates,
131+
Some(crates),
127132
)
128133
}
129134

130-
fn default_crates() -> Vec<String> {
131-
vec![
132-
"ockam".to_string(),
133-
"ockam_node".to_string(),
134-
"ockam_core".to_string(),
135-
"ockam_vault".to_string(),
136-
"ockam_identity".to_string(),
137-
"ockam_transport_tcp".to_string(),
138-
"ockam_api".to_string(),
139-
"ockam_command".to_string(),
135+
pub fn default_crates() -> &'static [&'static str] {
136+
&[
137+
"ockam",
138+
"ockam_node",
139+
"ockam_core",
140+
"ockam_vault",
141+
"ockam_identity",
142+
"ockam_transport_tcp",
143+
"ockam_api",
144+
"ockam_command",
140145
]
141146
}
142147
}
@@ -151,10 +156,7 @@ impl Default for LoggingConfiguration {
151156
LogFormat::Default,
152157
Colored::Off,
153158
None,
154-
&LoggingConfiguration::default_crates()
155-
.iter()
156-
.map(|c| c.as_str())
157-
.collect::<Vec<&str>>(),
159+
None,
158160
)
159161
}
160162
}
@@ -225,7 +227,7 @@ pub fn new_logging_configuration(
225227
log_format(),
226228
colored,
227229
log_dir,
228-
crates,
230+
Some(crates),
229231
)
230232
}
231233

@@ -275,7 +277,7 @@ fn legacy_logging_configuration(
275277
format: log_format(),
276278
colored,
277279
log_dir,
278-
crates: crates.iter().map(|c| c.to_string()).collect(),
280+
crates: Some(crates.iter().map(|c| c.to_string()).collect()),
279281
})
280282
}
281283

implementations/rust/ockam/ockam_api/src/logs/setup.rs

-80
Original file line numberDiff line numberDiff line change
@@ -334,86 +334,6 @@ impl std::fmt::Display for LogFormat {
334334
}
335335
}
336336

337-
#[cfg(test)]
338-
mod tests {
339-
use crate::logs::{LoggingConfiguration, LoggingTracing};
340-
use crate::random_name;
341-
use opentelemetry::global;
342-
use opentelemetry::trace::Tracer;
343-
use opentelemetry_sdk::{self as sdk};
344-
use sdk::testing::logs::*;
345-
use sdk::testing::trace::*;
346-
use std::fs;
347-
use tempfile::NamedTempFile;
348-
349-
#[test]
350-
fn test_log_and_traces() {
351-
let temp_file = NamedTempFile::new().unwrap();
352-
let log_directory = &temp_file.path().parent().unwrap().join(random_name());
353-
354-
let spans_exporter = InMemorySpanExporter::default();
355-
let logs_exporter = InMemoryLogsExporter::default();
356-
let ockam_crates = &["ockam_api"];
357-
let guard = LoggingTracing::setup_with_exporters(
358-
spans_exporter.clone(),
359-
logs_exporter.clone(),
360-
None,
361-
LoggingConfiguration::default()
362-
.set_log_directory(log_directory.into())
363-
.set_crates(ockam_crates),
364-
"test",
365-
);
366-
367-
let tracer = global::tracer("ockam-test");
368-
tracer.in_span("Logging::test", |_| {
369-
info!("inside span");
370-
error!("something went wrong!");
371-
});
372-
373-
// check that the spans are exported
374-
guard.force_flush();
375-
let spans = spans_exporter.get_finished_spans().unwrap();
376-
assert_eq!(spans.len(), 1);
377-
let parent_span = spans.first().unwrap();
378-
379-
// check that log records are exported
380-
let logs = logs_exporter.get_emitted_logs().unwrap();
381-
assert_eq!(logs.len(), 2);
382-
for log in logs {
383-
assert_eq!(
384-
log.clone().record.trace_context.map(|tc| tc.trace_id),
385-
Some(parent_span.span_context.trace_id()),
386-
"{log:?}\n{parent_span:?}"
387-
)
388-
}
389-
390-
// read the content of the log file to make sure that log messages are there
391-
let mut stdout_file_checked = false;
392-
for file in fs::read_dir(log_directory).unwrap() {
393-
let file_path = file.unwrap().path();
394-
if file_path.to_string_lossy().contains("stdout") {
395-
let contents = fs::read_to_string(file_path).unwrap();
396-
assert!(
397-
contents.contains("INFO ockam_api::logs::setup::tests: inside span"),
398-
"{:?}",
399-
contents
400-
);
401-
assert!(
402-
contents.contains("ERROR ockam_api::logs::setup::tests: something went wrong!"),
403-
"{:?}",
404-
contents
405-
);
406-
stdout_file_checked = true
407-
}
408-
}
409-
410-
assert!(
411-
stdout_file_checked,
412-
"the stdout log file must have been found and checked"
413-
)
414-
}
415-
}
416-
417337
#[derive(Debug)]
418338
struct DecoratedLogExporter<L: LogExporter> {
419339
exporter: L,

0 commit comments

Comments
 (0)