use serde_json::Value;
use opentelemetry::logs::{AnyValue, LogRecord as _, Logger as _, LoggerProvider as _, Severity};
fn json_value_to_anyvalue(v: &Value) -> AnyValue {
match v {
Value::String(s) => AnyValue::String(s.clone().into()),
Value::Bool(b) => AnyValue::Boolean(*b),
Value::Number(n) => {
if let Some(i) = n.as_i64() {
AnyValue::Int(i)
} else {
AnyValue::Double(n.as_f64().unwrap_or(0.0))
}
}
Value::Array(arr) => {
AnyValue::ListAny(Box::new(arr.iter().map(json_value_to_anyvalue).collect()))
}
Value::Object(map) => AnyValue::Map(Box::new(
map.iter()
.map(|(k, v)| (k.clone().into(), json_value_to_anyvalue(v)))
.collect(),
)),
Value::Null => AnyValue::String("".into()),
}
}
#[derive(Clone, Default)]
pub struct Logger {}
impl Logger {
pub fn new() -> Self {
Self {}
}
fn emit_otel(&self, message: &str, severity: Severity, data: Option<&Value>) -> bool {
let Some(provider) = crate::telemetry::get_logger_provider() else {
return false;
};
let logger = provider.logger("iii-rust-sdk");
let mut record = logger.create_log_record();
let now = std::time::SystemTime::now();
record.set_timestamp(now);
record.set_observed_timestamp(now);
record.set_severity_number(severity);
record.set_body(message.to_string().into());
if let Some(d) = data {
record.add_attribute("log.data", json_value_to_anyvalue(d));
}
{
use opentelemetry::trace::TraceContextExt;
let cx = opentelemetry::Context::current();
let span_ctx = cx.span().span_context().clone();
if span_ctx.is_valid() {
record.set_trace_context(
span_ctx.trace_id(),
span_ctx.span_id(),
Some(span_ctx.trace_flags()),
);
}
}
logger.emit(record);
true
}
pub fn info(&self, message: &str, data: Option<Value>) {
if self.emit_otel(message, Severity::Info, data.as_ref()) {
return;
}
tracing::info!(message = %message);
}
pub fn warn(&self, message: &str, data: Option<Value>) {
if self.emit_otel(message, Severity::Warn, data.as_ref()) {
return;
}
tracing::warn!(message = %message);
}
pub fn error(&self, message: &str, data: Option<Value>) {
if self.emit_otel(message, Severity::Error, data.as_ref()) {
return;
}
tracing::error!(message = %message);
}
pub fn debug(&self, message: &str, data: Option<Value>) {
if self.emit_otel(message, Severity::Debug, data.as_ref()) {
return;
}
tracing::debug!(message = %message);
}
}