1use std::{
2 collections::HashMap,
3 convert::{TryFrom, TryInto},
4 fmt::Debug,
5 iter::FromIterator,
6 mem::size_of,
7 num::NonZeroUsize,
8 sync::{Arc, LazyLock},
9};
10
11use bytes::Bytes;
12use chrono::Utc;
13use crossbeam_utils::atomic::AtomicCell;
14use lookup::{PathPrefix, lookup_v2::TargetPath, metadata_path, path};
15use serde::{Deserialize, Serialize, Serializer};
16use vector_common::{
17 EventDataEq,
18 byte_size_of::ByteSizeOf,
19 internal_event::{OptionalTag, TaggedEventsSent},
20 json_size::{JsonSize, NonZeroJsonSize},
21 request_metadata::GetEventCountTags,
22};
23use vrl::{
24 event_path, owned_value_path,
25 path::{OwnedTargetPath, PathParseError, parse_target_path},
26};
27
28use super::{
29 EventFinalizers, Finalizable, KeyString, MergeFinalizable, ObjectMap, Value,
30 estimated_json_encoded_size_of::EstimatedJsonEncodedSizeOf,
31 finalization::{BatchNotifier, EventFinalizer},
32 metadata::EventMetadata,
33 util,
34};
35use crate::{
36 config::{LogNamespace, log_schema, telemetry},
37 event::{
38 MaybeAsLogMut,
39 util::log::{all_fields, all_fields_skip_array_elements, all_metadata_fields},
40 },
41};
42
43static VECTOR_SOURCE_TYPE_PATH: LazyLock<Option<OwnedTargetPath>> = LazyLock::new(|| {
44 Some(OwnedTargetPath::metadata(owned_value_path!(
45 "vector",
46 "source_type"
47 )))
48});
49
50#[derive(Debug, Deserialize)]
51struct Inner {
52 #[serde(flatten)]
53 fields: Value,
54
55 #[serde(skip)]
56 size_cache: AtomicCell<Option<NonZeroUsize>>,
57
58 #[serde(skip)]
59 json_encoded_size_cache: AtomicCell<Option<NonZeroJsonSize>>,
60}
61
62impl Inner {
63 fn invalidate(&self) {
64 self.size_cache.store(None);
65 self.json_encoded_size_cache.store(None);
66 }
67
68 fn as_value(&self) -> &Value {
69 &self.fields
70 }
71}
72
73impl ByteSizeOf for Inner {
74 fn size_of(&self) -> usize {
75 self.size_cache
76 .load()
77 .unwrap_or_else(|| {
78 let size = size_of::<Self>() + self.allocated_bytes();
79 let size = NonZeroUsize::new(size).expect("Size cannot be zero");
84 self.size_cache.store(Some(size));
85 size
86 })
87 .into()
88 }
89
90 fn allocated_bytes(&self) -> usize {
91 self.fields.allocated_bytes()
92 }
93}
94
95impl EstimatedJsonEncodedSizeOf for Inner {
96 fn estimated_json_encoded_size_of(&self) -> JsonSize {
97 self.json_encoded_size_cache
98 .load()
99 .unwrap_or_else(|| {
100 let size = self.fields.estimated_json_encoded_size_of();
101 let size = NonZeroJsonSize::new(size).expect("Size cannot be zero");
102
103 self.json_encoded_size_cache.store(Some(size));
104 size
105 })
106 .into()
107 }
108}
109
110impl Clone for Inner {
111 fn clone(&self) -> Self {
112 Self {
113 fields: self.fields.clone(),
114 size_cache: None.into(),
118
119 json_encoded_size_cache: None.into(),
123 }
124 }
125}
126
127impl Default for Inner {
128 fn default() -> Self {
129 Self {
130 fields: Value::Object(Default::default()),
132 size_cache: Default::default(),
133 json_encoded_size_cache: Default::default(),
134 }
135 }
136}
137
138impl From<Value> for Inner {
139 fn from(fields: Value) -> Self {
140 Self {
141 fields,
142 size_cache: Default::default(),
143 json_encoded_size_cache: Default::default(),
144 }
145 }
146}
147
148impl PartialEq for Inner {
149 fn eq(&self, other: &Self) -> bool {
150 self.fields.eq(&other.fields)
151 }
152}
153
154#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
155pub struct LogEvent {
156 #[serde(flatten)]
157 inner: Arc<Inner>,
158
159 #[serde(skip)]
160 metadata: EventMetadata,
161}
162
163impl LogEvent {
164 pub fn from_str_legacy(msg: impl Into<String>) -> Self {
167 let mut log = LogEvent::default();
168 log.maybe_insert(log_schema().message_key_target_path(), msg.into());
169
170 if let Some(timestamp_key) = log_schema().timestamp_key_target_path() {
171 log.insert(timestamp_key, Utc::now());
172 }
173
174 log
175 }
176
177 pub fn from_bytes_legacy(msg: &Bytes) -> Self {
180 Self::from_str_legacy(String::from_utf8_lossy(msg.as_ref()).to_string())
181 }
182
183 pub fn value(&self) -> &Value {
184 self.inner.as_ref().as_value()
185 }
186
187 pub fn value_mut(&mut self) -> &mut Value {
188 let result = Arc::make_mut(&mut self.inner);
189 result.invalidate();
192 &mut result.fields
193 }
194
195 pub fn metadata(&self) -> &EventMetadata {
196 &self.metadata
197 }
198
199 pub fn metadata_mut(&mut self) -> &mut EventMetadata {
200 &mut self.metadata
201 }
202
203 pub fn namespace(&self) -> LogNamespace {
207 if self.contains((PathPrefix::Metadata, path!("vector"))) {
208 LogNamespace::Vector
209 } else {
210 LogNamespace::Legacy
211 }
212 }
213}
214
215impl ByteSizeOf for LogEvent {
216 fn allocated_bytes(&self) -> usize {
217 self.inner.size_of() + self.metadata.allocated_bytes()
218 }
219}
220
221impl Finalizable for LogEvent {
222 fn take_finalizers(&mut self) -> EventFinalizers {
223 self.metadata.take_finalizers()
224 }
225}
226
227impl MergeFinalizable for LogEvent {
228 fn merge_finalizers(&mut self, finalizers: EventFinalizers) {
229 self.metadata.merge_finalizers(finalizers);
230 }
231}
232
233impl EstimatedJsonEncodedSizeOf for LogEvent {
234 fn estimated_json_encoded_size_of(&self) -> JsonSize {
235 self.inner.estimated_json_encoded_size_of()
236 }
237}
238
239impl GetEventCountTags for LogEvent {
240 fn get_tags(&self) -> TaggedEventsSent {
241 let source = if telemetry().tags().emit_source {
242 self.metadata().source_id().cloned().into()
243 } else {
244 OptionalTag::Ignored
245 };
246
247 let service = if telemetry().tags().emit_service {
248 self.get_by_meaning("service")
249 .map(|value| value.to_string_lossy().to_string())
250 .into()
251 } else {
252 OptionalTag::Ignored
253 };
254
255 TaggedEventsSent { source, service }
256 }
257}
258
259impl LogEvent {
260 #[must_use]
261 pub fn new_with_metadata(metadata: EventMetadata) -> Self {
262 Self {
263 inner: Default::default(),
264 metadata,
265 }
266 }
267
268 pub fn from_parts(value: Value, metadata: EventMetadata) -> Self {
270 Self {
271 inner: Arc::new(value.into()),
272 metadata,
273 }
274 }
275
276 pub fn from_map(map: ObjectMap, metadata: EventMetadata) -> Self {
278 let inner = Arc::new(Inner::from(Value::Object(map)));
279 Self { inner, metadata }
280 }
281
282 pub fn into_parts(mut self) -> (Value, EventMetadata) {
284 self.value_mut();
285
286 let value = Arc::try_unwrap(self.inner)
287 .unwrap_or_else(|_| unreachable!("inner fields already cloned after owning"))
288 .fields;
289 let metadata = self.metadata;
290 (value, metadata)
291 }
292
293 #[must_use]
294 pub fn with_batch_notifier(mut self, batch: &BatchNotifier) -> Self {
295 self.metadata = self.metadata.with_batch_notifier(batch);
296 self
297 }
298
299 #[must_use]
300 pub fn with_batch_notifier_option(mut self, batch: &Option<BatchNotifier>) -> Self {
301 self.metadata = self.metadata.with_batch_notifier_option(batch);
302 self
303 }
304
305 pub fn add_finalizer(&mut self, finalizer: EventFinalizer) {
306 self.metadata.add_finalizer(finalizer);
307 }
308
309 pub fn parse_path_and_get_value(
313 &self,
314 path: impl AsRef<str>,
315 ) -> Result<Option<&Value>, PathParseError> {
316 parse_target_path(path.as_ref()).map(|path| self.get(&path))
317 }
318
319 #[allow(clippy::needless_pass_by_value)] pub fn get<'a>(&self, key: impl TargetPath<'a>) -> Option<&Value> {
321 match key.prefix() {
322 PathPrefix::Event => self.inner.fields.get(key.value_path()),
323 PathPrefix::Metadata => self.metadata.value().get(key.value_path()),
324 }
325 }
326
327 pub fn get_by_meaning(&self, meaning: impl AsRef<str>) -> Option<&Value> {
332 self.metadata().dropped_field(&meaning).or_else(|| {
333 self.metadata()
334 .schema_definition()
335 .meaning_path(meaning.as_ref())
336 .and_then(|path| self.get(path))
337 })
338 }
339
340 pub fn get_mut_by_meaning(&mut self, meaning: impl AsRef<str>) -> Option<&mut Value> {
345 Arc::clone(self.metadata.schema_definition())
346 .meaning_path(meaning.as_ref())
347 .and_then(|path| self.get_mut(path))
348 }
349
350 pub fn find_key_by_meaning(&self, meaning: impl AsRef<str>) -> Option<&OwnedTargetPath> {
352 self.metadata()
353 .schema_definition()
354 .meaning_path(meaning.as_ref())
355 }
356
357 #[allow(clippy::needless_pass_by_value)] pub fn get_mut<'a>(&mut self, path: impl TargetPath<'a>) -> Option<&mut Value> {
359 match path.prefix() {
360 PathPrefix::Event => self.value_mut().get_mut(path.value_path()),
361 PathPrefix::Metadata => self.metadata.value_mut().get_mut(path.value_path()),
362 }
363 }
364
365 #[allow(clippy::needless_pass_by_value)] pub fn contains<'a>(&self, path: impl TargetPath<'a>) -> bool {
367 match path.prefix() {
368 PathPrefix::Event => self.value().contains(path.value_path()),
369 PathPrefix::Metadata => self.metadata.value().contains(path.value_path()),
370 }
371 }
372
373 pub fn parse_path_and_insert(
378 &mut self,
379 path: impl AsRef<str>,
380 value: impl Into<Value>,
381 ) -> Result<Option<Value>, PathParseError> {
382 let target_path = parse_target_path(path.as_ref())?;
383 Ok(self.insert(&target_path, value))
384 }
385
386 #[allow(clippy::needless_pass_by_value)] pub fn insert<'a>(
388 &mut self,
389 path: impl TargetPath<'a>,
390 value: impl Into<Value>,
391 ) -> Option<Value> {
392 match path.prefix() {
393 PathPrefix::Event => self.value_mut().insert(path.value_path(), value.into()),
394 PathPrefix::Metadata => self
395 .metadata
396 .value_mut()
397 .insert(path.value_path(), value.into()),
398 }
399 }
400
401 pub fn maybe_insert<'a>(&mut self, path: Option<impl TargetPath<'a>>, value: impl Into<Value>) {
402 if let Some(path) = path {
403 self.insert(path, value);
404 }
405 }
406
407 pub fn try_insert<'a>(&mut self, path: impl TargetPath<'a>, value: impl Into<Value>) {
409 if !self.contains(path.clone()) {
410 self.insert(path, value);
411 }
412 }
413
414 pub fn rename_key<'a>(&mut self, from: impl TargetPath<'a>, to: impl TargetPath<'a>) {
418 if let Some(val) = self.remove(from) {
419 self.insert(to, val);
420 }
421 }
422
423 pub fn remove<'a>(&mut self, path: impl TargetPath<'a>) -> Option<Value> {
424 self.remove_prune(path, false)
425 }
426
427 #[allow(clippy::needless_pass_by_value)] pub fn remove_prune<'a>(&mut self, path: impl TargetPath<'a>, prune: bool) -> Option<Value> {
429 match path.prefix() {
430 PathPrefix::Event => self.value_mut().remove(path.value_path(), prune),
431 PathPrefix::Metadata => self.metadata.value_mut().remove(path.value_path(), prune),
432 }
433 }
434
435 pub fn keys(&self) -> Option<impl Iterator<Item = KeyString> + '_> {
436 match &self.inner.fields {
437 Value::Object(map) => Some(util::log::keys(map)),
438 _ => None,
439 }
440 }
441
442 pub fn all_event_fields(
445 &self,
446 ) -> Option<impl Iterator<Item = (KeyString, &Value)> + Serialize> {
447 self.as_map().map(all_fields)
448 }
449
450 pub fn all_event_fields_skip_array_elements(
452 &self,
453 ) -> Option<impl Iterator<Item = (KeyString, &Value)> + Serialize> {
454 self.as_map().map(all_fields_skip_array_elements)
455 }
456
457 pub fn all_metadata_fields(
460 &self,
461 ) -> Option<impl Iterator<Item = (KeyString, &Value)> + Serialize> {
462 match self.metadata.value() {
463 Value::Object(metadata_map) => Some(all_metadata_fields(metadata_map)),
464 _ => None,
465 }
466 }
467
468 pub fn convert_to_fields(&self) -> impl Iterator<Item = (KeyString, &Value)> + Serialize {
472 if let Some(map) = self.as_map() {
473 util::log::all_fields(map)
474 } else {
475 util::log::all_fields_non_object_root(self.value())
476 }
477 }
478
479 pub fn convert_to_fields_unquoted(
482 &self,
483 ) -> impl Iterator<Item = (KeyString, &Value)> + Serialize {
484 if let Some(map) = self.as_map() {
485 util::log::all_fields_unquoted(map)
486 } else {
487 util::log::all_fields_non_object_root(self.value())
488 }
489 }
490
491 pub fn is_empty_object(&self) -> bool {
492 if let Some(map) = self.as_map() {
493 map.is_empty()
494 } else {
495 false
496 }
497 }
498
499 pub fn as_map(&self) -> Option<&ObjectMap> {
500 match self.value() {
501 Value::Object(map) => Some(map),
502 _ => None,
503 }
504 }
505
506 pub fn as_map_mut(&mut self) -> Option<&mut ObjectMap> {
507 match self.value_mut() {
508 Value::Object(map) => Some(map),
509 _ => None,
510 }
511 }
512
513 pub fn merge(&mut self, mut incoming: LogEvent, fields: &[impl AsRef<str>]) {
516 for field in fields {
517 let field_path = event_path!(field.as_ref());
518 let Some(incoming_val) = incoming.remove(field_path) else {
519 continue;
520 };
521 match self.get_mut(field_path) {
522 None => {
523 self.insert(field_path, incoming_val);
524 }
525 Some(current_val) => current_val.merge(incoming_val),
526 }
527 }
528 self.metadata.merge(incoming.metadata);
529 }
530}
531
532impl LogEvent {
535 pub fn message_path(&self) -> Option<&OwnedTargetPath> {
538 match self.namespace() {
539 LogNamespace::Vector => self.find_key_by_meaning("message"),
540 LogNamespace::Legacy => log_schema().message_key_target_path(),
541 }
542 }
543
544 pub fn timestamp_path(&self) -> Option<&OwnedTargetPath> {
547 match self.namespace() {
548 LogNamespace::Vector => self.find_key_by_meaning("timestamp"),
549 LogNamespace::Legacy => log_schema().timestamp_key_target_path(),
550 }
551 }
552
553 pub fn host_path(&self) -> Option<&OwnedTargetPath> {
556 match self.namespace() {
557 LogNamespace::Vector => self.find_key_by_meaning("host"),
558 LogNamespace::Legacy => log_schema().host_key_target_path(),
559 }
560 }
561
562 pub fn source_type_path(&self) -> Option<&OwnedTargetPath> {
565 match self.namespace() {
566 LogNamespace::Vector => VECTOR_SOURCE_TYPE_PATH.as_ref(),
567 LogNamespace::Legacy => log_schema().source_type_key_target_path(),
568 }
569 }
570
571 pub fn get_message(&self) -> Option<&Value> {
574 match self.namespace() {
575 LogNamespace::Vector => self.get_by_meaning("message"),
576 LogNamespace::Legacy => log_schema()
577 .message_key_target_path()
578 .and_then(|key| self.get(key)),
579 }
580 }
581
582 pub fn get_timestamp(&self) -> Option<&Value> {
585 match self.namespace() {
586 LogNamespace::Vector => self.get_by_meaning("timestamp"),
587 LogNamespace::Legacy => log_schema()
588 .timestamp_key_target_path()
589 .and_then(|key| self.get(key)),
590 }
591 }
592
593 pub fn remove_timestamp(&mut self) -> Option<Value> {
596 self.timestamp_path()
597 .cloned()
598 .and_then(|key| self.remove(&key))
599 }
600
601 pub fn get_host(&self) -> Option<&Value> {
604 match self.namespace() {
605 LogNamespace::Vector => self.get_by_meaning("host"),
606 LogNamespace::Legacy => log_schema()
607 .host_key_target_path()
608 .and_then(|key| self.get(key)),
609 }
610 }
611
612 pub fn get_source_type(&self) -> Option<&Value> {
615 match self.namespace() {
616 LogNamespace::Vector => self.get(metadata_path!("vector", "source_type")),
617 LogNamespace::Legacy => log_schema()
618 .source_type_key_target_path()
619 .and_then(|key| self.get(key)),
620 }
621 }
622}
623
624impl MaybeAsLogMut for LogEvent {
625 fn maybe_as_log_mut(&mut self) -> Option<&mut LogEvent> {
626 Some(self)
627 }
628}
629
630impl EventDataEq for LogEvent {
631 fn event_data_eq(&self, other: &Self) -> bool {
632 self.inner.fields == other.inner.fields && self.metadata.event_data_eq(&other.metadata)
633 }
634}
635
636#[cfg(any(test, feature = "test"))]
637mod test_utils {
638 use super::{Bytes, LogEvent, Utc, log_schema};
639
640 impl From<Bytes> for LogEvent {
647 fn from(message: Bytes) -> Self {
648 let mut log = LogEvent::default();
649 log.maybe_insert(log_schema().message_key_target_path(), message);
650 if let Some(timestamp_key) = log_schema().timestamp_key_target_path() {
651 log.insert(timestamp_key, Utc::now());
652 }
653 log
654 }
655 }
656
657 impl From<&str> for LogEvent {
658 fn from(message: &str) -> Self {
659 message.to_owned().into()
660 }
661 }
662
663 impl From<String> for LogEvent {
664 fn from(message: String) -> Self {
665 Bytes::from(message).into()
666 }
667 }
668}
669
670impl From<Value> for LogEvent {
671 fn from(value: Value) -> Self {
672 Self::from_parts(value, EventMetadata::default())
673 }
674}
675
676impl From<ObjectMap> for LogEvent {
677 fn from(map: ObjectMap) -> Self {
678 Self::from_parts(Value::Object(map), EventMetadata::default())
679 }
680}
681
682impl From<HashMap<KeyString, Value>> for LogEvent {
683 fn from(map: HashMap<KeyString, Value>) -> Self {
684 Self::from_parts(
685 Value::Object(map.into_iter().collect::<ObjectMap>()),
686 EventMetadata::default(),
687 )
688 }
689}
690
691impl TryFrom<serde_json::Value> for LogEvent {
692 type Error = crate::Error;
693
694 fn try_from(map: serde_json::Value) -> Result<Self, Self::Error> {
695 match map {
696 serde_json::Value::Object(fields) => Ok(LogEvent::from(
697 fields
698 .into_iter()
699 .map(|(k, v)| (k.into(), v.into()))
700 .collect::<ObjectMap>(),
701 )),
702 _ => Err(crate::Error::from(
703 "Attempted to convert non-Object JSON into a LogEvent.",
704 )),
705 }
706 }
707}
708
709impl TryInto<serde_json::Value> for LogEvent {
710 type Error = crate::Error;
711
712 fn try_into(self) -> Result<serde_json::Value, Self::Error> {
713 Ok(serde_json::to_value(&self.inner.fields)?)
714 }
715}
716
717#[cfg(any(test, feature = "test"))]
718impl<T> std::ops::Index<T> for LogEvent
719where
720 T: AsRef<str>,
721{
722 type Output = Value;
723
724 fn index(&self, key: T) -> &Value {
725 self.parse_path_and_get_value(key.as_ref())
726 .ok()
727 .flatten()
728 .unwrap_or_else(|| panic!("Key is not found: {:?}", key.as_ref()))
729 }
730}
731
732impl<K, V> Extend<(K, V)> for LogEvent
733where
734 K: AsRef<str>,
735 V: Into<Value>,
736{
737 fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
738 for (k, v) in iter {
739 if let Ok(path) = parse_target_path(k.as_ref()) {
740 self.insert(&path, v.into());
741 }
742 }
743 }
744}
745
746impl<K: AsRef<str>, V: Into<Value>> FromIterator<(K, V)> for LogEvent {
748 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
749 let mut log_event = Self::default();
750 log_event.extend(iter);
751 log_event
752 }
753}
754
755impl Serialize for LogEvent {
756 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
757 where
758 S: Serializer,
759 {
760 self.value().serialize(serializer)
761 }
762}
763
764struct TracingTargetPaths {
766 pub(crate) timestamp: OwnedTargetPath,
767 pub(crate) kind: OwnedTargetPath,
768 pub(crate) module_path: OwnedTargetPath,
769 pub(crate) level: OwnedTargetPath,
770 pub(crate) target: OwnedTargetPath,
771}
772
773static TRACING_TARGET_PATHS: LazyLock<TracingTargetPaths> = LazyLock::new(|| TracingTargetPaths {
775 timestamp: OwnedTargetPath::event(owned_value_path!("timestamp")),
776 kind: OwnedTargetPath::event(owned_value_path!("metadata", "kind")),
777 level: OwnedTargetPath::event(owned_value_path!("metadata", "level")),
778 module_path: OwnedTargetPath::event(owned_value_path!("metadata", "module_path")),
779 target: OwnedTargetPath::event(owned_value_path!("metadata", "target")),
780});
781
782impl From<&tracing::Event<'_>> for LogEvent {
783 fn from(event: &tracing::Event<'_>) -> Self {
784 let now = chrono::Utc::now();
785 let mut maker = LogEvent::default();
786 event.record(&mut maker);
787
788 let mut log = maker;
789 log.insert(&TRACING_TARGET_PATHS.timestamp, now);
790
791 let meta = event.metadata();
792 log.insert(
793 &TRACING_TARGET_PATHS.kind,
794 if meta.is_event() {
795 Value::Bytes("event".to_string().into())
796 } else if meta.is_span() {
797 Value::Bytes("span".to_string().into())
798 } else {
799 Value::Null
800 },
801 );
802 log.insert(&TRACING_TARGET_PATHS.level, meta.level().to_string());
803 log.insert(
804 &TRACING_TARGET_PATHS.module_path,
805 meta.module_path()
806 .map_or(Value::Null, |mp| Value::Bytes(mp.to_string().into())),
807 );
808 log.insert(&TRACING_TARGET_PATHS.target, meta.target().to_string());
809 log
810 }
811}
812
813impl tracing::field::Visit for LogEvent {
815 fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
816 self.insert(event_path!(field.name()), value.to_string());
817 }
818
819 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn Debug) {
820 self.insert(event_path!(field.name()), format!("{value:?}"));
821 }
822
823 fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
824 self.insert(event_path!(field.name()), value);
825 }
826
827 fn record_u64(&mut self, field: &tracing::field::Field, value: u64) {
828 let field_path = event_path!(field.name());
829 let converted: Result<i64, _> = value.try_into();
830 match converted {
831 Ok(value) => self.insert(field_path, value),
832 Err(_) => self.insert(field_path, value.to_string()),
833 };
834 }
835
836 fn record_bool(&mut self, field: &tracing::field::Field, value: bool) {
837 self.insert(event_path!(field.name()), value);
838 }
839}
840
841#[cfg(test)]
842mod test {
843 use lookup::event_path;
844 use uuid::Version;
845 use vrl::{btreemap, value};
846
847 use super::*;
848 use crate::test_util::open_fixture;
849
850 #[test]
853 fn rename_key_flat_equiv_exists() {
854 let value = value!({
855 one: 1,
856 two: 2
857 });
858
859 let mut base = LogEvent::from_parts(value.clone(), EventMetadata::default());
860 base.rename_key(event_path!("one"), event_path!("one"));
861 let (actual_fields, _) = base.into_parts();
862
863 assert_eq!(value, actual_fields);
864 }
865 #[test]
866 fn rename_key_flat_equiv_not_exists() {
867 let value = value!({
868 one: 1,
869 two: 2
870 });
871
872 let mut base = LogEvent::from_parts(value.clone(), EventMetadata::default());
873 base.rename_key(event_path!("three"), event_path!("three"));
874 let (actual_fields, _) = base.into_parts();
875
876 assert_eq!(value, actual_fields);
877 }
878 #[test]
881 fn rename_key_flat_not_exists() {
882 let value = value!({
883 one: 1,
884 two: 2
885 });
886
887 let mut base = LogEvent::from_parts(value.clone(), EventMetadata::default());
888 base.rename_key(event_path!("three"), event_path!("four"));
889 let (actual_fields, _) = base.into_parts();
890
891 assert_eq!(value, actual_fields);
892 }
893 #[test]
896 fn rename_key_flat_no_overlap() {
897 let value = value!({
898 one: 1,
899 two: 2
900 });
901
902 let mut expected_value = value.clone();
903 let one = expected_value.remove(path!("one"), true).unwrap();
904 expected_value.insert(path!("three"), one);
905
906 let mut base = LogEvent::from_parts(value, EventMetadata::default());
907 base.rename_key(event_path!("one"), event_path!("three"));
908 let (actual_fields, _) = base.into_parts();
909
910 assert_eq!(expected_value, actual_fields);
911 }
912 #[test]
916 fn rename_key_flat_overlap() {
917 let value = value!({
918 one: 1,
919 two: 2
920 });
921
922 let mut expected_value = value.clone();
923 let val = expected_value.remove(path!("one"), true).unwrap();
924 expected_value.insert(path!("two"), val);
925
926 let mut base = LogEvent::from_parts(value, EventMetadata::default());
927 base.rename_key(event_path!("one"), event_path!("two"));
928 let (actual_value, _) = base.into_parts();
929
930 assert_eq!(expected_value, actual_value);
931 }
932
933 #[test]
934 fn insert() {
935 let mut log = LogEvent::default();
936
937 let old = log.insert(event_path!("foo"), "foo");
938
939 assert_eq!(log.get(event_path!("foo")), Some(&"foo".into()));
940 assert_eq!(old, None);
941 }
942
943 #[test]
944 fn insert_existing() {
945 let mut log = LogEvent::default();
946 log.insert(event_path!("foo"), "foo");
947
948 let old = log.insert(event_path!("foo"), "bar");
949
950 assert_eq!(log.get(event_path!("foo")), Some(&"bar".into()));
951 assert_eq!(old, Some("foo".into()));
952 }
953
954 #[test]
955 fn try_insert() {
956 let mut log = LogEvent::default();
957
958 log.try_insert(event_path!("foo"), "foo");
959
960 assert_eq!(log.get(event_path!("foo")), Some(&"foo".into()));
961 }
962
963 #[test]
964 fn try_insert_existing() {
965 let mut log = LogEvent::default();
966 log.insert(event_path!("foo"), "foo");
967
968 log.try_insert(event_path!("foo"), "bar");
969
970 assert_eq!(log.get(event_path!("foo")), Some(&"foo".into()));
971 }
972
973 #[test]
974 fn try_insert_nested() {
975 let mut log = LogEvent::default();
976
977 log.try_insert(event_path!("foo", "bar"), "foo");
978
979 assert_eq!(log.get(event_path!("foo", "bar")), Some(&"foo".into()));
980 assert_eq!(log.get(event_path!("foo.bar")), None);
981 }
982
983 #[test]
984 fn try_insert_existing_nested() {
985 let mut log = LogEvent::default();
986 log.insert(event_path!("foo", "bar"), "foo");
987
988 log.try_insert(event_path!("foo", "bar"), "bar");
989
990 assert_eq!(log.get(event_path!("foo", "bar")), Some(&"foo".into()));
991 assert_eq!(log.get(event_path!("foo.bar")), None);
992 }
993
994 #[test]
995 fn try_insert_flat() {
996 let mut log = LogEvent::default();
997
998 log.try_insert(event_path!("foo"), "foo");
999
1000 assert_eq!(log.get(event_path!("foo")), Some(&"foo".into()));
1001 }
1002
1003 #[test]
1004 fn try_insert_flat_existing() {
1005 let mut log = LogEvent::default();
1006 log.insert(event_path!("foo"), "foo");
1007
1008 log.try_insert(event_path!("foo"), "bar");
1009
1010 assert_eq!(log.get(event_path!("foo")), Some(&"foo".into()));
1011 }
1012
1013 #[test]
1014 fn try_insert_flat_dotted() {
1015 let mut log = LogEvent::default();
1016
1017 log.try_insert(event_path!("foo.bar"), "foo");
1018
1019 assert_eq!(log.get(event_path!("foo.bar")), Some(&"foo".into()));
1020 }
1021
1022 #[test]
1023 fn try_insert_flat_existing_dotted() {
1024 let mut log = LogEvent::default();
1025 log.insert(event_path!("foo.bar"), "foo");
1026
1027 log.try_insert(event_path!("foo.bar"), "bar");
1028
1029 assert_eq!(log.get(event_path!("foo.bar")), Some(&"foo".into()));
1030 }
1031
1032 #[test]
1041 fn json_value_to_vector_log_event_to_json_value() {
1042 const FIXTURE_ROOT: &str = "tests/data/fixtures/log_event";
1043
1044 for fixture_file in std::fs::read_dir(FIXTURE_ROOT).unwrap() {
1045 match fixture_file {
1046 Ok(fixture_file) => {
1047 let path = fixture_file.path();
1048 tracing::trace!(?path, "Opening.");
1049 let serde_value = open_fixture(&path).unwrap();
1050
1051 let vector_value = LogEvent::try_from(serde_value.clone()).unwrap();
1052 let serde_value_again: serde_json::Value = vector_value.try_into().unwrap();
1053
1054 assert_eq!(serde_value, serde_value_again);
1055 }
1056 _ => panic!("This test should never read Err'ing test fixtures."),
1057 }
1058 }
1059 }
1060
1061 fn assert_merge_value(
1062 current: impl Into<Value>,
1063 incoming: impl Into<Value>,
1064 expected: impl Into<Value>,
1065 ) {
1066 let mut merged = current.into();
1067 merged.merge(incoming.into());
1068 assert_eq!(merged, expected.into());
1069 }
1070
1071 #[test]
1072 fn merge_value_works_correctly() {
1073 assert_merge_value("hello ", "world", "hello world");
1074
1075 assert_merge_value(true, false, false);
1076 assert_merge_value(false, true, true);
1077
1078 assert_merge_value("my_val", true, true);
1079 assert_merge_value(true, "my_val", "my_val");
1080
1081 assert_merge_value(1, 2, 2);
1082 }
1083
1084 #[test]
1085 fn merge_event_combines_values_accordingly() {
1086 let fields_to_merge = vec![
1090 "merge".to_string(),
1091 "merge_a".to_string(),
1092 "merge_b".to_string(),
1093 "merge_c".to_string(),
1094 ];
1095
1096 let current = {
1097 let mut log = LogEvent::default();
1098
1099 log.insert(event_path!("merge"), "hello "); log.insert(event_path!("do_not_merge"), "my_first_value"); log.insert(event_path!("merge_a"), true); log.insert(event_path!("merge_b"), 123i64); log.insert(event_path!("a"), true); log.insert(event_path!("b"), 123i64); log
1112 };
1113
1114 let incoming = {
1115 let mut log = LogEvent::default();
1116
1117 log.insert(event_path!("merge"), "world"); log.insert(event_path!("do_not_merge"), "my_second_value"); log.insert(event_path!("merge_b"), 456i64); log.insert(event_path!("merge_c"), false); log.insert(event_path!("b"), 456i64); log.insert(event_path!("c"), true); log
1129 };
1130
1131 let mut merged = current;
1132 merged.merge(incoming, &fields_to_merge);
1133
1134 let expected = {
1135 let mut log = LogEvent::default();
1136 log.insert(event_path!("merge"), "hello world");
1137 log.insert(event_path!("do_not_merge"), "my_first_value");
1138 log.insert(event_path!("a"), true);
1139 log.insert(event_path!("b"), 123i64);
1140 log.insert(event_path!("merge_a"), true);
1141 log.insert(event_path!("merge_b"), 456i64);
1142 log.insert(event_path!("merge_c"), false);
1143 log
1144 };
1145
1146 vector_common::assert_event_data_eq!(merged, expected);
1147 }
1148
1149 #[test]
1150 fn event_fields_iter() {
1151 let mut log = LogEvent::default();
1152 log.insert(event_path!("a"), 0);
1153 log.insert(event_path!("a", "b"), 1);
1154 log.insert(event_path!("c"), 2);
1155 let actual: Vec<(KeyString, Value)> = log
1156 .all_event_fields()
1157 .unwrap()
1158 .map(|(s, v)| (s, v.clone()))
1159 .collect();
1160 assert_eq!(
1161 actual,
1162 vec![("a.b".into(), 1.into()), ("c".into(), 2.into())]
1163 );
1164 }
1165
1166 #[test]
1167 fn metadata_fields_iter() {
1168 let mut log = LogEvent::default();
1169 log.insert(metadata_path!("a"), 0);
1170 log.insert(metadata_path!("a", "b"), 1);
1171 log.insert(metadata_path!("c"), 2);
1172 let actual: Vec<(KeyString, Value)> = log
1173 .all_metadata_fields()
1174 .unwrap()
1175 .map(|(s, v)| (s, v.clone()))
1176 .collect();
1177 assert_eq!(
1178 actual,
1179 vec![("%a.b".into(), 1.into()), ("%c".into(), 2.into())]
1180 );
1181 }
1182
1183 #[test]
1184 fn skip_array_elements() {
1185 let log = LogEvent::from(Value::from(btreemap! {
1186 "arr" => [1],
1187 "obj" => btreemap! {
1188 "arr" => [1,2,3]
1189 },
1190 }));
1191
1192 let actual: Vec<(KeyString, Value)> = log
1193 .all_event_fields_skip_array_elements()
1194 .unwrap()
1195 .map(|(s, v)| (s, v.clone()))
1196 .collect();
1197 assert_eq!(
1198 actual,
1199 vec![
1200 ("arr".into(), [1].into()),
1201 ("obj.arr".into(), [1, 2, 3].into())
1202 ]
1203 );
1204 }
1205
1206 #[test]
1207 fn metadata_set_unique_uuid_v4_source_event_id() {
1208 let log1 = LogEvent::default();
1210 assert_eq!(
1211 log1.metadata()
1212 .source_event_id()
1213 .expect("source_event_id should be auto-generated for new events")
1214 .get_version(),
1215 Some(Version::Random)
1216 );
1217
1218 let log2 = LogEvent::default();
1220 assert_ne!(
1221 log1.metadata().source_event_id(),
1222 log2.metadata().source_event_id()
1223 );
1224 }
1225}