use std::ops::Deref;
use langfuse_core::types::{CostDetails, ObservationType, UsageDetails};
use serde::Serialize;
use super::attributes;
use super::span::LangfuseSpan;
pub struct LangfuseGeneration {
span: LangfuseSpan,
}
impl std::fmt::Debug for LangfuseGeneration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LangfuseGeneration")
.field("trace_id", &self.span.trace_id())
.field("span_id", &self.span.span_id())
.finish()
}
}
impl Clone for LangfuseGeneration {
fn clone(&self) -> Self {
Self {
span: self.span.clone(),
}
}
}
impl LangfuseGeneration {
#[must_use]
pub fn start(name: &str) -> Self {
use opentelemetry::trace::{TraceContextExt, Tracer};
let tracer = opentelemetry::global::tracer("langfuse");
let otel_span = tracer.start(name.to_owned());
let context = opentelemetry::Context::current().with_span(otel_span);
let span = LangfuseSpan::from_context(context);
if let Ok(serde_json::Value::String(s)) = serde_json::to_value(ObservationType::Generation)
{
span.set_string_attribute(attributes::LANGFUSE_OBSERVATION_TYPE, &s);
}
Self { span }
}
pub(crate) fn from_span(span: LangfuseSpan) -> Self {
Self { span }
}
pub(crate) fn from_context(context: opentelemetry::Context) -> Self {
Self {
span: LangfuseSpan::from_context(context),
}
}
pub fn set_model(&self, model: &str) -> &Self {
self.span
.set_string_attribute(attributes::LANGFUSE_MODEL, model);
self
}
pub fn set_model_parameters(&self, params: &impl Serialize) -> &Self {
self.span
.set_json_attribute(attributes::LANGFUSE_MODEL_PARAMETERS, params);
self
}
pub fn set_usage(&self, usage: &UsageDetails) -> &Self {
self.span
.set_json_attribute(attributes::LANGFUSE_USAGE, usage);
self
}
pub fn set_cost(&self, cost: &CostDetails) -> &Self {
self.span
.set_json_attribute(attributes::LANGFUSE_COST, cost);
self
}
pub fn set_tool_calls(&self, tool_calls: &impl Serialize) -> &Self {
self.span
.set_json_attribute(attributes::LANGFUSE_TOOL_CALLS, tool_calls);
self
}
pub fn set_completion_start_time(&self, time: &chrono::DateTime<chrono::Utc>) -> &Self {
self.span.set_string_attribute(
attributes::LANGFUSE_COMPLETION_START_TIME,
&time.to_rfc3339(),
);
self
}
}
impl Deref for LangfuseGeneration {
type Target = LangfuseSpan;
fn deref(&self) -> &Self::Target {
&self.span
}
}