opentelemetry_sdk/logs/
mod.rs

1//! # OpenTelemetry Log SDK
2
3mod log_emitter;
4mod log_processor;
5mod record;
6
7pub use log_emitter::{Builder, Logger, LoggerProvider};
8pub use log_processor::{
9    BatchConfig, BatchConfigBuilder, BatchLogProcessor, BatchLogProcessorBuilder, LogProcessor,
10    SimpleLogProcessor,
11};
12pub use record::{LogRecord, TraceContext};
13
14#[cfg(all(test, feature = "testing"))]
15mod tests {
16    use super::*;
17    use crate::testing::logs::InMemoryLogsExporter;
18    use crate::Resource;
19    use opentelemetry::logs::LogRecord;
20    use opentelemetry::logs::{Logger, LoggerProvider as _, Severity};
21    use opentelemetry::{logs::AnyValue, Key, KeyValue};
22    use std::borrow::Borrow;
23    use std::collections::HashMap;
24
25    #[test]
26    fn logging_sdk_test() {
27        // Arrange
28        let resource = Resource::new(vec![
29            KeyValue::new("k1", "v1"),
30            KeyValue::new("k2", "v2"),
31            KeyValue::new("k3", "v3"),
32            KeyValue::new("k4", "v4"),
33        ]);
34        let exporter: InMemoryLogsExporter = InMemoryLogsExporter::default();
35        let logger_provider = LoggerProvider::builder()
36            .with_resource(resource.clone())
37            .with_log_processor(SimpleLogProcessor::new(Box::new(exporter.clone())))
38            .build();
39
40        // Act
41        let logger = logger_provider.logger("test-logger");
42        let mut log_record = logger.create_log_record();
43        log_record.set_severity_number(Severity::Error);
44        log_record.set_severity_text("Error".into());
45
46        // Adding attributes using a vector with explicitly constructed Key and AnyValue objects.
47        log_record.add_attributes(vec![
48            (Key::new("key1"), AnyValue::from("value1")),
49            (Key::new("key2"), AnyValue::from("value2")),
50        ]);
51
52        // Adding attributes using an array with explicitly constructed Key and AnyValue objects.
53        log_record.add_attributes([
54            (Key::new("key3"), AnyValue::from("value3")),
55            (Key::new("key4"), AnyValue::from("value4")),
56        ]);
57
58        // Adding attributes using a vector with tuple auto-conversion to Key and AnyValue.
59        log_record.add_attributes(vec![("key5", "value5"), ("key6", "value6")]);
60
61        // Adding attributes using an array with tuple auto-conversion to Key and AnyValue.
62        log_record.add_attributes([("key7", "value7"), ("key8", "value8")]);
63
64        // Adding Attributes from a HashMap
65        let mut attributes_map = HashMap::new();
66        attributes_map.insert("key9", "value9");
67        attributes_map.insert("key10", "value10");
68
69        log_record.add_attributes(attributes_map);
70
71        logger.emit(log_record);
72
73        // Assert
74        let exported_logs = exporter
75            .get_emitted_logs()
76            .expect("Logs are expected to be exported.");
77        assert_eq!(exported_logs.len(), 1);
78        let log = exported_logs
79            .first()
80            .expect("Atleast one log is expected to be present.");
81        assert_eq!(log.instrumentation.name, "test-logger");
82        assert_eq!(log.record.severity_number, Some(Severity::Error));
83        let attributes: Vec<(Key, AnyValue)> = log
84            .record
85            .attributes
86            .clone()
87            .expect("Attributes are expected");
88        assert_eq!(attributes.len(), 10);
89        for i in 1..=10 {
90            assert!(log.record.attributes.clone().unwrap().contains(&(
91                Key::new(format!("key{}", i)),
92                AnyValue::String(format!("value{}", i).into())
93            )));
94        }
95
96        // validate Resource
97        assert_eq!(&resource, log.resource.borrow());
98    }
99
100    #[test]
101    fn logger_attributes() {
102        let provider = LoggerProvider::builder().build();
103        let logger = provider
104            .logger_builder("test_logger")
105            .with_schema_url("https://opentelemetry.io/schema/1.0.0")
106            .with_attributes(vec![(KeyValue::new("test_k", "test_v"))])
107            .build();
108        let instrumentation_library = logger.instrumentation_library();
109        let attributes = &instrumentation_library.attributes;
110        assert_eq!(instrumentation_library.name, "test_logger");
111        assert_eq!(
112            instrumentation_library.schema_url,
113            Some("https://opentelemetry.io/schema/1.0.0".into())
114        );
115        assert_eq!(attributes.len(), 1);
116        assert_eq!(attributes[0].key, "test_k".into());
117        assert_eq!(attributes[0].value, "test_v".into());
118    }
119
120    #[test]
121    #[allow(deprecated)]
122    fn versioned_logger_options() {
123        let provider = LoggerProvider::builder().build();
124        let logger = provider.versioned_logger(
125            "test_logger",
126            Some("v1.2.3".into()),
127            Some("https://opentelemetry.io/schema/1.0.0".into()),
128            Some(vec![(KeyValue::new("test_k", "test_v"))]),
129        );
130        let instrumentation_library = logger.instrumentation_library();
131        let attributes = &instrumentation_library.attributes;
132        assert_eq!(instrumentation_library.version, Some("v1.2.3".into()));
133        assert_eq!(
134            instrumentation_library.schema_url,
135            Some("https://opentelemetry.io/schema/1.0.0".into())
136        );
137        assert_eq!(attributes.len(), 1);
138        assert_eq!(attributes[0].key, "test_k".into());
139        assert_eq!(attributes[0].value, "test_v".into());
140    }
141}