Skip to content

Commit

Permalink
feat(libmake): ✨ new loggers functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienrousseau committed Nov 6, 2023
1 parent 9ac83c4 commit 7fcdabf
Show file tree
Hide file tree
Showing 8 changed files with 516 additions and 10 deletions.
4 changes: 2 additions & 2 deletions .deepsource.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ version = 1
name = "rust"
enabled = true

[analyzers.meta]
msrv = "stable"
[analyzers.meta]
msrv = "stable"
30 changes: 30 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright © 2023 LibMake. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 OR MIT

# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4

[*.rs]
max_line_length = 80

[*.md]
# double whitespace at end of line
# denotes a line break in Markdown
trim_trailing_whitespace = false

[*.yml]
indent_size = 2

[Makefile]
indent_style = tab
16 changes: 9 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
authors = ["Sebastien Rousseau <[email protected]>}"]
authors = ["Sebastien Rousseau <[email protected]>"]
categories = ['development-tools', 'command-line-utilities', 'template-engine']
description = "A code generator to reduce repetitive tasks and build high-quality Rust libraries."
edition = "2021"
Expand Down Expand Up @@ -42,15 +42,17 @@ debug = true

[dependencies]
assert_cmd = "2.0.12"
clap = "4.4.6"
clap = "4.4.7"
csv = "1.3.0"
dtt = "0.0.4"
figlet-rs = "0.1.5"
openssl = { version = "0.10.57", features = ["vendored"] }
# openssl = { version = "0.10.59", features = ["vendored"] }
reqwest = { version = "0.11.22", features = ["blocking"] }
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.107"
serde_yaml = "0.9.25"
toml = "0.8.2"
serde = { version = "1.0.190", features = ["derive"] }
serde_json = "1.0.108"
serde_yaml = "0.9.27"
toml = "0.8.6"
vrd = "0.0.4"

[dev-dependencies]
criterion = "0.5.1"
Expand Down
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
fn main() {
// Avoid unnecessary re-building.
println!("cargo:rerun-if-changed=build.rs");
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ pub mod generator;
/// The `interface` module contains functions for displaying the
/// interface.
pub mod interface;
/// The `loggers` module contains the loggers for the library.
pub mod loggers;
/// The `macros` module contains functions for generating macros.
pub mod macros;
/// The `utils` module contains a function for reading a CSV file at the
Expand Down
243 changes: 243 additions & 0 deletions src/loggers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
// Copyright © 2023 LibMake. All rights reserved.
// SPDX-License-Identifier: Apache-2.0 OR MIT

// Standard library imports for formatting and I/O operations.
use std::{
fmt,
fs::OpenOptions,
io::{self, Write as IoWrite},
};

/// Enum representing the different log formats that can be used.
///
/// This enum allows the developer to specify the format in which log messages should be displayed.
///
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd)]
pub enum LogFormat {
/// The log format is set to the Common Log Format (CLF)
CLF,
/// The log format is set to the JSON format
JSON,
/// The log format is set to the Common Event Format (CEF)
CEF,
/// The log format is set to the Extended Log Format (ELF)
ELF,
/// The log format is set to the W3C Extended Log File Format
W3C,
/// The log format is set to the Graylog Extended Log Format (GELF)
GELF,
}

/// Implements Display trait for `LogFormat` enum.
///
/// This allows easy conversion of the log format enums to strings.
impl fmt::Display for LogFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "{self:?}")
}
}

/// An enumeration of the different levels that a log message can have.
/// Each variant of the enumeration represents a different level of
/// importance.
///
/// # Arguments
///
/// * `ALL` - The log level is set to all.
/// * `DEBUG` - The log level is set to debug.
/// * `DISABLED` - The log level is set to disabled.
/// * `ERROR` - The log level is set to error.
/// * `FATAL` - The log level is set to fatal.
/// * `INFO` - The log level is set to info.
/// * `NONE` - The log level is set to none.
/// * `TRACE` - The log level is set to trace.
/// * `VERBOSE` - The log level is set to verbose.
/// * `WARNING` - The log level is set to warning.
///
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd)]
pub enum LogLevel {
/// The log level is set to all.
ALL,
/// The log level is set to debug.
DEBUG,
/// The log level is set to disabled.
DISABLED,
/// The log level is set to error.
ERROR,
/// The log level is set to fatal.
FATAL,
/// The log level is set to info.
INFO,
/// The log level is set to none.
NONE,
/// The log level is set to trace.
TRACE,
/// The log level is set to verbose.
VERBOSE,
/// The log level is set to warning.
WARNING,
}
/// Display trait implementation for `LogLevel`.
///
/// This converts the enum to a string representation.
impl fmt::Display for LogLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}

/// Struct representing a log message.
///
/// Contains all the elements that make up a complete log message.
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct Log {
/// A string that holds a session ID. The session ID is a unique
/// identifier for the current session. A random GUID (Globally
/// Unique Identifier) is generated by default.
pub session_id: String,
/// A string that holds the timestamp in ISO 8601 format.
pub time: String,
/// A string that holds the level (INFO, WARN, ERROR, etc.).
pub level: LogLevel,
/// A string that holds the component name.
pub component: String,
/// A string that holds the description of the log message.
pub description: String,
/// A string that holds the log format.
pub format: LogFormat,
}

impl Log {
/// Logs a message to the console using a pre-allocated buffer to
/// reduce memory allocation and flush the output buffer to ensure
/// that the message is written immediately.
///
/// # Errors
///
/// This function will panic if an error occurs when writing to the
/// pre-allocated buffer or flushing the output buffer.
pub fn log(&self) -> io::Result<()> {
// Open the file in append mode. If the file does not exist, create it.
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open("libmake.log")?;
match self.format {
LogFormat::CLF => {
writeln!(
file,
"SessionID={}\tTimestamp={}\tDescription={}\tLevel={}\tComponent={}\tFormat={}",
self.session_id,
self.time,
self.description,
self.level,
self.component,
self.format
)
}
LogFormat::JSON => {
writeln!(
file,
r#"{{"session_id": "{}", "timestamp": "{}", "description": "{}", "level": "{}", "component": "{}", "format": "{}"}}"#,
self.session_id,
self.time,
self.description,
self.level,
self.component,
self.format
)
}
LogFormat::CEF => {
writeln!(
file,
r#"[CEF]
<Event xmlns="http://www.w3.org/2003/05/events/Log">
<LogID>1</LogID>
<SourceName>LibMake</SourceName>
<SourceType>Application</SourceType>
<EventReceivedTime>{}</EventReceivedTime>
<EventType>Log</EventType>
<Severity>{}</Severity>
<Message>{}</Message>
<SessionID>{}</SessionID>
<HostName>localhost</HostName>
<ComputerName>localhost</ComputerName>
<UserID>-</UserID>
<ThreadID>-</ThreadID>
<FileName>-</FileName>
<LineNumber>-</LineNumber>
<ProcessID>-</ProcessID>
<ModuleID>-</ModuleID>
</Event>
"#,
self.time,
self.level,
self.description,
self.session_id
)
}
_ => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Unsupported log format",
)),
}?;
file.flush()?;
Ok(())
}

/// Creates a new `Log` instance.
///
/// Initializes a new `Log` struct with the provided details.
///
/// # Returns
///
/// Returns a new instance of the `Log` struct.
pub fn new(
session_id: &str,
time: &str,
level: LogLevel,
component: &str,
description: &str,
format: LogFormat,
) -> Self {
Self {
session_id: session_id.to_string(),
time: time.to_string(),
level,
component: component.to_string(),
description: description.to_string(),
format,
}
}
}

/// Provides default values for `Log`.
///
/// This implementation provides a quick way to generate a `Log` instance with default values.
impl Default for Log {
fn default() -> Self {
Self {
session_id: String::default(),
time: String::default(),
level: LogLevel::INFO, // Default log level
component: String::default(),
description: String::default(),
format: LogFormat::CLF, // Default log format
}
}
}
#[cfg(test)]
/// Tests for the `log_info!` macro.
mod tests {
use crate::macro_log_info;

#[test]
fn test_log_info() {
macro_log_info!(
LogLevel::INFO,
"component",
"description",
LogFormat::CLF
);
}
}
Loading

0 comments on commit 7fcdabf

Please sign in to comment.