use serde::Deserialize;
use serde_json::{Map, Value};
#[derive(Debug, Default, Deserialize)]
pub struct ExportTraceServiceRequest {
#[serde(default, rename = "resourceSpans")]
pub resource_spans: Vec<ResourceSpans>,
}
#[derive(Debug, Default, Deserialize)]
pub struct ResourceSpans {
#[serde(default)]
pub resource: Resource,
#[serde(default, rename = "scopeSpans", alias = "instrumentationLibrarySpans")]
pub scope_spans: Vec<ScopeSpans>,
}
#[derive(Debug, Default, Deserialize)]
pub struct Resource {
#[serde(default)]
pub attributes: Vec<KeyValue>,
}
#[derive(Debug, Default, Deserialize)]
pub struct ScopeSpans {
#[serde(default, alias = "instrumentationLibrary")]
pub scope: Scope,
#[serde(default)]
pub spans: Vec<Span>,
}
#[derive(Debug, Default, Deserialize)]
pub struct Scope {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub version: Option<String>,
}
#[derive(Debug, Default, Deserialize)]
pub struct Span {
#[serde(default, rename = "traceId")]
pub trace_id: String,
#[serde(default, rename = "spanId")]
pub span_id: String,
#[serde(default, rename = "parentSpanId")]
pub parent_span_id: Option<String>,
#[serde(default)]
pub name: String,
#[serde(default, rename = "startTimeUnixNano")]
pub start_time_unix_nano: Option<Value>,
#[serde(default, rename = "endTimeUnixNano")]
pub end_time_unix_nano: Option<Value>,
#[serde(default)]
pub attributes: Vec<KeyValue>,
#[serde(default)]
pub status: Status,
#[serde(default)]
pub events: Vec<Event>,
}
#[derive(Debug, Default, Deserialize)]
pub struct Status {
#[serde(default)]
pub code: Option<Value>,
#[serde(default)]
pub message: Option<String>,
}
impl Status {
pub fn is_error(&self) -> bool {
match &self.code {
Some(Value::Number(n)) => n.as_i64() == Some(2),
Some(Value::String(s)) => {
s == "2"
|| s.eq_ignore_ascii_case("STATUS_CODE_ERROR")
|| s.eq_ignore_ascii_case("ERROR")
}
_ => false,
}
}
}
#[derive(Debug, Default, Deserialize)]
pub struct Event {
#[serde(default)]
pub name: String,
#[serde(default, rename = "timeUnixNano")]
pub time_unix_nano: Option<Value>,
#[serde(default)]
pub attributes: Vec<KeyValue>,
}
#[derive(Debug, Default, Deserialize)]
pub struct KeyValue {
#[serde(default)]
pub key: String,
#[serde(default)]
pub value: AnyValue,
}
#[derive(Debug, Default, Deserialize)]
pub struct AnyValue {
#[serde(default, rename = "stringValue")]
pub string_value: Option<String>,
#[serde(default, rename = "intValue")]
pub int_value: Option<Value>,
#[serde(default, rename = "doubleValue")]
pub double_value: Option<f64>,
#[serde(default, rename = "boolValue")]
pub bool_value: Option<bool>,
#[serde(default, rename = "arrayValue")]
pub array_value: Option<ArrayValue>,
#[serde(default, rename = "kvlistValue")]
pub kvlist_value: Option<KvList>,
#[serde(default, rename = "bytesValue")]
pub bytes_value: Option<String>,
}
#[derive(Debug, Default, Deserialize)]
pub struct ArrayValue {
#[serde(default)]
pub values: Vec<AnyValue>,
}
#[derive(Debug, Default, Deserialize)]
pub struct KvList {
#[serde(default)]
pub values: Vec<KeyValue>,
}
impl AnyValue {
pub fn to_json(&self) -> Value {
if let Some(s) = &self.string_value {
return Value::String(s.clone());
}
if let Some(v) = &self.int_value {
return match v {
Value::String(s) => s
.parse::<i64>()
.map(Value::from)
.unwrap_or_else(|_| Value::String(s.clone())),
other => other.clone(),
};
}
if let Some(d) = self.double_value {
return serde_json::Number::from_f64(d).map_or(Value::Null, Value::Number);
}
if let Some(b) = self.bool_value {
return Value::Bool(b);
}
if let Some(arr) = &self.array_value {
return Value::Array(arr.values.iter().map(AnyValue::to_json).collect());
}
if let Some(kv) = &self.kvlist_value {
return Value::Object(key_values_to_map(&kv.values));
}
if let Some(b) = &self.bytes_value {
return Value::String(b.clone());
}
Value::Null
}
pub fn to_label_string(&self) -> String {
match self.to_json() {
Value::String(s) => s,
other => other.to_string(),
}
}
}
pub fn key_values_to_map(kvs: &[KeyValue]) -> Map<String, Value> {
let mut map = Map::new();
for kv in kvs {
if kv.key.is_empty() {
continue;
}
map.insert(kv.key.clone(), kv.value.to_json());
}
map
}