opentelemetry_sdk/logs/
mod.rs

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