Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions crates/goose-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1059,7 +1059,7 @@ async fn handle_interactive_session(
};

tracing::info!(
counter.goose.session_starts = 1,
monotonic_counter.goose.session_starts = 1,
session_type,
interactive = true,
"Session started"
Expand Down Expand Up @@ -1136,7 +1136,7 @@ async fn log_session_completion(
.unwrap_or((0, 0));

tracing::info!(
counter.goose.session_completions = 1,
monotonic_counter.goose.session_completions = 1,
session_type,
exit_type,
duration_ms = session_duration.as_millis() as u64,
Expand All @@ -1146,14 +1146,14 @@ async fn log_session_completion(
);

tracing::info!(
counter.goose.session_duration_ms = session_duration.as_millis() as u64,
monotonic_counter.goose.session_duration_ms = session_duration.as_millis() as u64,
session_type,
"Session duration"
);

if total_tokens > 0 {
tracing::info!(
counter.goose.session_tokens = total_tokens,
monotonic_counter.goose.session_tokens = total_tokens,
session_type,
"Session tokens"
);
Expand Down Expand Up @@ -1236,7 +1236,7 @@ fn parse_run_input(
}

tracing::info!(
counter.goose.recipe_runs = 1,
monotonic_counter.goose.recipe_runs = 1,
recipe_name = %recipe_display_name,
recipe_version = %recipe_version,
session_type = "recipe",
Expand Down Expand Up @@ -1323,7 +1323,7 @@ async fn handle_run_command(
let session_type = if recipe.is_some() { "recipe" } else { "run" };

tracing::info!(
counter.goose.session_starts = 1,
monotonic_counter.goose.session_starts = 1,
session_type,
interactive = false,
"Headless session started"
Expand Down Expand Up @@ -1437,7 +1437,7 @@ pub async fn cli() -> anyhow::Result<()> {

let command_name = get_command_name(&cli.command);
tracing::info!(
counter.goose.cli_commands = 1,
monotonic_counter.goose.cli_commands = 1,
command = command_name,
"CLI command executed"
);
Expand Down
4 changes: 2 additions & 2 deletions crates/goose-cli/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1740,7 +1740,7 @@ fn log_tool_metrics(message: &Message, messages: &Conversation) {
if let MessageContent::ToolRequest(tool_request) = content {
if let Ok(tool_call) = &tool_request.tool_call {
tracing::info!(
counter.goose.tool_calls = 1,
monotonic_counter.goose.tool_calls = 1,
tool_name = %tool_call.name,
"Tool call started"
);
Expand Down Expand Up @@ -1771,7 +1771,7 @@ fn log_tool_metrics(message: &Message, messages: &Conversation) {
"error"
};
tracing::info!(
counter.goose.tool_completions = 1,
monotonic_counter.goose.tool_completions = 1,
tool_name = %tool_name,
result = %result_status,
"Tool call completed"
Expand Down
16 changes: 8 additions & 8 deletions crates/goose-server/src/routes/reply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fn track_tool_telemetry(content: &MessageContent, all_messages: &[Message]) {
let result_status = if success { "success" } else { "error" };

tracing::info!(
counter.goose.tool_completions = 1,
monotonic_counter.goose.tool_completions = 1,
tool_name = %tool_name,
result = %result_status,
"Tool call completed"
Expand Down Expand Up @@ -209,7 +209,7 @@ pub async fn reply(
let session_start = std::time::Instant::now();

tracing::info!(
counter.goose.session_starts = 1,
monotonic_counter.goose.session_starts = 1,
session_type = "app",
interface = "ui",
"Session started"
Expand All @@ -225,7 +225,7 @@ pub async fn reply(
.unwrap_or_else(|| "unknown".to_string());

tracing::info!(
counter.goose.recipe_runs = 1,
monotonic_counter.goose.recipe_runs = 1,
recipe_name = %recipe_name,
recipe_version = %recipe_version,
session_type = "app",
Expand Down Expand Up @@ -396,7 +396,7 @@ pub async fn reply(
if let Ok(session) = state.session_manager().get_session(&session_id, true).await {
let total_tokens = session.total_tokens.unwrap_or(0);
tracing::info!(
counter.goose.session_completions = 1,
monotonic_counter.goose.session_completions = 1,
session_type = "app",
interface = "ui",
exit_type = "normal",
Expand All @@ -407,23 +407,23 @@ pub async fn reply(
);

tracing::info!(
counter.goose.session_duration_ms = session_duration.as_millis() as u64,
monotonic_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,
monotonic_counter.goose.session_tokens = total_tokens,
session_type = "app",
interface = "ui",
"Session tokens"
);
}
} else {
tracing::info!(
counter.goose.session_completions = 1,
monotonic_counter.goose.session_completions = 1,
session_type = "app",
interface = "ui",
exit_type = "normal",
Expand All @@ -434,7 +434,7 @@ pub async fn reply(
);

tracing::info!(
counter.goose.session_duration_ms = session_duration.as_millis() as u64,
monotonic_counter.goose.session_duration_ms = session_duration.as_millis() as u64,
session_type = "app",
interface = "ui",
"Session duration"
Expand Down
2 changes: 1 addition & 1 deletion crates/goose-server/src/routes/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ async fn run_now_handler(

let recipe_version_tag = recipe_version_opt.as_deref().unwrap_or("");
tracing::info!(
counter.goose.recipe_runs = 1,
monotonic_counter.goose.recipe_runs = 1,
recipe_name = %recipe_display_name,
recipe_version = %recipe_version_tag,
session_type = "schedule",
Expand Down
2 changes: 1 addition & 1 deletion crates/goose/src/agents/tool_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl Agent {
// Log user decision if this was a security alert
if let Some(finding_id) = get_security_finding_id_from_results(&request.id, inspection_results) {
tracing::info!(
counter.goose.prompt_injection_user_decisions = 1,
monotonic_counter.goose.prompt_injection_user_decisions = 1,
decision = ?confirmation.permission,
finding_id = %finding_id,
tool_request_id = %request.id,
Expand Down
29 changes: 28 additions & 1 deletion crates/goose/src/otel/otlp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use opentelemetry::trace::TracerProvider;
use opentelemetry::{global, KeyValue};
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
use opentelemetry_sdk::logs::{SdkLogger, SdkLoggerProvider};
use opentelemetry_sdk::metrics::SdkMeterProvider;
use opentelemetry_sdk::metrics::{SdkMeterProvider, Temporality};
use opentelemetry_sdk::propagation::TraceContextPropagator;
use opentelemetry_sdk::resource::{EnvResourceDetector, TelemetryResourceDetector};
use opentelemetry_sdk::trace::SdkTracerProvider;
Expand Down Expand Up @@ -173,6 +173,19 @@ fn create_otlp_tracing_layer() -> OtlpResult<OtlpTracingLayer> {
Ok(tracing_opentelemetry::layer().with_tracer(tracer))
}

// TODO: remove once https://github.com/open-telemetry/opentelemetry-rust/pull/3351 is released.
fn temporality_preference() -> Temporality {
match env::var("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE")
.unwrap_or_default()
.to_lowercase()
.as_str()
{
"delta" => Temporality::Delta,
"lowmemory" => Temporality::LowMemory,
_ => Temporality::Cumulative,
}
}

fn create_otlp_metrics_layer() -> OtlpResult<OtlpMetricsLayer> {
let exporter = signal_exporter("metrics").ok_or("Metrics not enabled")?;
let resource = create_resource();
Expand All @@ -181,6 +194,7 @@ fn create_otlp_metrics_layer() -> OtlpResult<OtlpMetricsLayer> {
ExporterType::Otlp => {
let exporter = opentelemetry_otlp::MetricExporter::builder()
.with_http()
.with_temporality(temporality_preference())
.build()?;
SdkMeterProvider::builder()
.with_resource(resource)
Expand Down Expand Up @@ -332,6 +346,7 @@ mod tests {
use super::*;
use opentelemetry::metrics::{Meter, MeterProvider};
use opentelemetry::InstrumentationScope;
use opentelemetry_sdk::metrics::Temporality;
use std::sync::Arc;
use test_case::test_case;

Expand Down Expand Up @@ -371,6 +386,7 @@ mod tests {
("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT", None),
("OTEL_EXPORTER_OTLP_TIMEOUT", None),
("OTEL_SERVICE_NAME", None),
("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", None),
("OTEL_RESOURCE_ATTRIBUTES", None),
]);
for &(k, v) in overrides {
Expand Down Expand Up @@ -548,4 +564,15 @@ mod tests {
expect_timeout
);
}

#[test_case(&[], Temporality::Cumulative; "default is cumulative")]
#[test_case(&[("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", "delta")], Temporality::Delta; "delta")]
#[test_case(&[("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", "Delta")], Temporality::Delta; "Delta mixed case")]
#[test_case(&[("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", "lowmemory")], Temporality::LowMemory; "lowmemory")]
#[test_case(&[("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", "cumulative")], Temporality::Cumulative; "cumulative")]
#[test_case(&[("OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", "bogus")], Temporality::Cumulative; "unknown defaults to cumulative")]
fn temporality_preference_from_env(env: &[(&str, &str)], expected: Temporality) {
let _guard = clear_otel_env(env);
assert_eq!(temporality_preference(), expected);
}
}
10 changes: 5 additions & 5 deletions crates/goose/src/security/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl SecurityManager {
) -> Result<Vec<SecurityResult>> {
if !self.is_prompt_injection_detection_enabled() {
tracing::debug!(
counter.goose.prompt_injection_scanner_disabled = 1,
monotonic_counter.goose.prompt_injection_scanner_disabled = 1,
"Security scanning disabled"
);
return Ok(vec![]);
Expand All @@ -74,7 +74,7 @@ impl SecurityManager {
match PromptInjectionScanner::with_ml_detection() {
Ok(s) => {
tracing::info!(
counter.goose.prompt_injection_scanner_enabled = 1,
monotonic_counter.goose.prompt_injection_scanner_enabled = 1,
"Security scanner initialized with ML-based detection"
);
s
Expand All @@ -90,7 +90,7 @@ impl SecurityManager {
}
} else {
tracing::info!(
counter.goose.prompt_injection_scanner_enabled = 1,
monotonic_counter.goose.prompt_injection_scanner_enabled = 1,
"Security scanner initialized with pattern-based detection only"
);
PromptInjectionScanner::new()
Expand Down Expand Up @@ -124,7 +124,7 @@ impl SecurityManager {
serde_json::to_string(&tool_call).unwrap_or_else(|_| "{}".to_string());

tracing::warn!(
counter.goose.prompt_injection_finding = 1,
monotonic_counter.goose.prompt_injection_finding = 1,
threat_type = "command_injection",
above_threshold = above_threshold,
tool_name = %tool_call.name,
Expand Down Expand Up @@ -164,7 +164,7 @@ impl SecurityManager {
}

tracing::info!(
counter.goose.prompt_injection_analysis_performed = 1,
monotonic_counter.goose.prompt_injection_analysis_performed = 1,
security_issues_found = results.len(),
"Prompt injection detection: Security analysis complete"
);
Expand Down
Loading