You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.8 KiB

  1. use std::io::{stderr, Write};
  2. use log::{warn, LevelFilter};
  3. use log4rs::{
  4. append::{
  5. console::ConsoleAppender,
  6. rolling_file::{
  7. policy::compound::{
  8. roll::fixed_window::FixedWindowRoller, trigger::size::SizeTrigger, CompoundPolicy,
  9. },
  10. RollingFileAppender,
  11. },
  12. },
  13. config::{Appender, Config, Root},
  14. encode::pattern::PatternEncoder,
  15. file::{Deserializers, RawConfig},
  16. init_config,
  17. };
  18. use serde_yaml::from_str;
  19. use crate::{misc::Vfs, Error};
  20. pub fn init(vfs: &Vfs) {
  21. let (config, err) = match load_from_file(vfs) {
  22. Ok(config) => (config, None),
  23. Err(err) => (default_config(), Some(err)),
  24. };
  25. init_config(config).expect("Unable to initialize logger");
  26. if let Some(err) = err {
  27. warn!("Unable to load log config from file: {}", err);
  28. }
  29. }
  30. fn load_from_file(vfs: &Vfs) -> Result<Config, Error> {
  31. let mut config = String::default();
  32. vfs.join("resources/log4rs.yml")?
  33. .open_file()?
  34. .read_to_string(&mut config)?;
  35. let mut stderr = stderr();
  36. let config = from_str::<RawConfig>(&config)?;
  37. let deserializers = Deserializers::default();
  38. let (appenders, errors) = config.appenders_lossy(&deserializers);
  39. for error in &errors {
  40. let _ = writeln!(stderr, "log: {}", error);
  41. }
  42. let (config, errors) = Config::builder()
  43. .appenders(appenders)
  44. .loggers(config.loggers())
  45. .build_lossy(config.root());
  46. for error in &errors {
  47. let _ = writeln!(stderr, "log: {}", error);
  48. }
  49. Ok(config)
  50. }
  51. #[allow(clippy::identity_op)]
  52. fn default_config() -> Config {
  53. let mut root = Root::builder();
  54. let mut config = Config::builder();
  55. let encoder = PatternEncoder::new("[{d} {h({l:>5})}] {m}{n}");
  56. let stdout = ConsoleAppender::builder()
  57. .encoder(Box::new(encoder))
  58. .build();
  59. root = root.appender("stdout");
  60. config = config.appender(Appender::builder().build("stdout", Box::new(stdout)));
  61. if let Ok(roller) = FixedWindowRoller::builder()
  62. .base(1)
  63. .build("space-crush-{}.log", 5)
  64. {
  65. let path = "space-crush.log";
  66. let trigger = SizeTrigger::new(1 * 1024 * 1024);
  67. let policy = CompoundPolicy::new(Box::new(trigger), Box::new(roller));
  68. let encoder = PatternEncoder::new(
  69. "{d} {h({l:<5})}{n} Module: {M}{n} File: {f}:{L}{n} Message: {m}{n}",
  70. );
  71. if let Ok(file) = RollingFileAppender::builder()
  72. .append(true)
  73. .encoder(Box::new(encoder))
  74. .build(path, Box::new(policy))
  75. {
  76. root = root.appender("file");
  77. config = config.appender(Appender::builder().build("file", Box::new(file)));
  78. }
  79. }
  80. config
  81. .build(root.build(LevelFilter::Info))
  82. .expect("Unable to create default log config")
  83. }