additional metrics + Ui implementation (#3871)

This commit is contained in:
Max Novich
2025-08-06 09:26:15 -07:00
committed by GitHub
parent a5371af4c1
commit 4567eb22be
8 changed files with 444 additions and 47 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ use tracing::info;
use goose::providers::pricing::initialize_pricing_cache;
pub async fn run() -> Result<()> {
// Initialize logging
// Initialize logging and telemetry
crate::logging::setup_logging(Some("goosed"))?;
let settings = configuration::Settings::new()?;
+119 -5
View File
@@ -11,7 +11,7 @@ use bytes::Bytes;
use futures::{stream::StreamExt, Stream};
use goose::{
agents::{AgentEvent, SessionConfig},
message::{push_message, Message},
message::{push_message, Message, MessageContent},
permission::permission_confirmation::PrincipalType,
};
use goose::{
@@ -37,6 +37,53 @@ use tokio_stream::wrappers::ReceiverStream;
use tokio_util::sync::CancellationToken;
use utoipa::ToSchema;
fn track_tool_telemetry(content: &MessageContent, all_messages: &[Message]) {
match content {
MessageContent::ToolRequest(tool_request) => {
if let Ok(tool_call) = &tool_request.tool_call {
tracing::info!(monotonic_counter.goose.tool_calls = 1,
tool_name = %tool_call.name,
"Tool call started"
);
}
}
MessageContent::ToolResponse(tool_response) => {
let tool_name = all_messages
.iter()
.rev()
.find_map(|msg| {
msg.content.iter().find_map(|c| {
if let MessageContent::ToolRequest(req) = c {
if req.id == tool_response.id {
if let Ok(tool_call) = &req.tool_call {
Some(tool_call.name.clone())
} else {
None
}
} else {
None
}
} else {
None
}
})
})
.unwrap_or_else(|| "unknown".to_string());
let success = tool_response.tool_result.is_ok();
let result_status = if success { "success" } else { "error" };
tracing::info!(
counter.goose.tool_completions = 1,
tool_name = %tool_name,
result = %result_status,
"Tool call completed"
);
}
_ => {}
}
}
#[derive(Debug, Deserialize, Serialize)]
struct ChatRequest {
messages: Vec<Message>,
@@ -126,6 +173,15 @@ async fn reply_handler(
) -> Result<SseResponse, StatusCode> {
verify_secret_key(&headers, &state)?;
let session_start = std::time::Instant::now();
tracing::info!(
counter.goose.session_starts = 1,
session_type = "app",
interface = "ui",
"Session started"
);
let (tx, rx) = mpsc::channel(100);
let stream = ReceiverStream::new(rx);
let cancel_token = CancellationToken::new();
@@ -222,8 +278,12 @@ async fn reply_handler(
response = timeout(Duration::from_millis(500), stream.next()) => {
match response {
Ok(Some(Ok(AgentEvent::Message(message)))) => {
push_message(&mut all_messages, message.clone());
stream_event(MessageEvent::Message { message }, &tx, &cancel_token).await;
for content in &message.content {
track_tool_telemetry(content, &all_messages);
}
push_message(&mut all_messages, message.clone());
stream_event(MessageEvent::Message { message }, &tx, &cancel_token).await;
}
Ok(Some(Ok(AgentEvent::HistoryReplaced(new_messages)))) => {
// Replace the message history with the compacted messages
@@ -269,10 +329,12 @@ async fn reply_handler(
if all_messages.len() > saved_message_count {
if let Ok(provider) = agent.provider().await {
let provider = Arc::clone(&provider);
let session_path_clone = session_path.to_path_buf();
let all_messages_clone = all_messages.clone();
tokio::spawn(async move {
if let Err(e) = session::persist_messages(
&session_path,
&all_messages,
&session_path_clone,
&all_messages_clone,
Some(provider),
Some(PathBuf::from(&session_working_dir)),
)
@@ -284,6 +346,58 @@ async fn reply_handler(
}
}
let session_duration = session_start.elapsed();
if let Ok(metadata) = session::read_metadata(&session_path) {
let total_tokens = metadata.total_tokens.unwrap_or(0);
let message_count = metadata.message_count;
tracing::info!(
counter.goose.session_completions = 1,
session_type = "app",
interface = "ui",
exit_type = "normal",
duration_ms = session_duration.as_millis() as u64,
total_tokens,
message_count,
"Session completed"
);
tracing::info!(
counter.goose.session_duration_ms = session_duration.as_millis() as u64,
session_type = "app",
interface = "ui",
"Session duration"
);
if total_tokens > 0 {
tracing::info!(
counter.goose.session_tokens = total_tokens,
session_type = "app",
interface = "ui",
"Session tokens"
);
}
} else {
tracing::info!(
counter.goose.session_completions = 1,
session_type = "app",
interface = "ui",
exit_type = "normal",
duration_ms = session_duration.as_millis() as u64,
total_tokens = 0u64,
message_count = all_messages.len(),
"Session completed"
);
tracing::info!(
counter.goose.session_duration_ms = session_duration.as_millis() as u64,
session_type = "app",
interface = "ui",
"Session duration"
);
}
let _ = stream_event(
MessageEvent::Finish {
reason: "stop".to_string(),