1//! Events represent single points in time during the execution of a program.
2use crate::parent::Parent;
3use crate::span::Id;
4use crate::{field, Metadata};
5
6/// `Event`s represent single points in time where something occurred during the
7/// execution of a program.
8///
9/// An `Event` can be compared to a log record in unstructured logging, but with
10/// two key differences:
11/// - `Event`s exist _within the context of a [span]_. Unlike log lines, they
12/// may be located within the trace tree, allowing visibility into the
13/// _temporal_ context in which the event occurred, as well as the source
14/// code location.
15/// - Like spans, `Event`s have structured key-value data known as _[fields]_,
16/// which may include textual message. In general, a majority of the data
17/// associated with an event should be in the event's fields rather than in
18/// the textual message, as the fields are more structured.
19///
20/// [span]: super::span
21/// [fields]: super::field
22#[derive(Debug)]
23pub struct Event<'a> {
24 fields: &'a field::ValueSet<'a>,
25 metadata: &'static Metadata<'static>,
26 parent: Parent,
27}
28
29impl<'a> Event<'a> {
30 /// Constructs a new `Event` with the specified metadata and set of values,
31 /// and observes it with the current subscriber.
32 pub fn dispatch(metadata: &'static Metadata<'static>, fields: &'a field::ValueSet<'_>) {
33 let event = Event::new(metadata, fields);
34 crate::dispatcher::get_default(|current| {
35 current.event(&event);
36 });
37 }
38
39 /// Returns a new `Event` in the current span, with the specified metadata
40 /// and set of values.
41 #[inline]
42 pub fn new(metadata: &'static Metadata<'static>, fields: &'a field::ValueSet<'a>) -> Self {
43 Event {
44 fields,
45 metadata,
46 parent: Parent::Current,
47 }
48 }
49
50 /// Returns a new `Event` as a child of the specified span, with the
51 /// provided metadata and set of values.
52 #[inline]
53 pub fn new_child_of(
54 parent: impl Into<Option<Id>>,
55 metadata: &'static Metadata<'static>,
56 fields: &'a field::ValueSet<'a>,
57 ) -> Self {
58 let parent = match parent.into() {
59 Some(p) => Parent::Explicit(p),
60 None => Parent::Root,
61 };
62 Event {
63 fields,
64 metadata,
65 parent,
66 }
67 }
68
69 /// Constructs a new `Event` with the specified metadata and set of values,
70 /// and observes it with the current subscriber and an explicit parent.
71 pub fn child_of(
72 parent: impl Into<Option<Id>>,
73 metadata: &'static Metadata<'static>,
74 fields: &'a field::ValueSet<'_>,
75 ) {
76 let event = Self::new_child_of(parent, metadata, fields);
77 crate::dispatcher::get_default(|current| {
78 current.event(&event);
79 });
80 }
81
82 /// Visits all the fields on this `Event` with the specified [visitor].
83 ///
84 /// [visitor]: super::field::Visit
85 #[inline]
86 pub fn record(&self, visitor: &mut dyn field::Visit) {
87 self.fields.record(visitor);
88 }
89
90 /// Returns an iterator over the set of values on this `Event`.
91 pub fn fields(&self) -> field::Iter {
92 self.fields.field_set().iter()
93 }
94
95 /// Returns [metadata] describing this `Event`.
96 ///
97 /// [metadata]: super::Metadata
98 pub fn metadata(&self) -> &'static Metadata<'static> {
99 self.metadata
100 }
101
102 /// Returns true if the new event should be a root.
103 pub fn is_root(&self) -> bool {
104 matches!(self.parent, Parent::Root)
105 }
106
107 /// Returns true if the new event's parent should be determined based on the
108 /// current context.
109 ///
110 /// If this is true and the current thread is currently inside a span, then
111 /// that span should be the new event's parent. Otherwise, if the current
112 /// thread is _not_ inside a span, then the new event will be the root of its
113 /// own trace tree.
114 pub fn is_contextual(&self) -> bool {
115 matches!(self.parent, Parent::Current)
116 }
117
118 /// Returns the new event's explicitly-specified parent, if there is one.
119 ///
120 /// Otherwise (if the new event is a root or is a child of the current span),
121 /// returns `None`.
122 pub fn parent(&self) -> Option<&Id> {
123 match self.parent {
124 Parent::Explicit(ref p) => Some(p),
125 _ => None,
126 }
127 }
128}
129