New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

logtrace

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry
This package has malicious versions linked to the ongoing "North Korea’s Contagious Interview Campaign" supply chain attack.

Affected versions:

1.0.11.0.2
View campaign page

logtrace

unpublished
Source
crates.io
Version
1.0.2
Version published
Maintainers
1
Created
Source

logtrace logo

CI Ubuntu Crates.io MSRV

Table of Contents

TL;DR

Installing the library

cargo add logtrace

Quick start

# use logtrace::{debug, info, warn, err, fatal};
debug!("This is a debug message!");
info!("This is an info message!");
warn!("This is a warning!");
err!("This is an error!");
fatal!("This is a fatal error!");

The Logger

The Logger struct only handles log filtering, relying on LogFormatter and LogOutput for formatting and outputting the logs.

Creating a Logger struct with default configuration:

# use logtrace::Logger;
let mut logger = Logger::default();

Log filtering

Logs are filtered based on their importance and the verbosity setting.

Setting logger verbosity:

# use logtrace::{Logger, config::Verbosity};
# let mut logger = Logger::default();
logger.set_verbosity(Verbosity::All);

Toggling log filtering:

# use logtrace::{Logger, config::Verbosity};
# let mut logger = Logger::default();
logger.enable_log_filtering();
logger.disable_log_filtering();

Logger templates

A Logger template is serialized Logger struct in JSON format. Logger templates can be used to easily manage and store logger configurations in files.

Here’s an example of what a serialized Logger struct looks like in JSON:

{
  "formatter": {
    "log_header_color_enabled": true,
    "debug_color": "Blue",
    "info_color": "Green",
    "warning_color": "Yellow",
    "error_color": "Red",
    "fatal_color": "Magenta",
    "debug_header": "DBG",
    "info_header": "INF",
    "warning_header": "WAR",
    "error_header": "ERR",
    "fatal_header": "FATAL",
    "log_format": "[%h] %m",
    "datetime_format": "%Y-%m-%d %H:%M:%S"
  },
  "output": {
    "stderr_output": {
      "enabled": true
    },
    "file_output": {
      "enabled": false,
      "max_buffer_size": 128,
      "on_drop_policy": "DiscardLogBuffer"
    },
    "buffer_output": {
      "enabled": false
    },
    "enabled": true
  },
  "verbosity": "Standard",
  "filtering_enabled": true
}

Loading Logger from a template file:

# use logtrace::Logger;
# let mut path = std::env::temp_dir();
# path.push("logtrace-tests/readme-logger-loading.json");
# let path = path.to_str().unwrap().to_string();
# Logger::default().save_template(&path);
let mut logger = Logger::from_template(&path);

Deserializing Logger from a JSON string:

# use logtrace::Logger;
// Obtain a deserializable string
let raw_json = serde_json::to_string(&Logger::default())
    .expect("Failed to serialize logger!");

// Deserialize `Logger` from a string
let logger = Logger::from_template_str(&raw_json)
    .expect("Failed to deserialize logger!");
# assert_eq!(Logger::default(), logger);

Saving Logger to a template file:

# use logtrace::Logger;
# let mut path = std::env::temp_dir();
# path.push("logtrace-tests/readme-logger-saving.json");
# let path = &path.to_str().unwrap().to_string();
let mut logger = Logger::default();
logger.save_template(path);

Global logger instance

The logtrace crate defines a global logger instance wrapped in RwLock, which you can share between multiple threads.

Modifying the global logger configuration:

# use logtrace::{glob::LOGGER, config::Verbosity};
// Get write access to the logger
let mut logger = LOGGER.write().unwrap();

// Modify the logger
logger.set_verbosity(Verbosity::All);

Using the global logger:

# use logtrace::glob::LOGGER;
// Get read access to the logger
let logger = LOGGER.read().unwrap();

// Print some logs
logger.info("Hello, World!");

Requiring read access to the global logger in every function you use is tedious, isn't it? Furthermore, because its methods only accept &str as message arguments, you’d have to handle all message formatting yourself.

Fortunately, there is a set of macros designed just to solve this issue.

Using logging macros to print some messages with the global logger:

# use logtrace::{debug, info, warn, err, fatal};
debug!("This is a debug message!");
info!("This is an info message!");
warn!("This is a warning!");
err!("This is an error!");
fatal!("This is a fatal error!");

Logging macros accept arguments just like the format! macro:

# use logtrace::info;
let some_value = 32;
let name = "User";

info!("Hello {name}, `some_value` is {some_value}.");

[!WARNING] Since the logging macros acquire read access to the global logger under the hood, they will block your thread if there is another process with write access to the logger.

This will block the thread:

# use logtrace::{info, glob::LOGGER};
// Get write access to the logger
let mut logger = LOGGER.write().unwrap();

// Trying to use logging macro blocks the thread
info!("This will never be shown!");

Log formatting

LogFormatter

The LogFormatter struct manages log formatting. It's accessible as a field within Logger, but can also operate independently.

Using a LogFormatter:

# use logtrace::{
#    config::LogStruct,
#    format::LogFormatter,
# };
// Create a `LogFormatter` with default configuration
let mut formatter = LogFormatter::default();

// Set a log format
formatter.set_log_format("[ %h %m ]");

// Obtain a formatted log from a `LogStruct`
let log = formatter.format_log(&LogStruct::debug("Hello from LogStruct!"));

// Print the formatted log message
print!("{}", &log);

Log format

A log consists of several headers:

  • Log Type The type of the log (debug, info, warning etc.)
  • Timestamp Contains the date and time the log was created
  • Message The actual log message

These headers can then be formatted using a log format string, similarly to how you would format datetime with a datetime format string.

Here is a log message with all its headers marked:

[ DEBUG 21:52:37 An example debug message ]
  ^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
  |     |        |
  |     |        the message
  |     timestamp
  log type

This specific effect was achieved by setting the datetime format to %H:%M:%S, log format to [ %h %d %m ] and the debug log type header to DEBUG.

Setting datetime format of a LogFormatter:

# use logtrace::format::LogFormatter;
let mut formatter = LogFormatter::default();
formatter.set_datetime_format("%H:%M:%S");

Setting a custom log format:

# use logtrace::format::LogFormatter;
let mut formatter = LogFormatter::default();
formatter.set_log_format("[ %h %d %m ]");

[!NOTE] The %m (message) placeholder is mandatory. You will get an error unless you include it in your format string.

Customizing log headers:

# use logtrace::format::LogFormatter;
let mut formatter = LogFormatter::default();
formatter.set_debug_header("DEBUG");
formatter.set_info_header("INFO");
formatter.set_warning_header("WARNING");
formatter.set_error_header("ERROR");
formatter.set_fatal_header("FATAL ERROR");

Setting custom log header colors:

# use logtrace::{
#     format::LogFormatter,
#     colors::Color
# };
let mut formatter = LogFormatter::default();
formatter.set_debug_color(Color::Blue);
formatter.set_info_color(Color::Green);
formatter.set_warning_color(Color::Yellow);
formatter.set_error_color(Color::Red);
formatter.set_fatal_color(Color::Magenta);

Using the LogStruct

LogStruct is a type that represents a single log entry. This is the raw, non-formatted log message used internally by Logger, LogFormatter and log streams.

Creating a LogStruct and formatting it with a LogFormatter:

# use logtrace::{
#     format::LogFormatter,
#     config::LogStruct
# };
let mut formatter = LogFormatter::default();

// Create a `LogStruct`
let raw_log = LogStruct::debug("Hello from a struct!");

// Format the `LogStruct`
let formatted_log = formatter.format_log(&raw_log);

// Print the formatted log
print!("{}", &formatted_log);

Log outputs

Log outputs determine how messages are routed, delivering logs to specific destinations like standard error (StderrStream) or a dedicated log file (FileStream). Each output can be selectively toggled. Additionally, the parent output provides an overall control mechanism; disabling it effectively halts all child streams.

LogOutput (parent)

LogOutput is used internally by the Logger struct for handling it's child output streams. Toggling it affects all of its child streams.

StderrStream

This is the simplest of the log outputs. It formats the given log using the formatter and prints it to stderr.

Printing a log to stderr:

# use logtrace::{
#     output::StderrStream,
#     format::LogFormatter,
#     config::LogStruct,
# };
// Required by `StderrStream` for parsing logs
let mut formatter = LogFormatter::default();

// Enabled by default
let mut stderr_output = StderrStream::default();

// Print "Hello, World!" in a neat format
stderr_output.out(&LogStruct::debug("Hello, World!"), &mut formatter);

BufferStream

When enabled, BufferStream stores raw logs in an internal buffer. This means that it doesn't need a formatter.

Using BufferStream:

# use logtrace::{
#     output::BufferStream,
#     output::Toggleable,
#     config::LogStruct,
# };
let mut buffer_stream = BufferStream::default();

// Enable the buffer stream
buffer_stream.enable();

// Write to the buffer 128 times
for i in 0..128 {
    buffer_stream.out(&LogStruct::debug(&format!("Log number {}", i)));
}

// Get a reference to the log buffer
let buffer = buffer_stream.get_log_buffer();
# assert_eq!(buffer.len(), 128);

// Do whatever you wish with the log buffer here

// Clear the log buffer
buffer_stream.clear();

FileStream

FileStream is used for storing logs in a log file. FileStream utilizes an internal log buffer for storing already formatted log messages until they are written to the log file.

Using FileStream:

# use logtrace::{
#     config::LogStruct,
#     format::LogFormatter,
#     output::{Toggleable, FileStream},
# };
# let mut path = std::env::temp_dir();
# path.push("logtrace-tests/readme-file-stream-doc1.log");
# let path = &path.to_str().unwrap().to_string();
let mut formatter = LogFormatter::default();

let mut file_stream = FileStream::default();

// Set the log file path before enabling the stream
file_stream.set_log_file_path(&path)
    .expect("Failed setting log file path!");

// Enable the stream after the log file path has been set
file_stream.enable()
    .expect("Failed enabling the file stream!");

// Write to the log buffer
file_stream.out(&LogStruct::debug("Hello from a file!"), &mut formatter)
    .expect("Failed outing to the file stream!");

// Write the contents of the log buffer to the log file
file_stream.flush()
    .expect("Failed flushing the file stream!");

[!NOTE] The log file path has to be set in order to enable and use the file stream.

Automatic log buffer flushing

FileStream can automatically write to the log file when its log buffer exceeds a specific limit. Setting this limit to None will disable this feature.

Example:

# use logtrace::{
#     output::{FileStream, Toggleable},
#     format::LogFormatter,
#     config::LogStruct,
# };
# let mut path = std::env::temp_dir();
# path.push("logtrace-tests/readme-file-stream-doc2.log");
# let path = &path.to_str().unwrap().to_string();
let mut formatter = LogFormatter::default();

// Configure the `FileStream`
let mut file_stream = FileStream::default();
file_stream.set_log_file_path(&path)
    .expect("Failed setting log file path!");
file_stream.enable()
    .expect("Failed enabling the file stream!");

// Set the log file buffer limit to 128
file_stream.set_max_buffer_size(Some(128));

// Write to the log buffer 128 times
for i in 0..128 {
    file_stream.out(&LogStruct::debug("Hello!"), &mut formatter)
        .expect("Failed to out to the log buffer!");
}
// Here the log buffer will automatically be flushed.

Locking the log file

The log file can be locked to prevent race conditions when there are multiple threads accessing it at the same time. It stops FileStream from writing to it until the lock has been released. The lock is only ignored when FileStream is being dropped and the OnDropPolicy is set to IgnoreLogFileLock (off by default).

Toggling the lock:

# use logtrace::output::FileStream;
# let mut file_stream = FileStream::default();
// Lock the log file
file_stream.lock_file();

// Unlock the log file
file_stream.unlock_file();

Setting on drop policy:

# use logtrace::{
#     output::FileStream,
#     config::OnDropPolicy,
# };
# let mut file_stream = FileStream::default();
file_stream.set_on_drop_policy(OnDropPolicy::IgnoreLogFileLock);

FAQs

Package last updated on 01 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts