Skip to content

Commit

Permalink
add application logging
Browse files Browse the repository at this point in the history
add configuration of logging which save logs into dedicated files and
outputs logs into console (stderr) #NEU-9
  • Loading branch information
keinsell committed Feb 2, 2025
1 parent 0d9b3e8 commit ddf12b4
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 12 deletions.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ strum = "0.26.3"
human-panic = "2.0.2"
crossbeam = { version = "0.8.4", features = ["crossbeam-channel"] }
uuid = { version = "1.12.1", features = ["v4"] }
etcetera = "0.8.0"
tracing-appender = "0.2.3"

[features]
default = ["tui"]
Expand Down
74 changes: 74 additions & 0 deletions docs/logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Logging Configuration

Neuronek implements a comprehensive logging system that provides both file-based and console-based logging capabilities. The logging system is designed to be XDG-compliant and supports multiple output layers with different configurations.

## Log File Location

Log files are stored following the XDG Base Directory Specification:

- **Development/Debug Mode**: Logs are stored in the system's temporary directory as `neuronek.sqlite`
- **Production Mode**: Logs are stored in the XDG cache directory: `~/.cache/neuronek/logs/debug.log` (Linux) or equivalent on other platforms

## Logging Layers

The logging system implements two main layers:

### 1. File Appender

The file appender writes detailed logs to a file with the following characteristics:

- Includes file names and line numbers for precise error tracking
- Records thread IDs for concurrent operation debugging
- Maintains detailed context for debugging purposes
- Stores logs in the XDG-compliant directory structure

### 2. Console Appender

The console appender provides a streamlined output to stderr:

- Simplified output without file names or line numbers
- No thread IDs to keep the output clean
- ANSI color support for better readability
- Focused on user-relevant information
- Writes to stderr for clean JSON output compatibility

## Log Levels

The logging system supports multiple log levels through the `tracing` crate:

- ERROR: For critical issues that prevent normal operation
- WARN: For important issues that don't stop execution
- INFO: For general information about program operation
- DEBUG: For detailed information useful during development
- TRACE: For very detailed debugging information

By default, the logging level is set to INFO, but this can be adjusted through environment variables.

## Configuration

The logging system integrates with Neuronek's configuration system and respects the following settings:

- Log file location is determined by the application mode (debug/release)
- Environment variables can control the logging level
- XDG base directories are used for log file storage

## Usage Example

```rust
// Log messages at different levels
error!("Critical error occurred");
warn!("Warning: operation may be slow");
info!("Operation completed successfully");
debug!("Detailed debug information");
trace!("Very detailed trace information");
```

## Implementation Details

The logging system is implemented using the following crates:

- `tracing`: Core logging functionality
- `tracing-subscriber`: Logging subscriber implementation
- `etcetera`: XDG base directory handling

The setup is handled in `src/core/logging.rs` and integrates with the application's configuration system in `src/core/config.rs`.
54 changes: 42 additions & 12 deletions src/core/logging.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
// TODO: Implement logging
pub fn setup_logger()
{
// let log_file_path = std::env::current_dir().unwrap().join("debug.log");
// let _ = std::fs::remove_file(&log_file_path);
//
// use tracing_subscriber::fmt;
// use tracing_subscriber::prelude::*;
//
// let file_layer = fmt::layer().with_writer(std::fs::File::create(log_file_path).unwrap());
//
// tracing_subscriber::registry().with(file_layer).init();
use etcetera::base_strategy::{BaseStrategy, Xdg};
use std::fs::create_dir_all;
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_appender::non_blocking::WorkerGuard;

pub fn setup_logger() -> Result<WorkerGuard, Box<dyn std::error::Error>> {
// Get XDG data directory
let xdg = Xdg::new()?.cache_dir().join("neuronek").join("logs");
create_dir_all(&xdg)?;

let file_appender = RollingFileAppender::new(
Rotation::DAILY,
&xdg,
"neuronek"
);

let (non_blocking_appender, guard) = tracing_appender::non_blocking(file_appender);

let file_layer = fmt::layer()
.with_file(true)
.with_line_number(true)
.with_thread_ids(true)
.with_target(false)
.with_writer(non_blocking_appender);

let console_layer = fmt::layer()
.with_target(false)
.with_thread_ids(false)
.with_file(false)
.with_line_number(false)
.with_ansi(true)
.with_writer(std::io::stderr);

tracing_subscriber::registry()
.with(EnvFilter::from_default_env()
.add_directive(tracing::Level::INFO.into()))
.with(file_layer)
.with(console_layer)
.init();

Ok(guard)
}

0 comments on commit ddf12b4

Please sign in to comment.