1use log::{Level, Metadata, Record};
114use opentelemetry::{
115 logs::{AnyValue, LogRecord, Logger, LoggerProvider, Severity},
116 Key,
117};
118#[cfg(feature = "experimental_metadata_attributes")]
119use opentelemetry_semantic_conventions::attribute::{
120 CODE_FILE_PATH, CODE_FUNCTION_NAME, CODE_LINE_NUMBER,
121};
122
123pub struct OpenTelemetryLogBridge<P, L>
124where
125 P: LoggerProvider<Logger = L> + Send + Sync,
126 L: Logger + Send + Sync,
127{
128 logger: L,
129 _phantom: std::marker::PhantomData<P>, }
131
132impl<P, L> log::Log for OpenTelemetryLogBridge<P, L>
133where
134 P: LoggerProvider<Logger = L> + Send + Sync,
135 L: Logger + Send + Sync,
136{
137 fn enabled(&self, _metadata: &Metadata) -> bool {
138 #[cfg(feature = "spec_unstable_logs_enabled")]
139 return self.logger.event_enabled(
140 severity_of_level(_metadata.level()),
141 _metadata.target(),
142 None,
143 );
144 #[cfg(not(feature = "spec_unstable_logs_enabled"))]
145 true
146 }
147
148 fn log(&self, record: &Record) {
149 if self.enabled(record.metadata()) {
150 let mut log_record = self.logger.create_log_record();
151 log_record.set_severity_number(severity_of_level(record.level()));
152 log_record.set_severity_text(record.level().as_str());
153 log_record.set_body(AnyValue::from(record.args().to_string()));
154
155 #[cfg(feature = "experimental_metadata_attributes")]
156 {
157 if let Some(filepath) = record.file() {
158 log_record.add_attribute(
159 Key::new(CODE_FILE_PATH),
160 AnyValue::from(filepath.to_string()),
161 );
162 }
163
164 if let Some(line_no) = record.line() {
165 log_record.add_attribute(Key::new(CODE_LINE_NUMBER), AnyValue::from(line_no));
166 }
167
168 if let Some(module) = record.module_path() {
169 log_record.add_attribute(
170 Key::new(CODE_FUNCTION_NAME),
171 AnyValue::from(module.to_string()),
172 );
173 }
174 }
175
176 log_record.add_attributes(log_attributes(record.key_values()));
177 log_record.set_target(record.metadata().target().to_string());
178
179 self.logger.emit(log_record);
180 }
181 }
182
183 fn flush(&self) {}
184}
185
186impl<P, L> OpenTelemetryLogBridge<P, L>
187where
188 P: LoggerProvider<Logger = L> + Send + Sync,
189 L: Logger + Send + Sync,
190{
191 pub fn new(provider: &P) -> Self {
192 Self {
193 logger: provider.logger(""),
199 _phantom: Default::default(),
200 }
201 }
202}
203
204const fn severity_of_level(level: Level) -> Severity {
205 match level {
206 Level::Error => Severity::Error,
207 Level::Warn => Severity::Warn,
208 Level::Info => Severity::Info,
209 Level::Debug => Severity::Debug,
210 Level::Trace => Severity::Trace,
211 }
212}
213
214fn log_attributes(kvs: impl log::kv::Source) -> Vec<(Key, AnyValue)> {
215 struct AttributeVisitor(Vec<(Key, AnyValue)>);
216
217 impl<'kvs> log::kv::VisitSource<'kvs> for AttributeVisitor {
218 fn visit_pair(
219 &mut self,
220 key: log::kv::Key<'kvs>,
221 value: log::kv::Value<'kvs>,
222 ) -> Result<(), log::kv::Error> {
223 let key = Key::from(String::from(key.as_str()));
224
225 if let Some(value) = any_value::serialize(value) {
226 self.0.push((key, value));
227 }
228
229 Ok(())
230 }
231 }
232
233 let mut visitor = AttributeVisitor(Vec::new());
234
235 let _ = kvs.visit(&mut visitor);
236
237 visitor.0
238}
239
240#[cfg(not(feature = "with-serde"))]
241mod any_value {
242 use opentelemetry::{logs::AnyValue, StringValue};
243
244 pub(crate) fn serialize(value: log::kv::Value) -> Option<AnyValue> {
245 struct ValueVisitor(Option<AnyValue>);
246
247 impl log::kv::VisitValue<'_> for ValueVisitor {
248 fn visit_any(&mut self, value: log::kv::Value) -> Result<(), log::kv::Error> {
249 self.0 = Some(AnyValue::String(StringValue::from(value.to_string())));
250
251 Ok(())
252 }
253
254 fn visit_bool(&mut self, value: bool) -> Result<(), log::kv::Error> {
255 self.0 = Some(AnyValue::Boolean(value));
256
257 Ok(())
258 }
259
260 fn visit_str(&mut self, value: &str) -> Result<(), log::kv::Error> {
261 self.0 = Some(AnyValue::String(StringValue::from(value.to_owned())));
262
263 Ok(())
264 }
265
266 fn visit_i64(&mut self, value: i64) -> Result<(), log::kv::Error> {
267 self.0 = Some(AnyValue::Int(value));
268
269 Ok(())
270 }
271
272 fn visit_u64(&mut self, value: u64) -> Result<(), log::kv::Error> {
273 if let Ok(value) = value.try_into() {
274 self.visit_i64(value)
275 } else {
276 self.visit_any(log::kv::Value::from(value))
277 }
278 }
279
280 fn visit_i128(&mut self, value: i128) -> Result<(), log::kv::Error> {
281 if let Ok(value) = value.try_into() {
282 self.visit_i64(value)
283 } else {
284 self.visit_any(log::kv::Value::from(value))
285 }
286 }
287
288 fn visit_u128(&mut self, value: u128) -> Result<(), log::kv::Error> {
289 if let Ok(value) = value.try_into() {
290 self.visit_i64(value)
291 } else {
292 self.visit_any(log::kv::Value::from(value))
293 }
294 }
295
296 fn visit_f64(&mut self, value: f64) -> Result<(), log::kv::Error> {
297 self.0 = Some(AnyValue::Double(value));
298
299 Ok(())
300 }
301 }
302
303 let mut visitor = ValueVisitor(None);
304 value.visit(&mut visitor).unwrap();
305 visitor.0
306 }
307}
308
309#[cfg(feature = "with-serde")]
311mod any_value {
312 use std::{collections::HashMap, fmt};
313
314 use opentelemetry::{logs::AnyValue, Key, StringValue};
315 use serde::ser::{
316 Error, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
317 SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer, StdError,
318 };
319
320 pub(crate) fn serialize(value: impl serde::Serialize) -> Option<AnyValue> {
329 value.serialize(ValueSerializer).ok()?
330 }
331
332 struct ValueSerializer;
333
334 struct ValueSerializeSeq {
335 value: Vec<AnyValue>,
336 }
337
338 struct ValueSerializeTuple {
339 value: Vec<AnyValue>,
340 }
341
342 struct ValueSerializeTupleStruct {
343 value: Vec<AnyValue>,
344 }
345
346 struct ValueSerializeMap {
347 key: Option<Key>,
348 value: HashMap<Key, AnyValue>,
349 }
350
351 struct ValueSerializeStruct {
352 value: HashMap<Key, AnyValue>,
353 }
354
355 struct ValueSerializeTupleVariant {
356 variant: &'static str,
357 value: Vec<AnyValue>,
358 }
359
360 struct ValueSerializeStructVariant {
361 variant: &'static str,
362 value: HashMap<Key, AnyValue>,
363 }
364
365 #[derive(Debug)]
366 struct ValueError(String);
367
368 impl fmt::Display for ValueError {
369 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
370 fmt::Display::fmt(&self.0, f)
371 }
372 }
373
374 impl Error for ValueError {
375 fn custom<T>(msg: T) -> Self
376 where
377 T: fmt::Display,
378 {
379 ValueError(msg.to_string())
380 }
381 }
382
383 impl StdError for ValueError {}
384
385 impl Serializer for ValueSerializer {
386 type Ok = Option<AnyValue>;
387
388 type Error = ValueError;
389
390 type SerializeSeq = ValueSerializeSeq;
391
392 type SerializeTuple = ValueSerializeTuple;
393
394 type SerializeTupleStruct = ValueSerializeTupleStruct;
395
396 type SerializeTupleVariant = ValueSerializeTupleVariant;
397
398 type SerializeMap = ValueSerializeMap;
399
400 type SerializeStruct = ValueSerializeStruct;
401
402 type SerializeStructVariant = ValueSerializeStructVariant;
403
404 fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
405 Ok(Some(AnyValue::Boolean(v)))
406 }
407
408 fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
409 self.serialize_i64(v as i64)
410 }
411
412 fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
413 self.serialize_i64(v as i64)
414 }
415
416 fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
417 self.serialize_i64(v as i64)
418 }
419
420 fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
421 Ok(Some(AnyValue::Int(v)))
422 }
423
424 fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
425 if let Ok(v) = v.try_into() {
426 self.serialize_i64(v)
427 } else {
428 self.collect_str(&v)
429 }
430 }
431
432 fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
433 self.serialize_i64(v as i64)
434 }
435
436 fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
437 self.serialize_i64(v as i64)
438 }
439
440 fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
441 self.serialize_i64(v as i64)
442 }
443
444 fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
445 if let Ok(v) = v.try_into() {
446 self.serialize_i64(v)
447 } else {
448 self.collect_str(&v)
449 }
450 }
451
452 fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
453 if let Ok(v) = v.try_into() {
454 self.serialize_i64(v)
455 } else {
456 self.collect_str(&v)
457 }
458 }
459
460 fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
461 self.serialize_f64(v as f64)
462 }
463
464 fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
465 Ok(Some(AnyValue::Double(v)))
466 }
467
468 fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
469 self.collect_str(&v)
470 }
471
472 fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
473 Ok(Some(AnyValue::String(StringValue::from(v.to_owned()))))
474 }
475
476 fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
477 Ok(Some(AnyValue::Bytes(Box::new(v.to_owned()))))
478 }
479
480 fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
481 Ok(None)
482 }
483
484 fn serialize_some<T: serde::Serialize + ?Sized>(
485 self,
486 value: &T,
487 ) -> Result<Self::Ok, Self::Error> {
488 value.serialize(self)
489 }
490
491 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
492 Ok(None)
493 }
494
495 fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
496 name.serialize(self)
497 }
498
499 fn serialize_unit_variant(
500 self,
501 _: &'static str,
502 _: u32,
503 variant: &'static str,
504 ) -> Result<Self::Ok, Self::Error> {
505 variant.serialize(self)
506 }
507
508 fn serialize_newtype_struct<T: serde::Serialize + ?Sized>(
509 self,
510 _: &'static str,
511 value: &T,
512 ) -> Result<Self::Ok, Self::Error> {
513 value.serialize(self)
514 }
515
516 fn serialize_newtype_variant<T: serde::Serialize + ?Sized>(
517 self,
518 _: &'static str,
519 _: u32,
520 variant: &'static str,
521 value: &T,
522 ) -> Result<Self::Ok, Self::Error> {
523 let mut map = self.serialize_map(Some(1))?;
524 map.serialize_entry(variant, value)?;
525 map.end()
526 }
527
528 fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
529 Ok(ValueSerializeSeq { value: Vec::new() })
530 }
531
532 fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
533 Ok(ValueSerializeTuple { value: Vec::new() })
534 }
535
536 fn serialize_tuple_struct(
537 self,
538 _: &'static str,
539 _: usize,
540 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
541 Ok(ValueSerializeTupleStruct { value: Vec::new() })
542 }
543
544 fn serialize_tuple_variant(
545 self,
546 _: &'static str,
547 _: u32,
548 variant: &'static str,
549 _: usize,
550 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
551 Ok(ValueSerializeTupleVariant {
552 variant,
553 value: Vec::new(),
554 })
555 }
556
557 fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
558 Ok(ValueSerializeMap {
559 key: None,
560 value: HashMap::new(),
561 })
562 }
563
564 fn serialize_struct(
565 self,
566 _: &'static str,
567 _: usize,
568 ) -> Result<Self::SerializeStruct, Self::Error> {
569 Ok(ValueSerializeStruct {
570 value: HashMap::new(),
571 })
572 }
573
574 fn serialize_struct_variant(
575 self,
576 _: &'static str,
577 _: u32,
578 variant: &'static str,
579 _: usize,
580 ) -> Result<Self::SerializeStructVariant, Self::Error> {
581 Ok(ValueSerializeStructVariant {
582 variant,
583 value: HashMap::new(),
584 })
585 }
586 }
587
588 impl SerializeSeq for ValueSerializeSeq {
589 type Ok = Option<AnyValue>;
590
591 type Error = ValueError;
592
593 fn serialize_element<T: serde::Serialize + ?Sized>(
594 &mut self,
595 value: &T,
596 ) -> Result<(), Self::Error> {
597 if let Some(value) = value.serialize(ValueSerializer)? {
598 self.value.push(value);
599 }
600
601 Ok(())
602 }
603
604 fn end(self) -> Result<Self::Ok, Self::Error> {
605 Ok(Some(AnyValue::ListAny(Box::new(self.value))))
606 }
607 }
608
609 impl SerializeTuple for ValueSerializeTuple {
610 type Ok = Option<AnyValue>;
611
612 type Error = ValueError;
613
614 fn serialize_element<T: serde::Serialize + ?Sized>(
615 &mut self,
616 value: &T,
617 ) -> Result<(), Self::Error> {
618 if let Some(value) = value.serialize(ValueSerializer)? {
619 self.value.push(value);
620 }
621
622 Ok(())
623 }
624
625 fn end(self) -> Result<Self::Ok, Self::Error> {
626 Ok(Some(AnyValue::ListAny(Box::new(self.value))))
627 }
628 }
629
630 impl SerializeTupleStruct for ValueSerializeTupleStruct {
631 type Ok = Option<AnyValue>;
632
633 type Error = ValueError;
634
635 fn serialize_field<T: serde::Serialize + ?Sized>(
636 &mut self,
637 value: &T,
638 ) -> Result<(), Self::Error> {
639 if let Some(value) = value.serialize(ValueSerializer)? {
640 self.value.push(value);
641 }
642
643 Ok(())
644 }
645
646 fn end(self) -> Result<Self::Ok, Self::Error> {
647 Ok(Some(AnyValue::ListAny(Box::new(self.value))))
648 }
649 }
650
651 impl SerializeTupleVariant for ValueSerializeTupleVariant {
652 type Ok = Option<AnyValue>;
653
654 type Error = ValueError;
655
656 fn serialize_field<T: serde::Serialize + ?Sized>(
657 &mut self,
658 value: &T,
659 ) -> Result<(), Self::Error> {
660 if let Some(value) = value.serialize(ValueSerializer)? {
661 self.value.push(value);
662 }
663
664 Ok(())
665 }
666
667 fn end(self) -> Result<Self::Ok, Self::Error> {
668 Ok(Some(AnyValue::Map({
669 let mut variant = Box::<HashMap<Key, AnyValue>>::default();
670 variant.insert(
671 Key::from(self.variant),
672 AnyValue::ListAny(Box::new(self.value)),
673 );
674 variant
675 })))
676 }
677 }
678
679 impl SerializeMap for ValueSerializeMap {
680 type Ok = Option<AnyValue>;
681
682 type Error = ValueError;
683
684 fn serialize_key<T: serde::Serialize + ?Sized>(
685 &mut self,
686 key: &T,
687 ) -> Result<(), Self::Error> {
688 let key = match key.serialize(ValueSerializer)? {
689 Some(AnyValue::String(key)) => Key::from(String::from(key)),
690 key => Key::from(format!("{key:?}")),
691 };
692
693 self.key = Some(key);
694
695 Ok(())
696 }
697
698 fn serialize_value<T: serde::Serialize + ?Sized>(
699 &mut self,
700 value: &T,
701 ) -> Result<(), Self::Error> {
702 let key = self
703 .key
704 .take()
705 .ok_or_else(|| Self::Error::custom("missing key"))?;
706
707 if let Some(value) = value.serialize(ValueSerializer)? {
708 self.value.insert(key, value);
709 }
710
711 Ok(())
712 }
713
714 fn end(self) -> Result<Self::Ok, Self::Error> {
715 Ok(Some(AnyValue::Map(Box::new(self.value))))
716 }
717 }
718
719 impl SerializeStruct for ValueSerializeStruct {
720 type Ok = Option<AnyValue>;
721
722 type Error = ValueError;
723
724 fn serialize_field<T: serde::Serialize + ?Sized>(
725 &mut self,
726 key: &'static str,
727 value: &T,
728 ) -> Result<(), Self::Error> {
729 let key = Key::from(key);
730
731 if let Some(value) = value.serialize(ValueSerializer)? {
732 self.value.insert(key, value);
733 }
734
735 Ok(())
736 }
737
738 fn end(self) -> Result<Self::Ok, Self::Error> {
739 Ok(Some(AnyValue::Map(Box::new(self.value))))
740 }
741 }
742
743 impl SerializeStructVariant for ValueSerializeStructVariant {
744 type Ok = Option<AnyValue>;
745
746 type Error = ValueError;
747
748 fn serialize_field<T: serde::Serialize + ?Sized>(
749 &mut self,
750 key: &'static str,
751 value: &T,
752 ) -> Result<(), Self::Error> {
753 let key = Key::from(key);
754
755 if let Some(value) = value.serialize(ValueSerializer)? {
756 self.value.insert(key, value);
757 }
758
759 Ok(())
760 }
761
762 fn end(self) -> Result<Self::Ok, Self::Error> {
763 Ok(Some(AnyValue::Map({
764 let mut variant = Box::<HashMap<Key, AnyValue>>::default();
765 variant.insert(Key::from(self.variant), AnyValue::Map(Box::new(self.value)));
766 variant
767 })))
768 }
769 }
770}
771
772#[cfg(test)]
773mod tests {
774 use super::OpenTelemetryLogBridge;
775
776 use opentelemetry::{logs::AnyValue, StringValue};
777 use opentelemetry_sdk::{logs::InMemoryLogExporter, logs::SdkLoggerProvider};
778
779 use log::Log;
780
781 #[test]
782 fn logbridge_with_default_metadata_is_enabled() {
783 let exporter = InMemoryLogExporter::default();
784
785 let logger_provider = SdkLoggerProvider::builder()
786 .with_simple_exporter(exporter)
787 .build();
788
789 let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
790
791 #[cfg(feature = "spec_unstable_logs_enabled")]
795 assert!(otel_log_appender.enabled(&log::Metadata::builder().build()));
796 #[cfg(not(feature = "spec_unstable_logs_enabled"))]
797 assert!(otel_log_appender.enabled(&log::Metadata::builder().build()));
798 }
799
800 #[test]
801 fn logbridge_with_record_can_log() {
802 let exporter = InMemoryLogExporter::default();
803
804 let logger_provider = SdkLoggerProvider::builder()
805 .with_simple_exporter(exporter.clone())
806 .build();
807
808 let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
809
810 otel_log_appender.log(
812 &log::RecordBuilder::new()
813 .level(log::Level::Trace)
814 .args(format_args!("TRACE"))
815 .build(),
816 );
817
818 otel_log_appender.log(
820 &log::RecordBuilder::new()
821 .level(log::Level::Debug)
822 .args(format_args!("DEBUG"))
823 .build(),
824 );
825
826 otel_log_appender.log(
828 &log::RecordBuilder::new()
829 .level(log::Level::Info)
830 .args(format_args!("INFO"))
831 .build(),
832 );
833
834 otel_log_appender.log(
836 &log::RecordBuilder::new()
837 .level(log::Level::Warn)
838 .args(format_args!("WARN"))
839 .build(),
840 );
841
842 otel_log_appender.log(
844 &log::RecordBuilder::new()
845 .level(log::Level::Error)
846 .args(format_args!("ERROR"))
847 .build(),
848 );
849
850 let logs = exporter.get_emitted_logs().unwrap();
851
852 assert_eq!(logs.len(), 5);
853 for log in logs {
854 let body: String = match log.record.body().unwrap() {
855 super::AnyValue::String(s) => s.to_string(),
856 _ => panic!("AnyValue::String expected"),
857 };
858 assert_eq!(body, log.record.severity_text().unwrap());
859 }
860 }
861
862 #[test]
863 fn logbridge_attributes() {
864 #[derive(serde::Serialize)]
865 struct Struct {
866 a: i32,
867 b: i32,
868 c: i32,
869 }
870
871 #[derive(serde::Serialize)]
872 struct Newtype(i32);
873
874 #[derive(serde::Serialize)]
875 enum Enum {
876 Unit,
877 Newtype(i32),
878 Struct { a: i32, b: i32, c: i32 },
879 Tuple(i32, i32, i32),
880 }
881
882 struct Bytes<B>(B);
883
884 impl<B: AsRef<[u8]>> serde::Serialize for Bytes<B> {
885 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
886 where
887 S: serde::Serializer,
888 {
889 serializer.serialize_bytes(self.0.as_ref())
890 }
891 }
892
893 struct Map {
894 a: i32,
895 b: i32,
896 c: i32,
897 }
898
899 impl serde::Serialize for Map {
900 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
901 where
902 S: serde::Serializer,
903 {
904 use serde::ser::SerializeMap;
905
906 let mut map = serializer.serialize_map(Some(3))?;
907
908 map.serialize_entry(&"a", &self.a)?;
909 map.serialize_entry(&"b", &self.b)?;
910 map.serialize_entry(&"c", &self.c)?;
911
912 map.end()
913 }
914 }
915
916 let exporter = InMemoryLogExporter::default();
917
918 let logger_provider = SdkLoggerProvider::builder()
919 .with_simple_exporter(exporter.clone())
920 .build();
921
922 let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
923
924 otel_log_appender.log(
925 &log::RecordBuilder::new()
926 .level(log::Level::Info)
927 .args(format_args!("body"))
928 .key_values(&[
929 ("str_value", log::kv::Value::from("a string")),
930 ("u8_value", log::kv::Value::from(1u8)),
931 ("u16_value", log::kv::Value::from(2u16)),
932 ("u32_value", log::kv::Value::from(42u32)),
933 ("u64_value", log::kv::Value::from(2147483660u64)),
934 ("u128_small_value", log::kv::Value::from(2147483660u128)),
935 (
936 "u128_big_value",
937 log::kv::Value::from(9223372036854775820u128),
938 ),
939 ("i8_value", log::kv::Value::from(1i8)),
940 ("i16_value", log::kv::Value::from(2i16)),
941 ("i32_value", log::kv::Value::from(42i32)),
942 ("i64_value", log::kv::Value::from(2147483660i64)),
943 ("i128_small_value", log::kv::Value::from(2147483660i128)),
944 (
945 "i128_big_value",
946 log::kv::Value::from(9223372036854775820i128),
947 ),
948 ("f64_value", log::kv::Value::from(4.2f64)),
949 ("bool_value", log::kv::Value::from(true)),
950 ("bytes_value", log::kv::Value::from_serde(&Bytes([1, 1, 1]))),
951 ("unit_value", log::kv::Value::from_serde(&())),
952 ("some_value", log::kv::Value::from_serde(&Some(42))),
953 ("none_value", log::kv::Value::from_serde(&None::<i32>)),
954 (
955 "slice_value",
956 log::kv::Value::from_serde(&(&[1, 1, 1] as &[i32])),
957 ),
958 (
959 "map_value",
960 log::kv::Value::from_serde(&Map { a: 1, b: 1, c: 1 }),
961 ),
962 (
963 "struct_value",
964 log::kv::Value::from_serde(&Struct { a: 1, b: 1, c: 1 }),
965 ),
966 ("tuple_value", log::kv::Value::from_serde(&(1, 1, 1))),
967 ("newtype_value", log::kv::Value::from_serde(&Newtype(42))),
968 (
969 "unit_variant_value",
970 log::kv::Value::from_serde(&Enum::Unit),
971 ),
972 (
973 "newtype_variant_value",
974 log::kv::Value::from_serde(&Enum::Newtype(42)),
975 ),
976 (
977 "struct_variant_value",
978 log::kv::Value::from_serde(&Enum::Struct { a: 1, b: 1, c: 1 }),
979 ),
980 (
981 "tuple_variant_value",
982 log::kv::Value::from_serde(&Enum::Tuple(1, 1, 1)),
983 ),
984 ])
985 .build(),
986 );
987
988 let logs = exporter.get_emitted_logs().unwrap();
989 assert_eq!(logs.len(), 1);
990
991 let log = logs.first().unwrap();
992 assert_eq!(log.instrumentation.name(), "");
993
994 let get = |needle: &str| -> Option<AnyValue> {
995 log.record.attributes_iter().find_map(|(k, v)| {
996 if k.as_str() == needle {
997 Some(v.clone())
998 } else {
999 None
1000 }
1001 })
1002 };
1003
1004 assert_eq!(
1005 AnyValue::String(StringValue::from("a string")),
1006 get("str_value").unwrap()
1007 );
1008
1009 assert_eq!(AnyValue::Int(1), get("i8_value").unwrap());
1010 assert_eq!(AnyValue::Int(2), get("i16_value").unwrap());
1011 assert_eq!(AnyValue::Int(42), get("i32_value").unwrap());
1012 assert_eq!(AnyValue::Int(2147483660), get("i64_value").unwrap());
1013 assert_eq!(AnyValue::Int(2147483660), get("i128_small_value").unwrap());
1014 assert_eq!(
1015 AnyValue::String(StringValue::from("9223372036854775820")),
1016 get("i128_big_value").unwrap()
1017 );
1018
1019 assert_eq!(AnyValue::Double(4.2), get("f64_value").unwrap());
1020
1021 assert_eq!(AnyValue::Boolean(true), get("bool_value").unwrap());
1022
1023 #[cfg(not(feature = "with-serde"))]
1024 {
1025 assert_eq!(
1026 AnyValue::String(StringValue::from("[1, 1, 1]")),
1027 get("slice_value").unwrap()
1028 );
1029
1030 assert_eq!(
1031 AnyValue::String(StringValue::from("{\"a\": 1, \"b\": 1, \"c\": 1}")),
1032 get("map_value").unwrap()
1033 );
1034
1035 assert_eq!(
1036 AnyValue::String(StringValue::from("Struct { a: 1, b: 1, c: 1 }")),
1037 get("struct_value").unwrap()
1038 );
1039
1040 assert_eq!(
1041 AnyValue::String(StringValue::from("(1, 1, 1)")),
1042 get("tuple_value").unwrap()
1043 );
1044
1045 assert_eq!(
1046 AnyValue::String(StringValue::from("Newtype(42)")),
1047 get("newtype_value").unwrap()
1048 );
1049
1050 assert_eq!(
1051 AnyValue::String(StringValue::from("Unit")),
1052 get("unit_variant_value").unwrap()
1053 );
1054
1055 assert_eq!(
1056 AnyValue::String(StringValue::from("Newtype(42)")),
1057 get("newtype_variant_value").unwrap()
1058 );
1059
1060 assert_eq!(
1061 AnyValue::String(StringValue::from("Struct { a: 1, b: 1, c: 1 }")),
1062 get("struct_variant_value").unwrap()
1063 );
1064
1065 assert_eq!(
1066 AnyValue::String(StringValue::from("Tuple(1, 1, 1)")),
1067 get("tuple_variant_value").unwrap()
1068 );
1069 }
1070 #[cfg(feature = "with-serde")]
1071 {
1072 use opentelemetry::Key;
1073 use std::collections::HashMap;
1074
1075 assert_eq!(None, get("unit_value"));
1076 assert_eq!(None, get("none_value"));
1077 assert_eq!(AnyValue::Int(42), get("some_value").unwrap());
1078
1079 assert_eq!(
1080 AnyValue::ListAny(Box::new(vec![
1081 AnyValue::Int(1),
1082 AnyValue::Int(1),
1083 AnyValue::Int(1)
1084 ])),
1085 get("slice_value").unwrap()
1086 );
1087
1088 assert_eq!(
1089 AnyValue::Map({
1090 let mut map = Box::<HashMap<Key, AnyValue>>::default();
1091
1092 map.insert(Key::from("a"), AnyValue::Int(1));
1093 map.insert(Key::from("b"), AnyValue::Int(1));
1094 map.insert(Key::from("c"), AnyValue::Int(1));
1095
1096 map
1097 }),
1098 get("map_value").unwrap()
1099 );
1100
1101 assert_eq!(
1102 AnyValue::Map({
1103 let mut map = Box::<HashMap<Key, AnyValue>>::default();
1104
1105 map.insert(Key::from("a"), AnyValue::Int(1));
1106 map.insert(Key::from("b"), AnyValue::Int(1));
1107 map.insert(Key::from("c"), AnyValue::Int(1));
1108
1109 map
1110 }),
1111 get("struct_value").unwrap()
1112 );
1113
1114 assert_eq!(
1115 AnyValue::ListAny(Box::new(vec![
1116 AnyValue::Int(1),
1117 AnyValue::Int(1),
1118 AnyValue::Int(1)
1119 ])),
1120 get("tuple_value").unwrap()
1121 );
1122
1123 assert_eq!(
1124 AnyValue::String(StringValue::from("Unit")),
1125 get("unit_variant_value").unwrap()
1126 );
1127
1128 assert_eq!(
1129 AnyValue::Map({
1130 let mut map = HashMap::new();
1131
1132 map.insert(Key::from("Newtype"), AnyValue::Int(42));
1133
1134 Box::new(map)
1135 }),
1136 get("newtype_variant_value").unwrap()
1137 );
1138
1139 assert_eq!(
1140 AnyValue::Map({
1141 let mut map = HashMap::new();
1142
1143 map.insert(
1144 Key::from("Struct"),
1145 AnyValue::Map(Box::new({
1146 let mut map = HashMap::new();
1147 map.insert(Key::from("a"), AnyValue::Int(1));
1148 map.insert(Key::from("b"), AnyValue::Int(1));
1149 map.insert(Key::from("c"), AnyValue::Int(1));
1150 map
1151 })),
1152 );
1153
1154 Box::new(map)
1155 }),
1156 get("struct_variant_value").unwrap()
1157 );
1158
1159 assert_eq!(
1160 AnyValue::Map({
1161 let mut map = HashMap::new();
1162
1163 map.insert(
1164 Key::from("Tuple"),
1165 AnyValue::ListAny(Box::new(vec![
1166 AnyValue::Int(1),
1167 AnyValue::Int(1),
1168 AnyValue::Int(1),
1169 ])),
1170 );
1171
1172 Box::new(map)
1173 }),
1174 get("tuple_variant_value").unwrap()
1175 );
1176 }
1177 }
1178
1179 #[cfg(feature = "experimental_metadata_attributes")]
1180 #[test]
1181 fn logbridge_code_attributes() {
1182 use opentelemetry_semantic_conventions::attribute::{
1183 CODE_FILE_PATH, CODE_FUNCTION_NAME, CODE_LINE_NUMBER,
1184 };
1185
1186 let exporter = InMemoryLogExporter::default();
1187
1188 let logger_provider = SdkLoggerProvider::builder()
1189 .with_simple_exporter(exporter.clone())
1190 .build();
1191
1192 let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
1193
1194 otel_log_appender.log(
1195 &log::RecordBuilder::new()
1196 .level(log::Level::Warn)
1197 .args(format_args!("WARN"))
1198 .file(Some("src/main.rs"))
1199 .module_path(Some("service"))
1200 .line(Some(101))
1201 .build(),
1202 );
1203
1204 let logs = exporter.get_emitted_logs().unwrap();
1205 assert_eq!(logs.len(), 1);
1206
1207 let log = logs.first().unwrap();
1208 assert_eq!(log.instrumentation.name(), "");
1209
1210 let get = |needle: &str| -> Option<AnyValue> {
1211 log.record.attributes_iter().find_map(|(k, v)| {
1212 if k.as_str() == needle {
1213 Some(v.clone())
1214 } else {
1215 None
1216 }
1217 })
1218 };
1219
1220 assert_eq!(
1221 Some(AnyValue::String(StringValue::from("src/main.rs"))),
1222 get(CODE_FILE_PATH)
1223 );
1224 assert_eq!(
1225 Some(AnyValue::String(StringValue::from("service"))),
1226 get(CODE_FUNCTION_NAME)
1227 );
1228 assert_eq!(Some(AnyValue::Int(101)), get(CODE_LINE_NUMBER));
1229 }
1230
1231 #[test]
1232 fn test_flush() {
1233 let exporter = InMemoryLogExporter::default();
1234
1235 let logger_provider = SdkLoggerProvider::builder()
1236 .with_simple_exporter(exporter)
1237 .build();
1238
1239 let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
1240 otel_log_appender.flush();
1241 }
1242
1243 #[test]
1244 fn check_level_severities() {
1245 assert_eq!(
1246 super::severity_of_level(log::Level::Error),
1247 opentelemetry::logs::Severity::Error
1248 );
1249 assert_eq!(
1250 super::severity_of_level(log::Level::Warn),
1251 opentelemetry::logs::Severity::Warn
1252 );
1253 assert_eq!(
1254 super::severity_of_level(log::Level::Info),
1255 opentelemetry::logs::Severity::Info
1256 );
1257 assert_eq!(
1258 super::severity_of_level(log::Level::Debug),
1259 opentelemetry::logs::Severity::Debug
1260 );
1261 assert_eq!(
1262 super::severity_of_level(log::Level::Trace),
1263 opentelemetry::logs::Severity::Trace
1264 );
1265 }
1266}