@@ -0,0 +1,122 @@
+use chrono::Offset;
+use env_logger::Builder;
+use log::LevelFilter;
+use simplelog::ConfigBuilder;
+use std::fs::{self, File, OpenOptions};
+use std::io::{self, Write};
+use time::UtcOffset;
+
+pub fn init_logger() {
+ let level = LevelFilter::Info;
+
+ // Prevent log file from becoming too large.
+ const KIB: u64 = 1024;
+ const MIB: u64 = 1024 * KIB;
+ const MAX_LOG_BYTES: u64 = MIB;
+ if std::fs::metadata(paths::log_file()).map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
+ {
+ let _ = std::fs::rename(paths::log_file(), paths::old_log_file());
+ }
+
+ match LogWriter::new(MAX_LOG_BYTES) {
+ Ok(writer) => {
+ let mut config_builder = ConfigBuilder::new();
+
+ config_builder.set_time_format_rfc3339();
+ let local_offset = chrono::Local::now().offset().fix().local_minus_utc();
+ if let Ok(offset) = UtcOffset::from_whole_seconds(local_offset) {
+ config_builder.set_time_offset(offset);
+ }
+
+ #[cfg(any(target_os = "linux", target_os = "freebsd"))]
+ {
+ config_builder.add_filter_ignore_str("zbus");
+ config_builder.add_filter_ignore_str("blade_graphics::hal::resource");
+ config_builder.add_filter_ignore_str("naga::back::spv::writer");
+ }
+
+ let config = config_builder.build();
+ simplelog::WriteLogger::init(level, config, writer)
+ .expect("could not initialize logger");
+ }
+ Err(err) => {
+ init_stdout_logger();
+ log::error!(
+ "could not open log file, defaulting to stdout logging: {}",
+ err
+ );
+ }
+ }
+}
+
+pub fn init_stdout_logger() {
+ Builder::new()
+ .parse_default_env()
+ .format(|buf, record| {
+ use env_logger::fmt::style::{AnsiColor, Style};
+
+ let subtle = Style::new().fg_color(Some(AnsiColor::BrightBlack.into()));
+ write!(buf, "{subtle}[{subtle:#}")?;
+ write!(
+ buf,
+ "{} ",
+ chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z")
+ )?;
+ let level_style = buf.default_level_style(record.level());
+ write!(buf, "{level_style}{:<5}{level_style:#}", record.level())?;
+ if let Some(path) = record.module_path() {
+ write!(buf, " {path}")?;
+ }
+ write!(buf, "{subtle}]{subtle:#}")?;
+ writeln!(buf, " {}", record.args())
+ })
+ .init();
+}
+
+struct LogWriter {
+ file: File,
+ max_size: u64,
+ current_size: u64,
+}
+
+impl LogWriter {
+ fn new(max_size: u64) -> io::Result<Self> {
+ let file = OpenOptions::new()
+ .create(true)
+ .append(true)
+ .open(paths::log_file())?;
+ let current_size = file.metadata()?.len();
+
+ Ok(LogWriter {
+ file,
+ max_size,
+ current_size,
+ })
+ }
+
+ fn replace(&mut self) -> io::Result<()> {
+ self.file.sync_all()?;
+ fs::rename(paths::log_file(), paths::old_log_file())?;
+ self.file = OpenOptions::new()
+ .create(true)
+ .append(true)
+ .open(paths::log_file())?;
+ self.current_size = 0;
+ Ok(())
+ }
+}
+
+impl Write for LogWriter {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ if self.current_size + buf.len() as u64 > self.max_size {
+ self.replace()?;
+ }
+ let bytes = self.file.write(buf)?;
+ self.current_size += bytes as u64;
+ Ok(bytes)
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.file.flush()
+ }
+}
@@ -1,11 +1,11 @@
// Disable command line from opening on release mode
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
+mod logger;
mod reliability;
mod zed;
use anyhow::{anyhow, Context as _, Result};
-use chrono::Offset;
use clap::{command, Parser};
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
use client::{parse_zed_link, Client, ProxySettings, UserStore};
@@ -13,7 +13,6 @@ use collab_ui::channel_view::ChannelView;
use collections::HashMap;
use db::kvp::{GLOBAL_KEY_VALUE_STORE, KEY_VALUE_STORE};
use editor::Editor;
-use env_logger::Builder;
use extension::ExtensionHostProxy;
use extension_host::ExtensionStore;
use fs::{Fs, RealFs};
@@ -24,11 +23,11 @@ use gpui::{App, AppContext as _, Application, AsyncApp, UpdateGlobal as _};
use gpui_tokio::Tokio;
use http_client::{read_proxy_from_env, Uri};
use language::LanguageRegistry;
-use log::LevelFilter;
use prompt_library::PromptBuilder;
use reqwest_client::ReqwestClient;
use assets::Assets;
+use logger::{init_logger, init_stdout_logger};
use node_runtime::{NodeBinaryOptions, NodeRuntime};
use parking_lot::Mutex;
use project::project_settings::ProjectSettings;
@@ -36,11 +35,9 @@ use recent_projects::{open_ssh_project, SshSettings};
use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
use session::{AppSession, Session};
use settings::{watch_config_file, Settings, SettingsStore};
-use simplelog::ConfigBuilder;
use std::{
env,
- fs::OpenOptions,
- io::{self, IsTerminal, Write},
+ io::{self, IsTerminal},
path::{Path, PathBuf},
process,
sync::Arc,
@@ -49,7 +46,6 @@ use theme::{
ActiveTheme, IconThemeNotFoundError, SystemAppearance, ThemeNotFoundError, ThemeRegistry,
ThemeSettings,
};
-use time::UtcOffset;
use util::{maybe, ResultExt, TryFutureExt};
use uuid::Uuid;
use welcome::{show_welcome_view, BaseKeymap, FIRST_OPEN};
@@ -198,7 +194,11 @@ fn main() {
return;
}
- init_logger();
+ if stdout_is_a_pty() {
+ init_stdout_logger();
+ } else {
+ init_logger();
+ }
log::info!("========== starting zed ==========");
@@ -936,82 +936,6 @@ fn init_paths() -> HashMap<io::ErrorKind, Vec<&'static Path>> {
})
}
-fn init_logger() {
- if stdout_is_a_pty() {
- init_stdout_logger();
- } else {
- let level = LevelFilter::Info;
-
- // Prevent log file from becoming too large.
- const KIB: u64 = 1024;
- const MIB: u64 = 1024 * KIB;
- const MAX_LOG_BYTES: u64 = MIB;
- if std::fs::metadata(paths::log_file())
- .map_or(false, |metadata| metadata.len() > MAX_LOG_BYTES)
- {
- let _ = std::fs::rename(paths::log_file(), paths::old_log_file());
- }
-
- match OpenOptions::new()
- .create(true)
- .append(true)
- .open(paths::log_file())
- {
- Ok(log_file) => {
- let mut config_builder = ConfigBuilder::new();
-
- config_builder.set_time_format_rfc3339();
- let local_offset = chrono::Local::now().offset().fix().local_minus_utc();
- if let Ok(offset) = UtcOffset::from_whole_seconds(local_offset) {
- config_builder.set_time_offset(offset);
- }
-
- #[cfg(any(target_os = "linux", target_os = "freebsd"))]
- {
- config_builder.add_filter_ignore_str("zbus");
- config_builder.add_filter_ignore_str("blade_graphics::hal::resource");
- config_builder.add_filter_ignore_str("naga::back::spv::writer");
- }
-
- let config = config_builder.build();
- 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::style::{AnsiColor, Style};
-
- let subtle = Style::new().fg_color(Some(AnsiColor::BrightBlack.into()));
- write!(buf, "{subtle}[{subtle:#}")?;
- write!(
- buf,
- "{} ",
- chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z")
- )?;
- let level_style = buf.default_level_style(record.level());
- write!(buf, "{level_style}{:<5}{level_style:#}", record.level())?;
- if let Some(path) = record.module_path() {
- write!(buf, " {path}")?;
- }
- write!(buf, "{subtle}]{subtle:#}")?;
- writeln!(buf, " {}", record.args())
- })
- .init();
-}
-
fn stdout_is_a_pty() -> bool {
std::env::var(FORCE_CLI_MODE_ENV_VAR_NAME).ok().is_none() && io::stdout().is_terminal()
}