Skip to main content

relay_spans/
description.rs

1use relay_conventions::attributes::*;
2use relay_conventions::description::description_for_op_and_attributes;
3use relay_event_schema::protocol::Attributes;
4use relay_protocol::{Annotated, Getter, Val};
5
6/// Derives a description for a V2 span, based on its name
7/// and attributes.
8///
9/// For now, this attempts to return the following values, in order:
10/// - the span's name if its [`SENTRY__ORIGIN`] attribute is `"manual"`
11/// - a name constructed following the rules defined in sentry-conventions
12/// - `None`
13pub fn derive_description_for_v2_span(
14    attributes: &Attributes,
15    name: &Annotated<String>,
16) -> Option<String> {
17    let origin = attributes
18        .get_value(SENTRY__ORIGIN)
19        .and_then(|o| o.as_str());
20
21    let name = name.as_str();
22
23    if let Some(name) = name
24        && origin == Some("manual")
25    {
26        return Some(name.to_owned());
27    }
28
29    let op = attributes.get_value(SENTRY__OP)?.as_str()?;
30
31    description_for_op_and_attributes(op, &AttributeGetter(attributes))
32}
33
34/// A custom getter for [`Attributes`] which only resolves values based on the attribute name.
35///
36/// This [`Getter`] does not implement nested traversals, which is the behaviour required for
37/// [`description_for_op_and_attributes`].
38struct AttributeGetter<'a>(&'a Attributes);
39
40impl<'a> Getter for AttributeGetter<'a> {
41    fn get_value(&self, path: &str) -> Option<Val<'_>> {
42        self.0.get_value(path).map(|value| value.into())
43    }
44}