1use api::v1::ColumnDataType;
16use api::v1::value::ValueData;
17use common_telemetry::warn;
18use jsonb::{Number as JsonbNumber, Value as JsonbValue};
19use opentelemetry_proto::tonic::common::v1::{KeyValue, any_value};
20
21use crate::otlp::trace::KEY_SERVICE_NAME;
22
23pub(crate) fn resource_service_name(resource_attrs: &[KeyValue]) -> Option<String> {
27 resource_attrs
28 .iter()
29 .find(|kv| kv.key == KEY_SERVICE_NAME)
30 .and_then(|kv| kv.value.as_ref()?.value.as_ref())
31 .and_then(|value| match value {
32 any_value::Value::StringValue(s) => Some(s.clone()),
33 any_value::Value::BytesValue(b) => Some(String::from_utf8_lossy(b).to_string()),
34 _ => None,
35 })
36}
37
38pub fn bytes_to_hex_string(bs: &[u8]) -> String {
39 hex::encode(bs)
40}
41
42pub fn any_value_to_jsonb(value: any_value::Value) -> JsonbValue<'static> {
43 match value {
44 any_value::Value::StringValue(s) => JsonbValue::String(s.into()),
45 any_value::Value::IntValue(i) => JsonbValue::Number(JsonbNumber::Int64(i)),
46 any_value::Value::DoubleValue(d) => JsonbValue::Number(JsonbNumber::Float64(d)),
47 any_value::Value::BoolValue(b) => JsonbValue::Bool(b),
48 any_value::Value::ArrayValue(a) => {
49 let values = a
50 .values
51 .into_iter()
52 .map(|v| match v.value {
53 Some(value) => any_value_to_jsonb(value),
54 None => JsonbValue::Null,
55 })
56 .collect();
57 JsonbValue::Array(values)
58 }
59 any_value::Value::KvlistValue(kv) => key_value_to_jsonb(kv.values),
60 any_value::Value::BytesValue(b) => JsonbValue::String(bytes_to_hex_string(&b).into()),
61 any_value::Value::StringValueStrindex(_) => {
66 warn!(
67 "encountered a profiling-only `StringValueStrindex` value in a non-profiling signal; ignoring"
68 );
69 JsonbValue::Null
70 }
71 }
72}
73
74pub fn key_value_to_jsonb(key_values: Vec<KeyValue>) -> JsonbValue<'static> {
75 JsonbValue::Object(
76 key_values
77 .into_iter()
78 .map(|kv| {
79 (
80 kv.key,
81 kv.value
82 .and_then(|v| v.value)
83 .map_or(JsonbValue::Null, any_value_to_jsonb),
84 )
85 })
86 .collect(),
87 )
88}
89
90#[inline]
91pub(crate) fn make_string_column_data(
92 name: &str,
93 value: Option<String>,
94) -> (String, ColumnDataType, Option<ValueData>) {
95 make_column_data(
96 name,
97 ColumnDataType::String,
98 value.map(ValueData::StringValue),
99 )
100}
101
102#[inline]
103pub(crate) fn make_column_data(
104 name: &str,
105 data_type: ColumnDataType,
106 value: Option<ValueData>,
107) -> (String, ColumnDataType, Option<ValueData>) {
108 (name.to_string(), data_type, value)
109}