Skip to content

Commit 74676b9

Browse files
committed
feat(rust): add an attribute to distinguish user journeys
1 parent ad16037 commit 74676b9

File tree

1 file changed

+58
-22
lines changed
  • implementations/rust/ockam/ockam_api/src/cli_state/journeys

1 file changed

+58
-22
lines changed

implementations/rust/ockam/ockam_api/src/cli_state/journeys/journeys.rs

+58-22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use ockam_core::{OpenTelemetryContext, OCKAM_TRACER_NAME};
1111
use opentelemetry::trace::{Link, SpanBuilder, SpanId, TraceContextExt, TraceId, Tracer};
1212
use opentelemetry::{global, Context, Key, KeyValue};
1313
use std::collections::HashMap;
14+
use std::fmt::{Display, Formatter};
1415
use std::ops::Add;
1516
use std::time::{Duration, SystemTime};
1617
use tracing::Level;
@@ -52,6 +53,22 @@ pub const APPLICATION_EVENT_OCKAM_HOME: &Key = &Key::from_static_str("app.event.
5253
pub const APPLICATION_EVENT_OCKAM_VERSION: &Key = &Key::from_static_str("app.event.ockam_version");
5354
pub const APPLICATION_EVENT_OCKAM_GIT_HASH: &Key =
5455
&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+
}
5572

5673
/// Journey events have a fixed duration
5774
pub const EVENT_DURATION: Duration = Duration::from_secs(100);
@@ -114,29 +131,49 @@ impl CliState {
114131
return Ok(());
115132
}
116133

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<()> {
117159
// get the journey context
118160
let tracer = global::tracer(OCKAM_TRACER_NAME);
119161
let event_span_context = Context::current().span().span_context().clone();
120-
let project = self.projects().get_default_project().await.ok();
121162

122163
// for both the host and the project journey create a span with a fixed duration
123164
// and add attributes to the span
124165
let start_time = SystemTime::from(Utc::now());
125166
let end_time = start_time.add(EVENT_DURATION);
126167

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);
140177
Ok(())
141178
}
142179

@@ -218,25 +255,22 @@ impl CliState {
218255
}
219256

220257
/// 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>)> {
222259
let now = *Context::current()
223260
.get::<DateTime<Utc>>()
224261
.unwrap_or(&Utc::now());
225262

226-
let mut result = vec![];
227-
228263
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? {
230265
Some(Either::Right(journey)) => journey,
231266
Some(Either::Left(journey)) => {
232267
self.create_host_journey(Some(journey.opentelemetry_context()), now)
233268
.await?
234269
}
235270
None => self.create_host_journey(None, now).await?,
236271
};
237-
result.push(journey);
238272

239-
if let Some(project_id) = project_id {
273+
let project_journey = if let Some(project_id) = project_id {
240274
let journey = match self
241275
.get_project_journey(&project_id, now, max_duration)
242276
.await?
@@ -252,10 +286,12 @@ impl CliState {
252286
}
253287
None => self.create_project_journey(&project_id, None, now).await?,
254288
};
255-
result.push(journey.to_journey());
289+
Some(journey.to_journey())
290+
} else {
291+
None
256292
};
257293

258-
Ok(result)
294+
Ok((host_journey, project_journey))
259295
}
260296

261297
/// When a project is deleted the project journeys need to be restarted

0 commit comments

Comments
 (0)