1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use std::time::SystemTime;

use tracing_actions::{ActionEvent, AttributeValue, SpanStatus, TraceKind};

use crate::{
    proto::opentelemetry::{
        common::v1::{any_value, AnyValue, KeyValue},
        trace::v1::{
            span::{self, Event},
            status::StatusCode,
            Span, Status,
        },
    },
    OtlpAttributes,
};

impl From<OtlpAttributes> for Vec<KeyValue> {
    fn from(value: OtlpAttributes) -> Self {
        let mut attributes: Vec<KeyValue> = value
            .other_attributes
            .unwrap_or_default()
            .into_iter()
            .map(|(key, value)| KeyValue {
                key,
                value: Some(AnyValue {
                    value: Some(any_value::Value::StringValue(value)),
                }),
            })
            .collect();
        attributes.push(KeyValue {
            key: "service.name".to_string(),
            value: Some(AnyValue {
                value: Some(any_value::Value::StringValue(value.service_name)),
            }),
        });
        attributes
    }
}

impl From<&mut tracing_actions::ActionSpan> for Span {
    fn from(value: &mut tracing_actions::ActionSpan) -> Self {
        Self {
            trace_id: value.trace_id.to_vec(),
            span_id: value.span_id.to_vec(),
            trace_state: value.trace_state.clone(),
            parent_span_id: value
                .parent_span_id
                .map(|id| id.to_vec())
                .unwrap_or_default(),
            name: value
                .metadata
                .map(|m| m.name().to_string())
                .unwrap_or_else(|| "unknown".to_string()),
            kind: as_spankind(value.kind) as i32,
            start_time_unix_nano: value
                .start
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap_or_default()
                .as_nanos() as u64,
            end_time_unix_nano: value
                .end
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap_or_default()
                .as_nanos() as u64,
            attributes: value.attributes.drain().map(KeyValue::from).collect(),
            dropped_attributes_count: 0,
            events: value.events.drain(..).map(Event::from).collect(),
            dropped_events_count: 0,
            links: vec![],
            dropped_links_count: 0,
            status: Some(value.status.into()),
        }
    }
}

fn as_spankind(value: TraceKind) -> span::SpanKind {
    match value {
        TraceKind::Client => span::SpanKind::Client,
        TraceKind::Server => span::SpanKind::Server,
    }
}

impl From<(&str, AttributeValue)> for KeyValue {
    fn from(value: (&str, AttributeValue)) -> Self {
        let (name, value) = value;
        Self {
            key: name.to_string(),
            value: Some(AnyValue {
                value: Some(match value {
                    AttributeValue::String(s) => any_value::Value::StringValue(s),
                    AttributeValue::F64(f) => any_value::Value::DoubleValue(f),
                    AttributeValue::I64(i) => any_value::Value::IntValue(i),
                    AttributeValue::U64(u) => any_value::Value::IntValue(u as i64),
                    AttributeValue::I128(i) => any_value::Value::IntValue(i as i64),
                    AttributeValue::U128(u) => any_value::Value::IntValue(u as i64),
                    AttributeValue::Bool(b) => any_value::Value::BoolValue(b),
                    AttributeValue::Error(e) => any_value::Value::StringValue(e),
                }),
            }),
        }
    }
}

impl From<ActionEvent> for Event {
    fn from(mut value: ActionEvent) -> Self {
        Self {
            time_unix_nano: value
                .timestamp
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap_or_default()
                .as_nanos() as u64,
            name: value.metadata.name().to_string(),
            attributes: value.attributes.drain().map(KeyValue::from).collect(),
            dropped_attributes_count: 0,
        }
    }
}

impl From<SpanStatus> for Status {
    fn from(value: SpanStatus) -> Self {
        match value {
            SpanStatus::Ok => Self {
                message: "".to_string(),
                code: StatusCode::Ok.into(),
            },
            SpanStatus::Error => Self {
                message: "".to_string(),
                code: StatusCode::Error.into(),
            },
        }
    }
}