Compare commits
24 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a952080a84 | |
|
|
5f950ab890 | |
|
|
58c88c6ec1 | |
|
|
2b218f171f | |
|
|
075ccdcdcc | |
|
|
cf3fc66af8 | |
|
|
e019422dd1 | |
|
|
f9b4718549 | |
|
|
b20b8fb55b | |
|
|
a1bcdf5b0b | |
|
|
43302ab0ea | |
|
|
493942396d | |
|
|
5dd910b683 | |
|
|
e5f6ab5c4d | |
|
|
06784491cd | |
|
|
613bb3413b | |
|
|
5d4dad61b9 | |
|
|
31b67389cd | |
|
|
c8e73f989c | |
|
|
dd68352dd3 | |
|
|
0e7ee82265 | |
|
|
cc3a1160e0 | |
|
|
7b6d13d9dc | |
|
|
3c096f9e5b |
|
|
@ -2,3 +2,5 @@
|
||||||
.dub
|
.dub
|
||||||
*.o
|
*.o
|
||||||
lib
|
lib
|
||||||
|
bin
|
||||||
|
test.log
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [1.0.1] - 2025-03-27
|
||||||
|
### Fixed
|
||||||
|
- Correct transfer of priority when writing to the system log.
|
||||||
|
|
||||||
|
## [1.0.0] - 2025-03-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Thread-safety**: Added a `Mutex` to ensure thread-safe logging operations across all methods (`_mutex` in `Log` class).
|
||||||
|
- **Destructor**: Implemented `~this()` to properly close the log file when the `Log` instance is destroyed.
|
||||||
|
- **File handle management**: Introduced `_file` (File handle) and `_fileOpen` (flag) for better file management, reducing repeated file opening/closing.
|
||||||
|
- **Enhanced documentation**: Added detailed DDoc comments for the module, `Log` class, and all public/private methods, including examples.
|
||||||
|
- **Immutable arrays**: Made `_sysPriority`, `_sysPriorityOS`, `_color` (Windows), `_colorCodes` (both platforms), and `_type` arrays immutable for better safety and performance.
|
||||||
|
- **Singleton initialization**: Improved singleton pattern with double-checked locking in `@property static Log msg()` for thread-safe initialization.
|
||||||
|
- **Fluent interface naming**: Renamed output-related enums (`SYSLOG`, `STD`, `FILE`) and methods (`std`, `syslog`, `file`) for consistency and clarity (e.g., `STDOUT` → `STD`).
|
||||||
|
- **Error handling**: Enhanced error reporting in `writefile` by logging exception messages instead of the full exception object.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Output handling**:
|
||||||
|
- Removed separate `writestdout` and `writestderr` methods; consolidated into a single `writestd` method that dynamically selects `stdout` or `stderr` based on log level (`ERROR` and above go to `stderr`, others to `stdout`).
|
||||||
|
- Adjusted output enum values: `SYSLOG = 1`, `STD = 2`, `FILE = 8` (removed `STDERR = 4` as it's now handled by `STD`).
|
||||||
|
- **Windows-specific**:
|
||||||
|
- Renamed `_color` to `_colorCodes` for consistency with POSIX.
|
||||||
|
- Updated `writesyslog` to use `toUTF16z()` for `_name` and added null checks.
|
||||||
|
- **POSIX-specific**:
|
||||||
|
- Renamed `_color` to `_colorCodes` and simplified console output logic in `writestd`.
|
||||||
|
- Changed `writesyslog` to pass priority directly instead of mapping it.
|
||||||
|
- **Log level filtering**: Moved priority check (`_priority > priority`) into `writelog` under the mutex for consistency.
|
||||||
|
- **File logging**:
|
||||||
|
- Simplified `writefile` by maintaining an open `File` handle (`_file`) instead of opening/closing on each write.
|
||||||
|
- Removed redundant file existence check (`this._path.exists`) as `File` opening handles it implicitly.
|
||||||
|
- **Configuration methods**: Made all setters (`program`, `file`, `level`, `color`, `output`) thread-safe with `synchronized (_mutex)`.
|
||||||
|
- **Naming consistency**:
|
||||||
|
- Renamed `Output.output()` to internal use; public access is via `Output` struct methods.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
- **Deprecated method**: Removed the deprecated `Log output(int outs)` method; users must now use the fluent `Output` struct.
|
||||||
|
- **Redundant output flags**: Removed `STDERR` from output enum as it's now handled dynamically by `STD`.
|
||||||
|
- **Unnecessary struct fields**: Removed `_output` and `_newoutput` from `Output` struct; replaced with a single `value` field.
|
||||||
|
- **Redundant methods**: Removed separate `writestdout` and `writestderr` in favor of `writestd`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Windows console output**: Added error checking in `colorTextOutput` and `defaultTextOutput` with `GetConsoleScreenBufferInfo`.
|
||||||
|
- **File closing**: Ensured proper file closure in `file` method when changing the log file path.
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
- **Output enum changes**:
|
||||||
|
- `STDOUT` renamed to `STD`, `STDERR` removed; code relying on `STDERR = 4` will need adjustment.
|
||||||
|
- Users must update output configuration to use `STD` instead of separate `STDOUT`/`STDERR`.
|
||||||
|
- **Method removal**: Code using the deprecated `Log output(int outs)` must switch to `Log.output(Output)`.
|
||||||
|
- **Console output behavior**: Messages with priority `ERROR` and above now go to `stderr` by default when `STD` is enabled, which may change existing output redirection logic.
|
||||||
|
|
||||||
|
## [0.5.0] - 2023-07-21
|
||||||
|
|
||||||
|
### New
|
||||||
|
|
||||||
|
- Added the ability to output messages to the standard error stream. Now messages above the `WARNING` level will not be output to the `stdout`. To output them, need to use `stderr`
|
||||||
|
- Write message to specific outputs via `log.now`
|
||||||
|
- Now `log.output` allows to set the output as an argument
|
||||||
|
- Now `log.level` allows to set the level as an argument
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Fixed streams redirection in Windows
|
||||||
|
|
||||||
|
## [0.4.0] - 2023-06-07
|
||||||
|
|
||||||
|
- Part of the code has been changed/rewritten
|
||||||
|
|
||||||
|
### New
|
||||||
|
|
||||||
|
- Color output of messages to the terminal and console
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- In Windows, unicode messages are output without distortion to the system log and console (thanks [Adam D. Ruppe](https://arsdnet.net/))
|
||||||
|
|
||||||
|
## [0.3.2] - 2023-06-01
|
||||||
|
|
||||||
|
- Printing information about the type of the logged message to the standard output stream and file
|
||||||
|
- Printing the date and time to the standard output stream
|
||||||
|
|
||||||
|
## [0.3.1] - 2023-05-30
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Log of debug messages
|
||||||
|
|
||||||
|
## [0.3.0] - 2023-04-28
|
||||||
|
|
||||||
|
- Minor changes
|
||||||
|
|
||||||
|
### New
|
||||||
|
|
||||||
|
- Windows OS Logging support
|
||||||
|
|
||||||
|
## [0.2.1] - 2023-03-29
|
||||||
|
|
||||||
|
### New
|
||||||
|
|
||||||
|
- Added aliases for the short form of function calls
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Calling the main object
|
||||||
|
|
||||||
|
## [0.2.0] - 2023-03-29
|
||||||
|
|
||||||
|
- Removed functions `fileOn()` and `fileOff()`
|
||||||
|
|
||||||
|
### New
|
||||||
|
|
||||||
|
- Simultaneous writing to the standard stream, syslog and file by binary setting the output flag
|
||||||
|
|
||||||
|
## [0.1.0] - 2023-03-23
|
||||||
|
|
||||||
|
### The first stable working release
|
||||||
|
|
||||||
|
- Output to the standard stream or syslog
|
||||||
|
- Enable an entry in the file
|
||||||
162
README.md
162
README.md
|
|
@ -1,62 +1,152 @@
|
||||||
# singlog
|

|
||||||
|
|
||||||
Singleton for simple logging
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
|
||||||
|
[](https://git.zhirov.kz/dlang/singlog)
|
||||||
|
[](https://github.com/AlexanderZhirov/singlog)
|
||||||
|
[](https://code.dlang.org/packages/singlog)
|
||||||
|
[](https://www.linux.org/)
|
||||||
|
[](https://support.microsoft.com/en-US/windows)
|
||||||
|
|
||||||
## Basic Usage
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Singleton Logging Module
|
||||||
|
|
||||||
|
`singlog` is a singleton logging module written in the D programming language, designed to provide thread-safe, cross-platform logging with flexible output targets. It supports multiple log levels, configurable output destinations (syslog, console, file), and optional colored console output, making it a versatile tool for application logging.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Thread-Safety**: Utilizes a `Mutex` to ensure safe logging in multi-threaded applications.
|
||||||
|
- **Cross-Platform**: Works on both Windows (Event Log, console) and POSIX (syslog, console) systems.
|
||||||
|
- **Flexible Output Targets**: Supports logging to:
|
||||||
|
- System logs (syslog on POSIX, Event Log on Windows).
|
||||||
|
- Standard output (`stdout` for NOTICE and above, `stderr` for ERROR and below).
|
||||||
|
- Files (with configurable file paths).
|
||||||
|
- **Log Levels**: Seven configurable levels:
|
||||||
|
- `DEBUGGING` (highest priority)
|
||||||
|
- `ALERT`
|
||||||
|
- `CRITICAL`
|
||||||
|
- `ERROR`
|
||||||
|
- `WARNING`
|
||||||
|
- `NOTICE`
|
||||||
|
- `INFORMATION` (lowest priority)
|
||||||
|
- **Fluent Interface**: Provides a chaining API for easy configuration of output targets, log levels, and settings.
|
||||||
|
- **Colored Output**: Optional ANSI color support for console messages (on POSIX) or Windows console colors.
|
||||||
|
- **Singleton Design**: Ensures a single logger instance throughout the application, accessible via `Log.msg` or the `log` alias.
|
||||||
|
- **Aliases**: Short aliases (e.g., `d` for `debugging`, `e` for `error`) for concise logging.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
To use `singlog`, include it in your D project:
|
||||||
|
|
||||||
|
1. **Via Source**: Copy the `singlog.d` file into your project’s source directory.
|
||||||
|
2. **Via DUB** (if packaged):
|
||||||
|
|
||||||
|
Add it to your `dub.json`:
|
||||||
|
```json
|
||||||
|
"dependencies": {
|
||||||
|
"singlog": "~>1.0.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Configuration and Logging
|
||||||
|
|
||||||
|
The `singlog` module provides a singleton logger instance accessible via `Log.msg` or the global `log` alias. Here’s a basic example:
|
||||||
|
|
||||||
```d
|
```d
|
||||||
import simplog;
|
import singlog;
|
||||||
|
|
||||||
void main()
|
void main() {
|
||||||
{
|
// Configure the logger
|
||||||
Log.msg.level(Log.DEBUG);
|
log.program("MyApp") // Set program name for syslog/Event Log
|
||||||
Log.msg.output(Log.SYSLOG);
|
.color(true) // Enable colored console output
|
||||||
Log.msg.file("./file.log");
|
.level(log.level.debugging) // Set minimum log level to DEBUGGING
|
||||||
Log.msg.warning("Hello, World!");
|
.output(log.output.std.file.syslog) // Output to console, file, and syslog
|
||||||
|
.file("./myapp.log"); // Set log file path
|
||||||
|
|
||||||
|
// Log messages
|
||||||
|
log.debugging("Starting application in debug mode");
|
||||||
|
log.information("Initialization complete");
|
||||||
|
log.error("Failed to load resource");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
This configures the logger to:
|
||||||
|
- Identify as "MyApp" in system logs.
|
||||||
|
- Use colored output on the console.
|
||||||
|
- Log all messages (from `DEBUGGING` up).
|
||||||
|
- Write to the console, a file (`myapp.log`), and the system log.
|
||||||
|
|
||||||
Setting the error output level:
|
### Log Levels and Aliases
|
||||||
|
|
||||||
|
The logger supports seven log levels with corresponding methods and aliases:
|
||||||
|
|
||||||
|
| Level | Method | Alias | Description |
|
||||||
|
|---------------|-------------------|-------|------------------------------|
|
||||||
|
| `DEBUGGING` | `debugging()` | `d()` | Debugging information |
|
||||||
|
| `ALERT` | `alert()` | `a()` | High-priority alerts |
|
||||||
|
| `CRITICAL` | `critical()` | `c()` | Critical errors |
|
||||||
|
| `ERROR` | `error()` | `e()` | General errors |
|
||||||
|
| `WARNING` | `warning()` | `w()` | Warnings |
|
||||||
|
| `NOTICE` | `notice()` | `n()` | Notices |
|
||||||
|
| `INFORMATION` | `information()` | `i()` | Informational messages |
|
||||||
|
|
||||||
|
Example using aliases:
|
||||||
|
|
||||||
```d
|
```d
|
||||||
Log.msg.level(Log.DEBUG);
|
log.d("Debug message");
|
||||||
Log.msg.level(Log.ALERT);
|
log.i("Info message");
|
||||||
Log.msg.level(Log.CRIT);
|
log.e("Error message");
|
||||||
Log.msg.level(Log.ERR);
|
|
||||||
Log.msg.level(Log.WARNING);
|
|
||||||
Log.msg.level(Log.NOTICE);
|
|
||||||
Log.msg.level(Log.INFO);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Assigning a target output:
|
### Output Targets
|
||||||
|
|
||||||
|
Output targets can be configured using the `output()` method and its fluent interface:
|
||||||
|
|
||||||
|
- `syslog()`: Logs to the system log (Event Log on Windows, syslog on POSIX).
|
||||||
|
- `std()`: Logs to the console (`stdout` or `stderr` based on log level).
|
||||||
|
- `file()`: Logs to a file (requires `file()` to set the path).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
```d
|
```d
|
||||||
Log.msg.output(Log.SYSLOG);
|
log.output(log.output.std.file); // Console and file output
|
||||||
Log.msg.output(Log.STDOUT);
|
log.i("This goes to console and file");
|
||||||
```
|
```
|
||||||
|
|
||||||
Setup and allowing writing to a file:
|
### Temporary Output Override
|
||||||
|
|
||||||
|
Use `now()` to temporarily override output targets for the next log call:
|
||||||
|
|
||||||
```d
|
```d
|
||||||
Log.msg.file("./file.log");
|
log.now(log.output.std).n("This goes only to console");
|
||||||
Log.msg.fileOn();
|
log.i("This uses default outputs again");
|
||||||
Log.msg.fileOff();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Output of messages to the log:
|
### Colored Output
|
||||||
|
|
||||||
|
Enable colored output with `color(true)`:
|
||||||
|
|
||||||
```d
|
```d
|
||||||
Log.msg.alert("Alert message");
|
log.color(true);
|
||||||
Log.msg.critical("Critical message");
|
log.w("This warning will be yellow on POSIX or Windows");
|
||||||
Log.msg.error("Error message");
|
log.c("This critical message will be magenta");
|
||||||
Log.msg.warning("Warning message");
|
|
||||||
Log.msg.notice("Notice message");
|
|
||||||
Log.msg.informations("Information message");
|
|
||||||
Log.msg.debugging("Debugging message");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dub
|
Colors differ by platform:
|
||||||
|
- **POSIX**: Uses ANSI escape codes (e.g., green for `DEBUGGING`, red for `ERROR`).
|
||||||
|
- **Windows**: Uses console color attributes (e.g., yellow for `WARNING`, white for `INFORMATION`).
|
||||||
|
|
||||||
Add a dependency on `"singlog": "~>0.1.0"`.
|
### File Logging
|
||||||
|
|
||||||
|
Set a log file with `file()`:
|
||||||
|
|
||||||
|
```d
|
||||||
|
log.file("app.log");
|
||||||
|
log.e("This error goes to app.log");
|
||||||
|
```
|
||||||
|
|
||||||
|
The file is opened in append mode (`"a+"`) and includes timestamps.
|
||||||
|
|
|
||||||
17
dub.json
17
dub.json
|
|
@ -7,9 +7,22 @@
|
||||||
"license": "GPL-2.0",
|
"license": "GPL-2.0",
|
||||||
"copyright": "© Alexander Zhirov, 2023",
|
"copyright": "© Alexander Zhirov, 2023",
|
||||||
"description": "Singleton for simple logging",
|
"description": "Singleton for simple logging",
|
||||||
"targetType": "library",
|
|
||||||
"targetPath": "lib",
|
|
||||||
"targetName": "singlog",
|
"targetName": "singlog",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "library",
|
||||||
|
"targetType": "library",
|
||||||
|
"targetPath": "lib"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"targetType": "executable",
|
||||||
|
"targetPath": "bin",
|
||||||
|
"targetName": "test",
|
||||||
|
"importPaths": ["source","tests"],
|
||||||
|
"sourcePaths": ["tests"]
|
||||||
|
}
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"datefmt": "~>1.0.4"
|
"datefmt": "~>1.0.4"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
.\" Man page for the singlog library
|
||||||
|
.TH SINGLOG 3 "March 23, 2025" "singlog" "Programmer's Manual"
|
||||||
|
.SH NAME
|
||||||
|
singlog \- Singleton logging library with thread-safety and flexible output targets
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
import singlog;
|
||||||
|
|
||||||
|
Log logger = Log.msg; // Access singleton instance
|
||||||
|
log.<method>(<args>); // Use global alias
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The \fBsinglog\fR library provides a thread-safe, singleton-based logging utility designed for cross-platform use on Windows and POSIX systems. It supports multiple output targets (syslog, stdout/stderr, file), configurable log levels, and optional colored console output. The library uses a fluent interface for easy configuration and provides short aliases for common log levels.
|
||||||
|
|
||||||
|
.SH FEATURES
|
||||||
|
.TP
|
||||||
|
.B Thread-safety
|
||||||
|
Uses a \fBMutex\fR to ensure safe logging in multi-threaded applications.
|
||||||
|
.TP
|
||||||
|
.B Cross-platform
|
||||||
|
Supports Windows (Event Log, console) and POSIX (syslog, console).
|
||||||
|
.TP
|
||||||
|
.B Flexible output
|
||||||
|
Logs to syslog, stdout/stderr (based on log level), or files.
|
||||||
|
.TP
|
||||||
|
.B Log levels
|
||||||
|
Seven levels: \fBDEBUGGING\fR, \fBALERT\fR, \fBCRITICAL\fR, \fBERROR\fR, \fBWARNING\fR, \fBNOTICE\fR, \fBINFORMATION\fR.
|
||||||
|
.TP
|
||||||
|
.B Fluent interface
|
||||||
|
Chainable configuration for output targets, levels, and more.
|
||||||
|
.TP
|
||||||
|
.B Colored output
|
||||||
|
Optional color support for console messages (STD output only).
|
||||||
|
|
||||||
|
.SH METHODS
|
||||||
|
.TP
|
||||||
|
.B Log.msg
|
||||||
|
Returns the singleton instance of the \fBLog\fR class.
|
||||||
|
.RS
|
||||||
|
Example: \fBauto logger = Log.msg; logger.i("Logger retrieved");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B program(string name)
|
||||||
|
Sets the program name for syslog identification. Returns \fBLog\fR for chaining.
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.program("MyApp").i("Name set");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B file(string path)
|
||||||
|
Sets the log file path. Returns \fBLog\fR for chaining.
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.file("app.log").i("File configured");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B level(int priority)
|
||||||
|
Sets the minimum log level. Returns \fBLog\fR for chaining.
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.level(log.level.warning).w("This shows");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B color(bool condition)
|
||||||
|
Enables/disables colored console output. Returns \fBLog\fR for chaining.
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.color(true).i("Colored output");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B output(Output outs)
|
||||||
|
Sets default output targets. Returns \fBLog\fR for chaining.
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.output(log.output.std.file).i("To console and file");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B now(Output outs)
|
||||||
|
Temporarily overrides output targets for the next log call. Returns \fBNow\fR for chaining.
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.now(log.output.std).n("Temp console output");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B Logging methods
|
||||||
|
Log messages at different levels: \fBalert\fR, \fBcritical\fR, \fBerror\fR, \fBwarning\fR, \fBnotice\fR, \fBinformation\fR, \fBdebugging\fR (with aliases \fBa\fR, \fBc\fR, \fBe\fR, \fBw\fR, \fBn\fR, \fBi\fR, \fBd\fR).
|
||||||
|
.RS
|
||||||
|
Example: \fBlog.e("Error occurred"); log.i(42);\fR
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH EXAMPLES
|
||||||
|
Configure and use the logger:
|
||||||
|
.nf
|
||||||
|
import singlog;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
log.program("MyApp")
|
||||||
|
.color(true)
|
||||||
|
.level(log.level.debugging)
|
||||||
|
.output(log.output.std.file.syslog)
|
||||||
|
.file("myapp.log");
|
||||||
|
|
||||||
|
log.d("Starting in debug mode");
|
||||||
|
log.i("App running");
|
||||||
|
log.e("Error occurred");
|
||||||
|
log.now(log.output.std).n("Temp console message");
|
||||||
|
}
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR dmd (1),
|
||||||
|
.BR syslog (3)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
Alexander Zhirov
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
.\" Страница руководства для библиотеки singlog
|
||||||
|
.TH SINGLOG 3 "23 марта 2025" "singlog" "Руководство программиста"
|
||||||
|
.SH ИМЯ
|
||||||
|
singlog \- Библиотека логирования с singleton-паттерном, потокобезопасностью и гибкими целями вывода
|
||||||
|
|
||||||
|
.SH СИНТАКСИС
|
||||||
|
.nf
|
||||||
|
import singlog;
|
||||||
|
|
||||||
|
Log logger = Log.msg; // Получение singleton-экземпляра
|
||||||
|
log.<метод>(<аргументы>); // Использование глобального алиаса
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH ОПИСАНИЕ
|
||||||
|
Библиотека \fBsinglog\fR предоставляет потокобезопасную утилиту логирования на основе singleton-паттерна, предназначенную для кроссплатформенного использования в системах Windows и POSIX. Поддерживает несколько целей вывода (syslog, stdout/stderr, файл), настраиваемые уровни логирования и опциональный цветной вывод в консоль. Библиотека использует плавный интерфейс для удобной настройки и предоставляет короткие алиасы для распространенных уровней логирования.
|
||||||
|
|
||||||
|
.SH ОСОБЕННОСТИ
|
||||||
|
.TP
|
||||||
|
.B Потокобезопасность
|
||||||
|
Использует \fBMutex\fR для обеспечения безопасного логирования в многопоточных приложениях.
|
||||||
|
.TP
|
||||||
|
.B Кроссплатформенность
|
||||||
|
Поддерживает Windows (журнал событий, консоль) и POSIX (syslog, консоль).
|
||||||
|
.TP
|
||||||
|
.B Гибкий вывод
|
||||||
|
Вывод логов в syslog, stdout/stderr (в зависимости от уровня) или файлы.
|
||||||
|
.TP
|
||||||
|
.B Уровни логирования
|
||||||
|
Семь уровней: \fBDEBUGGING\fR, \fBALERT\fR, \fBCRITICAL\fR, \fBERROR\fR, \fBWARNING\fR, \fBNOTICE\fR, \fBINFORMATION\fR.
|
||||||
|
.TP
|
||||||
|
.B Плавный интерфейс
|
||||||
|
Цепочная настройка целей вывода, уровней и других параметров.
|
||||||
|
.TP
|
||||||
|
.B Цветной вывод
|
||||||
|
Опциональная поддержка цветного вывода в консоль (только для STD).
|
||||||
|
|
||||||
|
.SH МЕТОДЫ
|
||||||
|
.TP
|
||||||
|
.B Log.msg
|
||||||
|
Возвращает singleton-экземпляр класса \fBLog\fR.
|
||||||
|
.RS
|
||||||
|
Пример: \fBauto logger = Log.msg; logger.i("Логгер получен");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B program(string name)
|
||||||
|
Устанавливает имя программы для идентификации в syslog. Возвращает \fBLog\fR для цепочки.
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.program("МоеПриложение").i("Имя установлено");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B file(string path)
|
||||||
|
Устанавливает путь к лог-файлу. Возвращает \fBLog\fR для цепочки.
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.file("app.log").i("Файл настроен");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B level(int priority)
|
||||||
|
Устанавливает минимальный уровень логирования. Возвращает \fBLog\fR для цепочки.
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.level(log.level.warning).w("Это отобразится");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B color(bool condition)
|
||||||
|
Включает/выключает цветной вывод в консоль. Возвращает \fBLog\fR для цепочки.
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.color(true).i("Цветной вывод");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B output(Output outs)
|
||||||
|
Устанавливает цели вывода по умолчанию. Возвращает \fBLog\fR для цепочки.
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.output(log.output.std.file).i("В консоль и файл");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B now(Output outs)
|
||||||
|
Временно переопределяет цели вывода для следующего вызова. Возвращает \fBNow\fR для цепочки.
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.now(log.output.std).n("Временный вывод в консоль");\fR
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B Методы логирования
|
||||||
|
Запись сообщений на разных уровнях: \fBalert\fR, \fBcritical\fR, \fBerror\fR, \fBwarning\fR, \fBnotice\fR, \fBinformation\fR, \fBdebugging\fR (с алиасами \fBa\fR, \fBc\fR, \fBe\fR, \fBw\fR, \fBn\fR, \fBi\fR, \fBd\fR).
|
||||||
|
.RS
|
||||||
|
Пример: \fBlog.e("Произошла ошибка"); log.i(42);\fR
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH ПРИМЕРЫ
|
||||||
|
Настройка и использование логгера:
|
||||||
|
.nf
|
||||||
|
import singlog;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
log.program("МоеПриложение")
|
||||||
|
.color(true)
|
||||||
|
.level(log.level.debugging)
|
||||||
|
.output(log.output.std.file.syslog)
|
||||||
|
.file("myapp.log");
|
||||||
|
|
||||||
|
log.d("Запуск в режиме отладки");
|
||||||
|
log.i("Приложение работает");
|
||||||
|
log.e("Произошла ошибка");
|
||||||
|
log.now(log.output.std).n("Временное сообщение в консоль");
|
||||||
|
}
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH СМ. ТАКЖЕ
|
||||||
|
.BR dmd (1),
|
||||||
|
.BR syslog (3)
|
||||||
|
|
||||||
|
.SH АВТОР
|
||||||
|
Александр Жиров
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
974
source/singlog.d
974
source/singlog.d
|
|
@ -1,147 +1,875 @@
|
||||||
|
/++
|
||||||
|
Singleton logging module with thread-safety and flexible output targets.
|
||||||
|
|
||||||
|
This module provides a simple, thread-safe logging utility with support for multiple output targets
|
||||||
|
(syslog, standard output/error, file), configurable log levels, and optional colored console output.
|
||||||
|
It is designed to be cross-platform, working on both Windows and POSIX systems.
|
||||||
|
|
||||||
|
The logger is implemented as a singleton, ensuring a single instance throughout the application.
|
||||||
|
It supports fluent configuration for ease of use and provides short aliases for common log levels.
|
||||||
|
+/
|
||||||
module singlog;
|
module singlog;
|
||||||
|
|
||||||
import core.sys.posix.syslog;
|
version(Windows) {
|
||||||
|
import core.sys.windows.windows;
|
||||||
|
import std.utf : toUTF8, toUTF16z;
|
||||||
|
} else version(Posix) {
|
||||||
|
import core.sys.posix.syslog;
|
||||||
|
}
|
||||||
|
|
||||||
|
import core.sync.mutex : Mutex;
|
||||||
|
import std.string;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.meta;
|
|
||||||
import std.file;
|
import std.file;
|
||||||
import std.datetime;
|
import std.datetime;
|
||||||
import datefmt;
|
import datefmt;
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Singleton for simple logging
|
Singleton logging class with thread-safe operations and flexible output.
|
||||||
|
|
||||||
|
The `Log` class is the core of the `singlog` module, providing a robust logging system with the following features:
|
||||||
|
- **Thread-safety**: Uses a `Mutex` to ensure safe logging in multi-threaded applications.
|
||||||
|
- **Cross-platform**: Supports Windows (Event Log, console) and POSIX (syslog, console) systems.
|
||||||
|
- **Flexible output**: Allows logging to syslog, stdout/stderr (based on log level), and files.
|
||||||
|
- **Log levels**: Supports seven levels (`DEBUGGING`, `ALERT`, `CRITICAL`, `ERROR`, `WARNING`, `NOTICE`, `INFORMATION`).
|
||||||
|
- **Fluent interface**: Enables easy configuration chaining for output targets, levels, and more.
|
||||||
|
- **Colored output**: Optional color support for console messages (STD output only).
|
||||||
|
|
||||||
|
The class is a singleton, accessible via the static `msg` property or the global `log` alias.
|
||||||
|
|
||||||
|
Example:
|
||||||
---
|
---
|
||||||
// Setting the error output level
|
import singlog;
|
||||||
Log.msg.level(Log.DEBUG);
|
|
||||||
Log.msg.level(Log.ALERT);
|
void main() {
|
||||||
Log.msg.level(Log.CRIT);
|
// Configure the logger
|
||||||
Log.msg.level(Log.ERR);
|
Log logger = Log.msg; // Get singleton instance
|
||||||
Log.msg.level(Log.WARNING);
|
logger.program("TestApp")
|
||||||
Log.msg.level(Log.NOTICE);
|
.color(true)
|
||||||
Log.msg.level(Log.INFO);
|
.level(Log.DEBUGGING)
|
||||||
// Assigning a target output
|
.output(Log.Output().std.file.syslog)
|
||||||
Log.msg.output(Log.SYSLOG);
|
.file("test.log");
|
||||||
Log.msg.output(Log.STDOUT);
|
|
||||||
// Setup and allowing writing to a file
|
// Log messages with full method names
|
||||||
Log.msg.file("./file.log");
|
logger.debugging("Starting in debug mode");
|
||||||
Log.msg.fileOn();
|
logger.information("App is running");
|
||||||
Log.msg.fileOff();
|
logger.error("An error occurred");
|
||||||
// Output of messages to the log
|
|
||||||
Log.msg.alert("Alert message");
|
// Log messages with aliases
|
||||||
Log.msg.critical("Critical message");
|
logger.d("Debug alias");
|
||||||
Log.msg.error("Error message");
|
logger.i("Info alias");
|
||||||
Log.msg.warning("Warning message");
|
logger.e("Error alias");
|
||||||
Log.msg.notice("Notice message");
|
|
||||||
Log.msg.informations("Information message");
|
// Temporary output override
|
||||||
Log.msg.debugging("Debugging message");
|
logger.now(Log.Output().std).notice("Temporary console message");
|
||||||
|
}
|
||||||
---
|
---
|
||||||
+/
|
+/
|
||||||
class Log
|
class Log {
|
||||||
{
|
private:
|
||||||
private static Log log;
|
static Log _log; /// Singleton instance of the logger
|
||||||
private string path;
|
Mutex _mutex; /// Mutex for thread-safety
|
||||||
private bool writeToFile = false;
|
string _path; /// Path to the log file
|
||||||
private bool fileExist = true;
|
File _file; /// File handle for logging
|
||||||
private static SysTime time;
|
bool _fileOpen = false; /// Indicates if the log file is open
|
||||||
|
wstring _name = "singlog"; /// Program name for syslog identification
|
||||||
|
bool _writeToFile = true; /// Flag to enable/disable file logging
|
||||||
|
bool _color = false; /// Flag to enable/disable colored console output
|
||||||
|
int _output = STD; /// Default output flags (STD by default)
|
||||||
|
int _priority = INFORMATION; /// Minimum log level for output
|
||||||
|
int _nowOutput = 0; /// Temporary output override for the next log call
|
||||||
|
|
||||||
// Target output
|
/++ Private constructor to enforce singleton pattern +/
|
||||||
enum {SYSLOG, STDOUT}
|
this() {
|
||||||
|
_mutex = new Mutex();
|
||||||
// Message output level
|
|
||||||
enum {
|
|
||||||
DEBUG = 0,
|
|
||||||
CRIT = 1,
|
|
||||||
ERR = 2,
|
|
||||||
WARNING = 3,
|
|
||||||
NOTICE = 4,
|
|
||||||
INFO = 5,
|
|
||||||
ALERT = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
int msgOutput = STDOUT;
|
|
||||||
int msgLevel = INFO;
|
|
||||||
|
|
||||||
private this() {}
|
|
||||||
|
|
||||||
private void writeLog(string message, int msgLevel, int priority)
|
|
||||||
{
|
|
||||||
if (this.msgLevel > msgLevel)
|
|
||||||
return;
|
|
||||||
if (this.msgOutput == STDOUT)
|
|
||||||
writeln(message);
|
|
||||||
else if (this.msgOutput == SYSLOG)
|
|
||||||
syslog(priority, (message ~ "\0").ptr);
|
|
||||||
writeFile(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeFile(string message)
|
/++ Destructor to ensure the log file is closed +/
|
||||||
{
|
~this() {
|
||||||
if (!this.writeToFile || !this.fileExist)
|
synchronized (_mutex) {
|
||||||
return;
|
if (_fileOpen) {
|
||||||
|
_file.close();
|
||||||
if (this.path.exists)
|
_fileOpen = false;
|
||||||
this.fileExist = true;
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
this.fileExist = false;
|
|
||||||
this.warning("The log file does not exist: " ~ this.path);
|
|
||||||
this.fileExist = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
File file;
|
|
||||||
|
|
||||||
try {
|
|
||||||
file = File(this.path, "a+");
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.fileOff();
|
|
||||||
this.error("Unable to open the log file " ~ this.path);
|
|
||||||
this.critical(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
file.writeln(this.time.format("%Y.%m.%d %H:%M:%S: ") ~ message);
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.fileOff();
|
|
||||||
this.error("Unable to write to the log file " ~ this.path);
|
|
||||||
this.critical(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
file.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.fileOff();
|
|
||||||
this.error("Unable to close the log file " ~ this.path);
|
|
||||||
this.critical(e);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@property static Log msg()
|
|
||||||
{
|
|
||||||
if (this.log is null)
|
|
||||||
{
|
|
||||||
this.log = new Log;
|
|
||||||
this.time = Clock.currTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.log;
|
version(Windows) {
|
||||||
|
immutable int[] _sysPriority = [0, 1, 1, 1, 2, 3, 3]; /// Mapping of log levels to syslog priorities
|
||||||
|
immutable WORD[] _sysPriorityOS = [ /// Windows Event Log types
|
||||||
|
EVENTLOG_SUCCESS, // DEBUGGING
|
||||||
|
EVENTLOG_ERROR_TYPE, // ALERT, CRITICAL, ERROR
|
||||||
|
EVENTLOG_WARNING_TYPE, // WARNING
|
||||||
|
EVENTLOG_INFORMATION_TYPE // NOTICE, INFORMATION
|
||||||
|
];
|
||||||
|
|
||||||
|
immutable WORD[] _colorCodes = [ /// Console color codes for each log level
|
||||||
|
FOREGROUND_GREEN, // DEBUGGING (green)
|
||||||
|
FOREGROUND_BLUE, // ALERT (blue)
|
||||||
|
FOREGROUND_RED | FOREGROUND_BLUE, // CRITICAL (magenta)
|
||||||
|
FOREGROUND_RED, // ERROR (red)
|
||||||
|
FOREGROUND_RED | FOREGROUND_GREEN, // WARNING (yellow)
|
||||||
|
FOREGROUND_BLUE | FOREGROUND_GREEN, // NOTICE (cyan)
|
||||||
|
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN // INFORMATION (white)
|
||||||
|
];
|
||||||
|
|
||||||
|
/++
|
||||||
|
Writes a message to the Windows Event Log.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log.
|
||||||
|
priority = The Windows Event Log type (e.g., EVENTLOG_ERROR_TYPE).
|
||||||
|
+/
|
||||||
|
void writesyslog(string message, WORD priority) {
|
||||||
|
auto wMessage = message.toUTF16z();
|
||||||
|
HANDLE handleEventLog = RegisterEventSourceW(null, _name.toUTF16z());
|
||||||
|
if (handleEventLog == null) return;
|
||||||
|
ReportEventW(handleEventLog, priority, 0, 0, null, 1, 0, &wMessage, null);
|
||||||
|
DeregisterEventSource(handleEventLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output(int msgOutput) { this.msgOutput = msgOutput; }
|
/++
|
||||||
void level(int msgLevel) { this.msgLevel = msgLevel; }
|
Outputs a colored log message to the console on Windows.
|
||||||
void file(string path) { this.path = path; }
|
|
||||||
|
|
||||||
void fileOn() { this.writeToFile = true; }
|
Params:
|
||||||
void fileOff() { this.writeToFile = false; }
|
handle = The console handle (STD_OUTPUT_HANDLE or STD_ERROR_HANDLE).
|
||||||
|
time = The timestamp of the message.
|
||||||
|
message = The message to log.
|
||||||
|
priority = The log level (used to select the color).
|
||||||
|
+/
|
||||||
|
void colorTextOutput(HANDLE handle, string time, string message, int priority) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO defaultConsole;
|
||||||
|
if (!GetConsoleScreenBufferInfo(handle, &defaultConsole)) return;
|
||||||
|
|
||||||
void alert(T)(T message) { writeLog(message.to!string, ALERT, LOG_ALERT); }
|
wstring wTime = "%s ".format(time).to!wstring;
|
||||||
void critical(T)(T message) { writeLog(message.to!string, CRIT, LOG_CRIT); }
|
wstring wType = _type[priority].to!wstring;
|
||||||
void error(T)(T message) { writeLog(message.to!string, ERR, LOG_ERR); }
|
wstring wMessage = " %s\n".format(message).to!wstring;
|
||||||
void warning(T)(T message) { writeLog(message.to!string, WARNING, LOG_WARNING); }
|
|
||||||
void notice(T)(T message) { writeLog(message.to!string, NOTICE, LOG_NOTICE); }
|
switch (GetFileType(handle)) {
|
||||||
void information(T)(T message) { writeLog(message.to!string, INFO, LOG_INFO); }
|
case FILE_TYPE_CHAR:
|
||||||
void debugging(T)(T message) {writeLog(message.to!string, DEBUG, LOG_DEBUG); }
|
WriteConsoleW(handle, wTime.ptr, cast(DWORD)wTime.length, null, null);
|
||||||
|
SetConsoleTextAttribute(handle, _colorCodes[priority] | FOREGROUND_INTENSITY);
|
||||||
|
WriteConsoleW(handle, wType.ptr, cast(DWORD)wType.length, null, null);
|
||||||
|
SetConsoleTextAttribute(handle, _colorCodes[priority]);
|
||||||
|
WriteConsoleW(handle, wMessage.ptr, cast(DWORD)wMessage.length, null, null);
|
||||||
|
SetConsoleTextAttribute(handle, defaultConsole.wAttributes);
|
||||||
|
break;
|
||||||
|
case FILE_TYPE_PIPE, FILE_TYPE_DISK:
|
||||||
|
auto utf8Message = (wTime ~ wType ~ wMessage).toUTF8;
|
||||||
|
WriteFile(handle, utf8Message.ptr, cast(DWORD)utf8Message.length, null, null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writesyslog("Unknown output file", _sysPriorityOS[_sysPriority[ERROR]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Outputs a plain log message to the console on Windows.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
handle = The console handle (STD_OUTPUT_HANDLE or STD_ERROR_HANDLE).
|
||||||
|
time = The timestamp of the message.
|
||||||
|
message = The message to log.
|
||||||
|
priority = The log level (used to format the message).
|
||||||
|
+/
|
||||||
|
void defaultTextOutput(HANDLE handle, string time, string message, int priority) {
|
||||||
|
wstring wMessage = "%s %s %s\n".format(time, _type[priority], message).to!wstring;
|
||||||
|
switch (GetFileType(handle)) {
|
||||||
|
case FILE_TYPE_CHAR:
|
||||||
|
WriteConsoleW(handle, wMessage.ptr, cast(DWORD)wMessage.length, null, null);
|
||||||
|
break;
|
||||||
|
case FILE_TYPE_PIPE, FILE_TYPE_DISK:
|
||||||
|
auto utf8Message = wMessage.toUTF8;
|
||||||
|
WriteFile(handle, utf8Message.ptr, cast(DWORD)utf8Message.length, null, null);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
writesyslog("Unknown output file", _sysPriorityOS[_sysPriority[ERROR]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Writes a message to the console on Windows, choosing stdout or stderr based on log level.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
time = The timestamp of the message.
|
||||||
|
message = The message to log.
|
||||||
|
priority = The log level (ERROR and above go to stderr, others to stdout).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.writestd("2025.03.23 12:00:00", "Test error", ERROR); // Outputs to stderr
|
||||||
|
log.writestd("2025.03.23 12:00:01", "Test info", INFORMATION); // Outputs to stdout
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void writestd(string time, string message, int priority) {
|
||||||
|
HANDLE handle = (priority <= ERROR) ?
|
||||||
|
GetStdHandle(STD_ERROR_HANDLE) :
|
||||||
|
GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
_color ? colorTextOutput(handle, time, message, priority) : defaultTextOutput(handle, time, message, priority);
|
||||||
|
}
|
||||||
|
} else version(Posix) {
|
||||||
|
immutable int[] _sysPriority = [0, 1, 2, 3, 4, 5, 6]; /// Mapping of log levels to syslog priorities
|
||||||
|
immutable int[] _sysPriorityOS = [ /// POSIX syslog priorities
|
||||||
|
LOG_DEBUG, // DEBUGGING
|
||||||
|
LOG_ALERT, // ALERT
|
||||||
|
LOG_CRIT, // CRITICAL
|
||||||
|
LOG_ERR, // ERROR
|
||||||
|
LOG_WARNING, // WARNING
|
||||||
|
LOG_NOTICE, // NOTICE
|
||||||
|
LOG_INFO // INFORMATION
|
||||||
|
];
|
||||||
|
|
||||||
|
immutable string[] _colorCodes = [ /// ANSI color codes for console output
|
||||||
|
"\x1b[1;32m%s\x1b[0;32m %s\x1b[0;0m", // DEBUGGING (green)
|
||||||
|
"\x1b[1;34m%s\x1b[0;34m %s\x1b[0;0m", // ALERT (blue)
|
||||||
|
"\x1b[1;35m%s\x1b[0;35m %s\x1b[0;0m", // CRITICAL (magenta)
|
||||||
|
"\x1b[1;31m%s\x1b[0;31m %s\x1b[0;0m", // ERROR (red)
|
||||||
|
"\x1b[1;33m%s\x1b[0;33m %s\x1b[0;0m", // WARNING (yellow)
|
||||||
|
"\x1b[1;36m%s\x1b[0;36m %s\x1b[0;0m", // NOTICE (cyan)
|
||||||
|
"\x1b[1;97m%s\x1b[0;97m %s\x1b[0;0m" // INFORMATION (white)
|
||||||
|
];
|
||||||
|
|
||||||
|
/++
|
||||||
|
Writes a message to the console on POSIX, choosing stdout or stderr based on log level.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
time = The timestamp of the message.
|
||||||
|
message = The message to log.
|
||||||
|
priority = The log level (ERROR and above go to stderr, others to stdout).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.writestd("2025.03.23 12:00:00", "Critical failure", CRITICAL); // Outputs to stderr
|
||||||
|
log.writestd("2025.03.23 12:00:01", "System ready", NOTICE); // Outputs to stdout
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void writestd(string time, string message, int priority) {
|
||||||
|
if (priority <= ERROR) {
|
||||||
|
stderr.writefln("%s %s", time, (_color ? _colorCodes[priority] : "%s %s").format(_type[priority], message));
|
||||||
|
} else {
|
||||||
|
writefln("%s %s", time, (_color ? _colorCodes[priority] : "%s %s").format(_type[priority], message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Writes a message to the POSIX syslog.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log.
|
||||||
|
priority = The syslog priority level (e.g., LOG_ERR).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.writesyslog("System crash", ERROR); // Logs to syslog with LOG_ERR
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void writesyslog(string message, int priority) {
|
||||||
|
syslog(priority, message.toStringz());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Log level constants
|
||||||
|
public enum : int {
|
||||||
|
DEBUGGING = 0, /// Debugging messages (lowest priority)
|
||||||
|
ALERT = 1, /// Alert messages (high priority)
|
||||||
|
CRITICAL = 2, /// Critical errors
|
||||||
|
ERROR = 3, /// General errors
|
||||||
|
WARNING = 4, /// Warnings
|
||||||
|
NOTICE = 5, /// Notices
|
||||||
|
INFORMATION = 6 /// Informational messages (highest priority)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Output target flags
|
||||||
|
public enum : int {
|
||||||
|
SYSLOG = 1, /// System log (Event Log on Windows, syslog on POSIX)
|
||||||
|
STD = 2, /// Standard output (stdout for >= WARNING, stderr for <= ERROR)
|
||||||
|
FILE = 8 /// File output
|
||||||
|
}
|
||||||
|
|
||||||
|
immutable string[] _type = [ /// Log level prefixes for formatting
|
||||||
|
"[DEBUG]:", "[ALERT]:", "[CRITICAL]:", "[ERROR]:", "[WARNING]:", "[NOTICE]:", "[INFO]:"
|
||||||
|
];
|
||||||
|
|
||||||
|
/++
|
||||||
|
Core logging function that writes a message to configured outputs.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log.
|
||||||
|
priority = The log level of the message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.writelog("Application started", INFORMATION); // Logs to configured outputs
|
||||||
|
log.writelog("Fatal error", CRITICAL); // Logs to stderr and other outputs
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void writelog(string message, int priority) {
|
||||||
|
synchronized (_mutex) {
|
||||||
|
if (_priority > priority) return;
|
||||||
|
int output = _nowOutput ? _nowOutput : _output;
|
||||||
|
_nowOutput = 0;
|
||||||
|
|
||||||
|
string time;
|
||||||
|
if (output & (STD | FILE)) {
|
||||||
|
time = Clock.currTime().format("%Y.%m.%d %H:%M:%S");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output & SYSLOG) writesyslog(message, _sysPriorityOS[_sysPriority[priority]]);
|
||||||
|
if (output & STD) writestd(time, message, priority);
|
||||||
|
if (output & FILE) writefile(time, message, priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Writes a message to the configured log file.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
time = The timestamp of the message.
|
||||||
|
message = The message to log.
|
||||||
|
priority = The log level of the message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.writefile("2025.03.23 12:00:00", "File operation failed", ERROR); // Writes to log file
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void writefile(string time, string message, int priority) {
|
||||||
|
if (!_writeToFile) return;
|
||||||
|
|
||||||
|
synchronized (_mutex) {
|
||||||
|
if (!_fileOpen) {
|
||||||
|
try {
|
||||||
|
_file = File(_path, "a+");
|
||||||
|
_fileOpen = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
_writeToFile = false;
|
||||||
|
now(this.output.std).error("Unable to open the log file " ~ _path);
|
||||||
|
information(e.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
_file.writefln("%s %s %s", time, _type[priority], message);
|
||||||
|
} catch (Exception e) {
|
||||||
|
_writeToFile = false;
|
||||||
|
now(this.output.std).error("Unable to write to the log file " ~ _path);
|
||||||
|
information(e.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/++
|
||||||
|
Property to access the singleton instance of the logger.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The single instance of the `Log` class.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
auto logger = Log.msg; // Access the singleton logger
|
||||||
|
logger.information("Logger retrieved");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
@property static Log msg() {
|
||||||
|
if (_log is null) {
|
||||||
|
synchronized {
|
||||||
|
if (_log is null) _log = new Log();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Sets the program name for syslog identification.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
name = The name of the program.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
This `Log` instance for chaining.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.program("MyProgram"); // Sets syslog identifier to "MyProgram"
|
||||||
|
log.i("Program name set");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Log program(string name) {
|
||||||
|
synchronized (_mutex) { _name = name.to!wstring; }
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Sets the file path for logging.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
path = The path to the log file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
This `Log` instance for chaining.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.file("myapp.log"); // Sets log file to "myapp.log"
|
||||||
|
log.i("Log file configured");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Log file(string path) {
|
||||||
|
synchronized (_mutex) {
|
||||||
|
if (_fileOpen) { _file.close(); _fileOpen = false; }
|
||||||
|
_path = path;
|
||||||
|
_writeToFile = true;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Sets the minimum log level.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
priority = The minimum log level (e.g., DEBUGGING, ERROR).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
This `Log` instance for chaining.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.level(log.level.warning); // Only WARNING and above will be logged
|
||||||
|
log.d("This won't show"); // Ignored due to level
|
||||||
|
log.w("This will show");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Log level(int priority) {
|
||||||
|
synchronized (_mutex) { _priority = priority; }
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Enables or disables colored console output.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
condition = `true` to enable colors, `false` to disable.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
This `Log` instance for chaining.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.color(true); // Enables colored output
|
||||||
|
log.i("This will be colored");
|
||||||
|
log.color(false); // Disables colored output
|
||||||
|
log.i("This will be plain");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Log color(bool condition) {
|
||||||
|
synchronized (_mutex) { _color = condition; }
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Starts configuring output targets using a fluent interface.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An `Output` struct for chaining output target methods.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
auto outs = log.output.std.file; // Configures std and file output
|
||||||
|
log.output(outs);
|
||||||
|
log.i("Logged to console and file");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Output output() {
|
||||||
|
return Output();
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Sets the default output targets.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
outs = An `Output` struct with configured targets.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
This `Log` instance for chaining.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.output(log.output.syslog.std); // Sets output to syslog and console
|
||||||
|
log.i("Logged to syslog and console");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Log output(Output outs) {
|
||||||
|
synchronized (_mutex) { _output = outs.value; }
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Temporarily overrides output targets for the next log call.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
outs = An `Output` struct with temporary targets.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A `Now` struct to chain the log call.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.std).n("Temporary console output"); // Only to console
|
||||||
|
log.i("Back to default outputs");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Now now(Output outs) {
|
||||||
|
synchronized (_mutex) { _nowOutput = outs.value; }
|
||||||
|
return Now(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs an alert message (priority ALERT).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.alert("System alert!"); // Logs with ALERT level
|
||||||
|
log.a(42); // Logs "42" with ALERT level
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void alert(T)(T message) { writelog(message.to!string, ALERT); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a critical error message (priority CRITICAL).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.critical("Critical failure"); // Logs with CRITICAL level
|
||||||
|
log.c("Out of memory"); // Alias usage
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void critical(T)(T message) { writelog(message.to!string, CRITICAL); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs an error message (priority ERROR).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.error("File not found"); // Logs with ERROR level to stderr
|
||||||
|
log.e("Error code: 404"); // Alias usage
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void error(T)(T message) { writelog(message.to!string, ERROR); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a warning message (priority WARNING).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.warning("Low disk space"); // Logs with WARNING level
|
||||||
|
log.w("Check disk"); // Alias usage
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void warning(T)(T message) { writelog(message.to!string, WARNING); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a notice message (priority NOTICE).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.notice("User logged in"); // Logs with NOTICE level
|
||||||
|
log.n("Session started"); // Alias usage
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void notice(T)(T message) { writelog(message.to!string, NOTICE); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs an informational message (priority INFORMATION).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.information("App started"); // Logs with INFORMATION level
|
||||||
|
log.i("Version 1.0"); // Alias usage
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void information(T)(T message) { writelog(message.to!string, INFORMATION); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a debugging message (priority DEBUGGING).
|
||||||
|
|
||||||
|
Params:
|
||||||
|
message = The message to log (converted to string).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.debugging("Variable x = 5"); // Logs with DEBUGGING level
|
||||||
|
log.d("Entering loop"); // Alias usage
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void debugging(T)(T message) { writelog(message.to!string, DEBUGGING); }
|
||||||
|
|
||||||
|
/++ Alias for `alert` +/
|
||||||
|
alias a = alert;
|
||||||
|
/++ Alias for `critical` +/
|
||||||
|
alias c = critical;
|
||||||
|
/++ Alias for `error` +/
|
||||||
|
alias e = error;
|
||||||
|
/++ Alias for `warning` +/
|
||||||
|
alias w = warning;
|
||||||
|
/++ Alias for `notice` +/
|
||||||
|
alias n = notice;
|
||||||
|
/++ Alias for `information` +/
|
||||||
|
alias i = information;
|
||||||
|
/++ Alias for `debugging` +/
|
||||||
|
alias d = debugging;
|
||||||
|
|
||||||
|
/++
|
||||||
|
Struct for fluent configuration of output targets.
|
||||||
|
|
||||||
|
Provides methods to chain output targets, accumulating them into a bitmask.
|
||||||
|
+/
|
||||||
|
struct Output {
|
||||||
|
private int value = 0;
|
||||||
|
|
||||||
|
/++
|
||||||
|
Adds syslog to the output targets.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.output(log.output.syslog); // Enables syslog output
|
||||||
|
log.i("Logged to syslog");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Output syslog() { value |= SYSLOG; return this; }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Adds standard output (stdout/stderr) to the output targets.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.output(log.output.std); // Enables console output
|
||||||
|
log.w("Logged to console");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Output std() { value |= STD; return this; }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Adds file output to the output targets.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.output(log.output.file); // Enables file output
|
||||||
|
log.i("Logged to file");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Output file() { value |= FILE; return this; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Struct for fluent configuration of log levels.
|
||||||
|
|
||||||
|
Provides methods to specify log levels.
|
||||||
|
+/
|
||||||
|
struct Level {
|
||||||
|
/++ Returns the DEBUGGING level +/
|
||||||
|
int debugging() { return DEBUGGING; }
|
||||||
|
/++ Returns the ALERT level +/
|
||||||
|
int alert() { return ALERT; }
|
||||||
|
/++ Returns the CRITICAL level +/
|
||||||
|
int critical() { return CRITICAL; }
|
||||||
|
/++ Returns the ERROR level +/
|
||||||
|
int error() { return ERROR; }
|
||||||
|
/++ Returns the WARNING level +/
|
||||||
|
int warning() { return WARNING; }
|
||||||
|
/++ Returns the NOTICE level +/
|
||||||
|
int notice() { return NOTICE; }
|
||||||
|
/++ Returns the INFORMATION level +/
|
||||||
|
int information() { return INFORMATION; }
|
||||||
|
|
||||||
|
/++ Alias for `debugging` +/
|
||||||
|
alias d = debugging;
|
||||||
|
/++ Alias for `alert` +/
|
||||||
|
alias a = alert;
|
||||||
|
/++ Alias for `critical` +/
|
||||||
|
alias c = critical;
|
||||||
|
/++ Alias for `error` +/
|
||||||
|
alias e = error;
|
||||||
|
/++ Alias for `warning` +/
|
||||||
|
alias w = warning;
|
||||||
|
/++ Alias for `notice` +/
|
||||||
|
alias n = notice;
|
||||||
|
/++ Alias for `information` +/
|
||||||
|
alias i = information;
|
||||||
|
|
||||||
|
/++
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.level(log.level.d); // Sets level to DEBUGGING
|
||||||
|
log.d("Debug message"); // Visible
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Helper method to start level configuration.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A `Level` struct for chaining level methods.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.level(log.level().warning); // Sets level to WARNING
|
||||||
|
log.i("This won't show"); // Ignored due to level
|
||||||
|
log.w("This will show");
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
Level level() { return Level(); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Struct for temporary output override.
|
||||||
|
|
||||||
|
Provides methods to log messages with temporary output settings.
|
||||||
|
+/
|
||||||
|
struct Now {
|
||||||
|
private Log _log;
|
||||||
|
|
||||||
|
this(Log log) { _log = log; }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs an alert message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.std).alert("Temp alert"); // Only to console
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void alert(T)(T message) { _log.alert(message); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a critical error message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.file).c("Temp critical"); // Only to file
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void critical(T)(T message) { _log.critical(message); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs an error message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.std).e("Temp error"); // Only to stderr
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void error(T)(T message) { _log.error(message); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a warning message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.syslog).w("Temp warning"); // Only to syslog
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void warning(T)(T message) { _log.warning(message); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a notice message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.std).n("Temp notice"); // Only to stdout
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void notice(T)(T message) { _log.notice(message); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs an informational message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.file).i("Temp info"); // Only to file
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void information(T)(T message) { _log.information(message); }
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logs a debugging message.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
log.now(log.output.std).d("Temp debug"); // Only to stdout
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
void debugging(T)(T message) { _log.debugging(message); }
|
||||||
|
|
||||||
|
/++ Alias for `alert` +/
|
||||||
|
alias a = alert;
|
||||||
|
/++ Alias for `critical` +/
|
||||||
|
alias c = critical;
|
||||||
|
/++ Alias for `error` +/
|
||||||
|
alias e = error;
|
||||||
|
/++ Alias for `warning` +/
|
||||||
|
alias w = warning;
|
||||||
|
/++ Alias for `notice` +/
|
||||||
|
alias n = notice;
|
||||||
|
/++ Alias for `information` +/
|
||||||
|
alias i = information;
|
||||||
|
/++ Alias for `debugging` +/
|
||||||
|
alias d = debugging;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Global alias for easy access to the logger instance.
|
||||||
|
|
||||||
|
The `log` alias provides a convenient shortcut to the singleton instance of the `Log` class,
|
||||||
|
allowing direct access to all logging functionality without explicitly calling `Log.msg`.
|
||||||
|
It supports the same methods, configuration options, and features as the `Log` class.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
---
|
||||||
|
import singlog;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Configure the logger using the alias
|
||||||
|
log.program("MyApp")
|
||||||
|
.color(true)
|
||||||
|
.level(log.level.debugging) // Using log.level directly
|
||||||
|
.output(log.output.std.file.syslog)
|
||||||
|
.file("myapp.log");
|
||||||
|
|
||||||
|
// Log messages with full method names
|
||||||
|
log.debugging("App starting in debug mode");
|
||||||
|
log.information("Initialization complete");
|
||||||
|
log.error("Failed to load resource");
|
||||||
|
|
||||||
|
// Log messages with aliases
|
||||||
|
log.d("Debug message via alias");
|
||||||
|
log.i("Info message via alias");
|
||||||
|
log.e("Error message via alias");
|
||||||
|
|
||||||
|
// Temporary output override
|
||||||
|
log.now(log.output.std).n("Temporary console-only message");
|
||||||
|
}
|
||||||
|
---
|
||||||
|
+/
|
||||||
|
alias log = Log.msg;
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 153 KiB |
|
|
@ -0,0 +1,60 @@
|
||||||
|
import singlog;
|
||||||
|
import std.format : format;
|
||||||
|
import std.exception : enforce;
|
||||||
|
|
||||||
|
/++
|
||||||
|
Logging Levels Table:
|
||||||
|
Level | Value | Description
|
||||||
|
--------------|----------|---------
|
||||||
|
DEBUGGING | 0 | Debugging information (highest)
|
||||||
|
ALERT | 1 | Urgent alerts
|
||||||
|
CRITICAL | 2 | Critical errors
|
||||||
|
ERROR | 3 | Errors
|
||||||
|
WARNING | 4 | Warnings
|
||||||
|
NOTICE | 5 | Notices
|
||||||
|
INFORMATION | 6 | Informational messages (lowest)
|
||||||
|
+/
|
||||||
|
void main(string[] argv) {
|
||||||
|
// Logger configuration
|
||||||
|
log.color(true) // Enable colored output
|
||||||
|
.level(log.level.error) // Threshold ERROR (3): shows ERROR and less critical (≥3)
|
||||||
|
.output(log.output.std.file.syslog) // Set all three output targets
|
||||||
|
.file("./test.log") // Set log file
|
||||||
|
.program(argv[0]); // Set program name (Windows only)
|
||||||
|
|
||||||
|
// Application start
|
||||||
|
log.i("ChainDemo application started"); // INFO (6) >= 3
|
||||||
|
log.e("Logging with ERROR level activated"); // ERROR (3) >= 3
|
||||||
|
|
||||||
|
// Level demonstration
|
||||||
|
log.e("Error during operation"); // ERROR (3) >= 3
|
||||||
|
log.w("Warning"); // WARNING (4) >= 3
|
||||||
|
log.n("Important notice"); // NOTICE (5) >= 3
|
||||||
|
log.d("Debugging not shown"); // DEBUGGING (0) < 3
|
||||||
|
log.i("General information"); // INFO (6) >= 3
|
||||||
|
log.a("Alert not shown"); // ALERT (1) < 3
|
||||||
|
|
||||||
|
// Example with data types
|
||||||
|
int errorCode = 500;
|
||||||
|
log.e("Server error %d".format(errorCode)); // ERROR (3) >= 3
|
||||||
|
|
||||||
|
// Temporary output redirection
|
||||||
|
log.now(log.output.std).e("Error only to console"); // ERROR (3) >= 3
|
||||||
|
|
||||||
|
// Exception handling
|
||||||
|
try {
|
||||||
|
enforce(false, "Test exception");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.e("Exception: %s".format(e.msg)); // ERROR (3) >= 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuration change
|
||||||
|
log.color(true)
|
||||||
|
.level(log.level.alert) // Threshold CRITICAL (2): shows CRITICAL and less critical (≥2)
|
||||||
|
.output(log.output.std.file);
|
||||||
|
log.e("This message will be shown (ERROR >= CRITICAL)"); // ERROR (3) >= 2
|
||||||
|
log.a("Configuration changed, ALERT messages"); // ALERT (1) >= 2
|
||||||
|
|
||||||
|
// Finale
|
||||||
|
log.c("Demonstration completed"); // CRITICAL (2) >= 2
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue