@@ -11,6 +11,7 @@ use ockam_core::{OpenTelemetryContext, OCKAM_TRACER_NAME};
11
11
use opentelemetry:: trace:: { Link , SpanBuilder , SpanId , TraceContextExt , TraceId , Tracer } ;
12
12
use opentelemetry:: { global, Context , Key , KeyValue } ;
13
13
use std:: collections:: HashMap ;
14
+ use std:: fmt:: { Display , Formatter } ;
14
15
use std:: ops:: Add ;
15
16
use std:: time:: { Duration , SystemTime } ;
16
17
use tracing:: Level ;
@@ -52,6 +53,22 @@ pub const APPLICATION_EVENT_OCKAM_HOME: &Key = &Key::from_static_str("app.event.
52
53
pub const APPLICATION_EVENT_OCKAM_VERSION : & Key = & Key :: from_static_str ( "app.event.ockam_version" ) ;
53
54
pub const APPLICATION_EVENT_OCKAM_GIT_HASH : & Key =
54
55
& Key :: from_static_str ( "app.event.ockam_git_hash" ) ;
56
+ pub const APPLICATION_EVENT_TRACE_TYPE : & Key = & Key :: from_static_str ( "app.event.trace_type" ) ;
57
+
58
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
59
+ pub enum TraceType {
60
+ Host ,
61
+ Project ,
62
+ }
63
+
64
+ impl Display for TraceType {
65
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
66
+ match self {
67
+ TraceType :: Host => f. write_str ( "host" ) ,
68
+ TraceType :: Project => f. write_str ( "project" ) ,
69
+ }
70
+ }
71
+ }
55
72
56
73
/// Journey events have a fixed duration
57
74
pub const EVENT_DURATION : Duration = Duration :: from_secs ( 100 ) ;
@@ -114,29 +131,49 @@ impl CliState {
114
131
return Ok ( ( ) ) ;
115
132
}
116
133
134
+ let project = self . projects ( ) . get_default_project ( ) . await . ok ( ) ;
135
+ let ( host_journey, project_journey) = self
136
+ . get_journeys ( project. clone ( ) . map ( |p| p. project_id ( ) . to_string ( ) ) )
137
+ . await ?;
138
+ self . make_span_from_journey ( & project, & event, & attributes, host_journey, "host" )
139
+ . await ?;
140
+ if let Some ( project_journey) = project_journey {
141
+ self . make_span_from_journey ( & project, & event, & attributes, project_journey, "project" )
142
+ . await ?;
143
+ }
144
+ Ok ( ( ) )
145
+ }
146
+
147
+ /// Create a span that will get its trace_id from the journey context
148
+ /// The trace_type is used to differentiate between the host and the project journeys.
149
+ /// We can later on use this information to filter all the spans for a given host, or all the spans
150
+ /// for a given project.
151
+ async fn make_span_from_journey (
152
+ & self ,
153
+ project : & Option < Project > ,
154
+ event : & JourneyEvent ,
155
+ attributes : & HashMap < & Key , String > ,
156
+ journey : Journey ,
157
+ trace_type : & str ,
158
+ ) -> Result < ( ) > {
117
159
// get the journey context
118
160
let tracer = global:: tracer ( OCKAM_TRACER_NAME ) ;
119
161
let event_span_context = Context :: current ( ) . span ( ) . span_context ( ) . clone ( ) ;
120
- let project = self . projects ( ) . get_default_project ( ) . await . ok ( ) ;
121
162
122
163
// for both the host and the project journey create a span with a fixed duration
123
164
// and add attributes to the span
124
165
let start_time = SystemTime :: from ( Utc :: now ( ) ) ;
125
166
let end_time = start_time. add ( EVENT_DURATION ) ;
126
167
127
- let journeys = self
128
- . get_journeys ( project. clone ( ) . map ( |p| p. project_id ( ) . to_string ( ) ) )
129
- . await ?;
130
- for journey in journeys {
131
- let span_builder = SpanBuilder :: from_name ( event. to_string ( ) )
132
- . with_start_time ( start_time)
133
- . with_end_time ( end_time)
134
- . with_links ( vec ! [ Link :: new( event_span_context. clone( ) , vec![ ] , 0 ) ] ) ;
135
- let span = tracer. build_with_context ( span_builder, & journey. extract_context ( ) ) ;
136
- let cx = Context :: current_with_span ( span) ;
137
- let _guard = cx. attach ( ) ;
138
- self . set_current_span_attributes ( & event, & attributes, & project)
139
- }
168
+ let span_builder = SpanBuilder :: from_name ( event. to_string ( ) )
169
+ . with_start_time ( start_time)
170
+ . with_end_time ( end_time)
171
+ . with_links ( vec ! [ Link :: new( event_span_context. clone( ) , vec![ ] , 0 ) ] ) ;
172
+ let span = tracer. build_with_context ( span_builder, & journey. extract_context ( ) ) ;
173
+ let cx = Context :: current_with_span ( span) ;
174
+ let _guard = cx. attach ( ) ;
175
+ self . set_current_span_attributes ( event, attributes, project) ;
176
+ CurrentSpan :: set_attribute ( APPLICATION_EVENT_TRACE_TYPE , trace_type) ;
140
177
Ok ( ( ) )
141
178
}
142
179
@@ -218,25 +255,22 @@ impl CliState {
218
255
}
219
256
220
257
/// Return a list of journeys for which we want to add spans
221
- async fn get_journeys ( & self , project_id : Option < String > ) -> Result < Vec < Journey > > {
258
+ async fn get_journeys ( & self , project_id : Option < String > ) -> Result < ( Journey , Option < Journey > ) > {
222
259
let now = * Context :: current ( )
223
260
. get :: < DateTime < Utc > > ( )
224
261
. unwrap_or ( & Utc :: now ( ) ) ;
225
262
226
- let mut result = vec ! [ ] ;
227
-
228
263
let max_duration = DEFAULT_JOURNEY_MAX_DURATION ;
229
- let journey = match self . get_host_journey ( now, max_duration) . await ? {
264
+ let host_journey = match self . get_host_journey ( now, max_duration) . await ? {
230
265
Some ( Either :: Right ( journey) ) => journey,
231
266
Some ( Either :: Left ( journey) ) => {
232
267
self . create_host_journey ( Some ( journey. opentelemetry_context ( ) ) , now)
233
268
. await ?
234
269
}
235
270
None => self . create_host_journey ( None , now) . await ?,
236
271
} ;
237
- result. push ( journey) ;
238
272
239
- if let Some ( project_id) = project_id {
273
+ let project_journey = if let Some ( project_id) = project_id {
240
274
let journey = match self
241
275
. get_project_journey ( & project_id, now, max_duration)
242
276
. await ?
@@ -252,10 +286,12 @@ impl CliState {
252
286
}
253
287
None => self . create_project_journey ( & project_id, None , now) . await ?,
254
288
} ;
255
- result. push ( journey. to_journey ( ) ) ;
289
+ Some ( journey. to_journey ( ) )
290
+ } else {
291
+ None
256
292
} ;
257
293
258
- Ok ( result )
294
+ Ok ( ( host_journey , project_journey ) )
259
295
}
260
296
261
297
/// When a project is deleted the project journeys need to be restarted
0 commit comments