1 | //! Events represent single points in time during the execution of a program. |
2 | use crate::parent::Parent; |
3 | use crate::span::Id; |
4 | use 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)] |
23 | pub struct Event<'a> { |
24 | fields: &'a field::ValueSet<'a>, |
25 | metadata: &'static Metadata<'static>, |
26 | parent: Parent, |
27 | } |
28 | |
29 | impl<'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 | |