mirror of
https://github.com/openai/codex.git
synced 2026-11-07 20:30:33 +00:00
Warn users when SQLite diagnostic log writes fail (#47887)
## Why Failed SQLite writes leave diagnostic logs incomplete. Notify users before they close Codex so they can submit logs or run `codex doctor`. ## What changed - Add a best-effort warning on the first log write failure in standalone and in-process app servers, while continuing to retain failure diagnostics in memory. - Handle failures that occurred before the in-process warning reporter was attached. - Tailor the warning's guidance to whether submitting logs is enabled. ## Testing Add coverage for warning deduplication, both guidance variants, retained diagnostics after the notification sender is dropped, and SQLite flush failures before and after reporter attachment. Extend log upload integration coverage and add a TUI warnings snapshot. GitOrigin-RevId: 12a74126d13c3568430e539a180cca47fa931fa9
This commit is contained in:
committed by
copyberry
parent
a285066737
commit
3d6428510f
@@ -0,0 +1,67 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_app_server_protocol::WarningNotification;
|
||||
use codex_core::config::Config;
|
||||
use codex_feedback::CodexFeedback;
|
||||
use codex_state::LogWriteFailureReporter;
|
||||
|
||||
use crate::outgoing_message::OutgoingMessageSender;
|
||||
|
||||
const LOG_WRITE_WARNING_WITH_FEEDBACK: &str = "Codex couldn't save diagnostic logs to its local database. Use /feedback with logs included before closing Codex, or run `codex doctor` for diagnostics.";
|
||||
const LOG_WRITE_WARNING_WITHOUT_FEEDBACK: &str = "Codex couldn't save diagnostic logs to its local database. Run `codex doctor` for diagnostics.";
|
||||
|
||||
pub(crate) struct LogWriteWarningReporter {
|
||||
feedback: CodexFeedback,
|
||||
outgoing: Weak<OutgoingMessageSender>,
|
||||
/// Permanently set by the first failure; limits warning delivery to one attempt
|
||||
/// for this reporter, even if later SQLite writes succeed.
|
||||
has_failure: AtomicBool,
|
||||
message: &'static str,
|
||||
}
|
||||
|
||||
impl LogWriteWarningReporter {
|
||||
pub(crate) fn new(
|
||||
feedback: CodexFeedback,
|
||||
outgoing: &Arc<OutgoingMessageSender>,
|
||||
config: &Config,
|
||||
) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
feedback,
|
||||
outgoing: Arc::downgrade(outgoing),
|
||||
has_failure: AtomicBool::new(false),
|
||||
message: if config.feedback_enabled {
|
||||
LOG_WRITE_WARNING_WITH_FEEDBACK
|
||||
} else {
|
||||
LOG_WRITE_WARNING_WITHOUT_FEEDBACK
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn notify_failure(&self) {
|
||||
if !self.has_failure.swap(true, Ordering::Relaxed)
|
||||
&& let Some(outgoing) = self.outgoing.upgrade()
|
||||
{
|
||||
outgoing.try_send_server_notification(ServerNotification::Warning(
|
||||
WarningNotification {
|
||||
thread_id: None,
|
||||
message: self.message.to_string(),
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LogWriteFailureReporter for LogWriteWarningReporter {
|
||||
fn report_failure(&self, diagnostic: &str) {
|
||||
self.feedback.report_failure(diagnostic);
|
||||
self.notify_failure();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "log_write_warning_tests.rs"]
|
||||
mod tests;
|
||||
Reference in New Issue
Block a user