use crate::transport::{
CallOptions, ClientOptions, HttpTransport, InfraClientError, ServiceEndpoint,
};
use agent_trace_contract::{
AppendEventsRequest, AppendResponse, EVENTS_APPEND_PATH, EVENTS_SEARCH_PATH, EventsResponse,
RuntimeEventRecord, SearchEventsRequest, TraceScope, redact_payload,
};
use reqwest::Client;
#[derive(Clone, Debug)]
pub struct TraceClient {
transport: HttpTransport,
}
impl TraceClient {
pub(crate) fn new_with_endpoint(
http: Client,
endpoint: ServiceEndpoint,
options: ClientOptions,
) -> Self {
Self {
transport: HttpTransport::new_with_options(
http,
agent_trace_contract::SERVICE_NAME,
endpoint,
options,
),
}
}
pub async fn append_events(
&self,
events: Vec<RuntimeEventRecord>,
) -> Result<AppendResponse, InfraClientError> {
self.append_events_with_options(events, CallOptions::default())
.await
}
pub async fn append_events_with_options(
&self,
mut events: Vec<RuntimeEventRecord>,
options: CallOptions,
) -> Result<AppendResponse, InfraClientError> {
for event in &mut events {
redact_payload(&mut event.payload);
redact_payload(&mut event.metadata);
}
self.transport
.post_json_with_options(
EVENTS_APPEND_PATH,
&AppendEventsRequest { events },
options.idempotent(true),
)
.await
}
pub async fn search_events(
&self,
conversation_id: &str,
run_id: &str,
event_type: Option<&str>,
limit: Option<usize>,
) -> Result<Vec<RuntimeEventRecord>, InfraClientError> {
let request = SearchEventsRequest {
scope: TraceScope::run(conversation_id, run_id),
event_type: event_type.map(ToOwned::to_owned),
limit,
};
let response: EventsResponse = self
.transport
.post_json(EVENTS_SEARCH_PATH, &request)
.await?;
Ok(response.items)
}
}