Fall back to stdout if log file is inaccessible (#8415)

https://github.com/zed-industries/zed/assets/31967125/644f3524-e680-457c-bf4c-a7f11f3ec8db

Fixes #8209
Defaults to env logger in case of open/access failure.

Release Notes:

- Improved Zed behavior when no log file access is possible ([8209](https://github.com/zed-industries/zed/issues/8209))

---------

Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This commit is contained in:
Dheeraj 2024-02-26 23:48:19 -08:00 committed by GitHub
parent 8fc2431a2a
commit af14bc7a27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 78 additions and 47 deletions

View file

@ -497,30 +497,7 @@ fn init_paths() {
fn init_logger() {
if stdout_is_a_pty() {
Builder::new()
.parse_default_env()
.format(|buf, record| {
use env_logger::fmt::Color;
let subtle = buf
.style()
.set_color(Color::Black)
.set_intense(true)
.clone();
write!(buf, "{}", subtle.value("["))?;
write!(
buf,
"{} ",
chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z")
)?;
write!(buf, "{:<5}", buf.default_styled_level(record.level()))?;
if let Some(path) = record.module_path() {
write!(buf, " {}", path)?;
}
write!(buf, "{}", subtle.value("]"))?;
writeln!(buf, " {}", record.args())
})
.init();
init_stdout_logger();
} else {
let level = LevelFilter::Info;
@ -533,21 +510,58 @@ fn init_logger() {
let _ = std::fs::rename(&*paths::LOG, &*paths::OLD_LOG);
}
let log_file = OpenOptions::new()
match OpenOptions::new()
.create(true)
.append(true)
.open(&*paths::LOG)
.expect("could not open logfile");
{
Ok(log_file) => {
let config = ConfigBuilder::new()
.set_time_format_str("%Y-%m-%dT%T%:z")
.set_time_to_local(true)
.build();
let config = ConfigBuilder::new()
.set_time_format_str("%Y-%m-%dT%T%:z")
.set_time_to_local(true)
.build();
simplelog::WriteLogger::init(level, config, log_file).expect("could not initialize logger");
simplelog::WriteLogger::init(level, config, log_file)
.expect("could not initialize logger");
}
Err(err) => {
init_stdout_logger();
log::error!(
"could not open log file, defaulting to stdout logging: {}",
err
);
}
}
}
}
fn init_stdout_logger() {
Builder::new()
.parse_default_env()
.format(|buf, record| {
use env_logger::fmt::Color;
let subtle = buf
.style()
.set_color(Color::Black)
.set_intense(true)
.clone();
write!(buf, "{}", subtle.value("["))?;
write!(
buf,
"{} ",
chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z")
)?;
write!(buf, "{:<5}", buf.default_styled_level(record.level()))?;
if let Some(path) = record.module_path() {
write!(buf, " {}", path)?;
}
write!(buf, "{}", subtle.value("]"))?;
writeln!(buf, " {}", record.args())
})
.init();
}
#[derive(Serialize, Deserialize)]
struct LocationData {
file: String,

View file

@ -477,25 +477,42 @@ fn open_log_file(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
cx.spawn(|workspace, mut cx| async move {
let (old_log, new_log) =
futures::join!(fs.load(&paths::OLD_LOG), fs.load(&paths::LOG));
let mut lines = VecDeque::with_capacity(MAX_LINES);
for line in old_log
.iter()
.flat_map(|log| log.lines())
.chain(new_log.iter().flat_map(|log| log.lines()))
{
if lines.len() == MAX_LINES {
lines.pop_front();
let log = match (old_log, new_log) {
(Err(_), Err(_)) => None,
(old_log, new_log) => {
let mut lines = VecDeque::with_capacity(MAX_LINES);
for line in old_log
.iter()
.flat_map(|log| log.lines())
.chain(new_log.iter().flat_map(|log| log.lines()))
{
if lines.len() == MAX_LINES {
lines.pop_front();
}
lines.push_back(line);
}
Some(
lines
.into_iter()
.flat_map(|line| [line, "\n"])
.collect::<String>(),
)
}
lines.push_back(line);
}
let log = lines
.into_iter()
.flat_map(|line| [line, "\n"])
.collect::<String>();
};
workspace
.update(&mut cx, |workspace, cx| {
let Some(log) = log else {
workspace.show_notification(29, cx, |cx| {
cx.new_view(|_| {
MessageNotification::new(format!(
"Unable to access/open log file at path {:?}",
paths::LOG.as_path()
))
})
});
return;
};
let project = workspace.project().clone();
let buffer = project
.update(cx, |project, cx| project.create_buffer("", None, cx))