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
2 changes: 2 additions & 0 deletions src/helper.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Internal helper functions for time handling and file I/O.

use chrono::{self, Datelike, Timelike};
use std::io::Write;
use thiserror::Error;
Expand Down
5 changes: 5 additions & 0 deletions src/logger/archivation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! Helper utilities for log file archiving.
//!
//! This module exposes functions to determine archive locations and ensure
//! directories are created when needed.

use std::path::PathBuf;

use crate::CONFIG;
Expand Down
6 changes: 6 additions & 0 deletions src/logger/file_handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! Infrastructure for log file output.
//!
//! This module groups together helpers responsible for formatting log file
//! names, managing file rotation and compression, and writing log entries to
//! disk.

pub(crate) mod file_formatter;
pub(crate) mod file_manager;
pub(crate) mod file_name;
Expand Down
12 changes: 12 additions & 0 deletions src/logger/file_handler/file_formatter.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
//! Parser for file name templates used when creating log files.
//!
//! [`FileFormatter`] validates that a user supplied pattern is safe for file
//! creation and produces a sequence of [`LogPart`]s that can later be expanded
//! into a concrete file name.

use crate::logger::formatter::LogPart;

use thiserror::Error;

#[derive(Clone, Debug)]
/// Internal representation of a validated file name pattern.
pub(crate) struct FileFormatter {
pub(crate) format: Vec<LogPart>,
}

#[derive(Debug, Error)]
/// Errors that can occur while parsing a file name template.
pub enum FileFormatterTryFromStringError {
#[error("an incorrect character given: {0}")]
IncorrectCharacterGiven(char),
Expand All @@ -26,6 +34,10 @@ impl FileFormatter {
fn forbidden_characters() -> [char; 4] {
['<', '>', '&', '%']
}
/// Parses a template string into a [`FileFormatter`].
///
/// Ensures that only allowed placeholders are present and that the
/// resulting file name ends with a valid extension (`.txt` or `.log`).
pub(crate) fn try_from_string(
format: &str,
) -> Result<FileFormatter, FileFormatterTryFromStringError> {
Expand Down
11 changes: 11 additions & 0 deletions src/logger/file_handler/file_manager.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! Handles creation, rotation and optional compression of log files.
//!
//! [`FileManager`] keeps track of the current log file and ensures it is
//! rotated when constraints are met (time, size or period). It is an internal
//! component used by the higher level configuration functions in [`crate::logger`].

use std::{
fs::File,
io::{self, BufReader},
Expand All @@ -19,6 +25,10 @@ use super::{
};

#[derive(Clone, Debug)]
/// Central structure responsible for writing log records to files.
///
/// It owns the current log file and metadata used to decide when a new file
/// should be created.
pub(crate) struct FileManager {
file_format: FileFormatter,
file_name: FileName,
Expand All @@ -27,6 +37,7 @@ pub(crate) struct FileManager {
}

#[derive(Error, Debug)]
/// Errors produced when creating a [`FileManager`] from a format string.
pub enum FileManagerFromStringError {
#[error("string parsing for the file format error: {0}")]
FileFormatParsingError(FileFormatterTryFromStringError),
Expand Down
13 changes: 11 additions & 2 deletions src/logger/file_handler/file_name.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
//! Representation and manipulation of log file names.
//!
//! [`FileName`] constructs a concrete file name from a pattern provided by
//! [`FileFormatter`]. It also supports incrementing the name when multiple files
//! with the same base name are created.

use crate::{helper, Level};

use crate::logger::formatter::LogPart;

use super::file_formatter::FileFormatter;
use thiserror::Error;
#[derive(Debug, Clone)]
/// File name generated from a [`FileFormatter`] pattern.
pub(crate) struct FileName {
file_name: String,
file_num: Option<u32>,
file_extension: String,
}

#[derive(Debug, Error)]
/// Errors that can occur while converting a [`FileFormatter`] into a file name.
pub enum FileNameFromFileFormatterError {
#[error("no fomrat provided")]
NoFormatProvided,
Expand Down Expand Up @@ -39,7 +47,7 @@ impl FileName {
Some(num) => self.file_num = Some(num + 1),
};
}
// pub(crate)
/// Expands a list of [`LogPart`] values into a concrete file name string.
pub fn get_string_from_log_parts(parts: Vec<LogPart>, level: Level) -> String {
let time_str = helper::get_current_time_in_string();
let date_str = helper::get_current_date_in_string();
Expand All @@ -59,7 +67,7 @@ impl FileName {
}
res
}
//pub(crate)
/// Build a [`FileName`] from a [`FileFormatter`] using the provided log level.
pub fn from_file_formatter(
format: FileFormatter,
level: Level,
Expand Down Expand Up @@ -99,6 +107,7 @@ impl FileName {
file_extension: extension.to_string(),
})
}
/// Returns the full file name including any appended index and extension.
pub(crate) fn get_full_file_name(&self) -> String {
String::from(self.to_owned())
}
Expand Down
25 changes: 23 additions & 2 deletions src/logger/formatter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
//! Utilities for parsing user provided log formatting templates.
//!
//! This module converts strings like `"<green>[{level}]<green> {message}"` into
//! [`LogFormatter`] structures used internally by the logger. It exposes
//! helper enums and functions to interpret color tags and placeholder blocks.

use thiserror::Error;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
/// Colors that can be applied to portions of a formatted log message.
pub(crate) enum LogColor {
Red,
Green,
Expand Down Expand Up @@ -56,6 +63,7 @@ impl LogColor {
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// A single placeholder or text fragment parsed from a format string.
pub(crate) enum LogPart {
Message,
Time,
Expand Down Expand Up @@ -99,17 +107,27 @@ impl From<String> for LogPart {
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// Internal helper tying a [`LogPart`] with an optional [`LogColor`].
pub(crate) struct LogFormatWrapper {
pub(crate) color: Option<LogColor>,
pub(crate) part: LogPart,
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// Representation of a parsed format string.
///
/// The struct stores a sequence of [`LogFormatWrapper`] elements that
/// correspond to the parts of the user provided template.
pub(crate) struct LogFormatter {
pub(crate) parts: Vec<LogFormatWrapper>,
}

impl LogFormatter {
/// Parses a format template into a [`LogFormatter`].
///
/// # Errors
/// Returns [`ParseStringToWrappersError`] when the string contains
/// unsupported placeholders or malformed color tags.
pub(crate) fn parse_from_string(text: &str) -> Result<Self, ParseStringToWrappersError> {
let wrappers = parse_string_to_wrappers(text)?;
Ok(LogFormatter { parts: wrappers })
Expand All @@ -130,7 +148,10 @@ pub enum ParseStringToWrappersError {
UnableToParsePartsToFormatter(ParsePartsToFormatterError),
}

/// Parse string to log_wrappers i.e Vec of log_part and assigned color to it
/// Parses a template into a vector of [`LogFormatWrapper`]s.
///
/// The returned wrappers combine [`LogPart`] placeholders with optional
/// [`LogColor`] information extracted from angle bracket tags.
pub(crate) fn parse_string_to_wrappers(
text: &str,
) -> Result<Vec<LogFormatWrapper>, ParseStringToWrappersError> {
Expand All @@ -146,7 +167,7 @@ pub(crate) fn parse_string_to_wrappers(
.map_err(ParseStringToWrappersError::UnableToParsePartsToFormatter)
}

/// Parse string to log_parts
/// Converts a template into a simple list of [`LogPart`]s.
pub(crate) fn parse_string_to_logparts(
text: &str,
) -> Result<Vec<LogPart>, ParseStringToWrappersError> {
Expand Down
6 changes: 6 additions & 0 deletions src/logger/from_env.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! Load configuration options from environment variables.
//!
//! The variables follow the same naming as the configuration file fields, such
//! as `level`, `print_to_terminal` or `file_name`.

use std::env;

use crate::logger::from_file_config::{parse_inter_config_from_serde_config, ConfigForSerde};
Expand Down Expand Up @@ -62,6 +67,7 @@ fn parse_config_from_env() -> Result<ConfigForSerde, ReadFromConfigFileError> {
Ok(res_conf)
}

/// Read environment variables and apply them to the logger configuration.
pub(crate) fn load_config_from_env() -> Result<(), ReadFromConfigFileError> {
let serde_conf = parse_config_from_env()?;
let inter_conf = parse_inter_config_from_serde_config(serde_conf)
Expand Down
7 changes: 5 additions & 2 deletions src/logger/from_file_config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// this module aims to provide a feature of setting the config up from a file (without explicitely
// precising it in the file (but make it still possible))
//! Parse configuration files in `ini`, `json` or `env` formats.
//!
//! The resulting settings are converted into [`crate::logger`] configuration
//! using [`InterConfig`].

use std::io::Read;

Expand Down Expand Up @@ -392,6 +394,7 @@ pub(crate) fn parse_inter_config_from_serde_config(
s_conf.try_into()
}

/// Load configuration from the specified file and apply it to the logger.
pub(crate) fn load_config_from_file(path: &str) -> Result<(), ReadFromConfigFileError> {
let parse_conf = parse_config_file(path)?;
let inter_conf = parse_inter_config_from_serde_config(parse_conf)
Expand Down
3 changes: 3 additions & 0 deletions src/logger/set_errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Error types used throughout the configuration helpers.

use crate::logger;
use thiserror::Error;

Expand All @@ -6,6 +8,7 @@ use super::{
};

#[derive(Debug, thiserror::Error)]
/// Errors while accessing or mutating the global configuration.
pub enum AccessError {
#[error("unable to load config")]
LoadConfig,
Expand Down