Update to 1.0.0

This commit is contained in:
Alexander Zhirov 2025-03-23 22:46:02 +03:00
parent 075ccdcdcc
commit 2b218f171f
8 changed files with 1217 additions and 347 deletions

View File

@ -1,6 +1,53 @@
# Changelog
## [v0.5.0](https://git.zhirov.kz/dlang/singlog/compare/v0.4.0...v0.5.0) (2023.07.21)
## [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
@ -13,7 +60,7 @@
- Fixed streams redirection in Windows
## [v0.4.0](https://git.zhirov.kz/dlang/singlog/compare/v0.3.2...v0.4.0) (2023.06.07)
## [0.4.0] - 2023-06-07
- Part of the code has been changed/rewritten
@ -25,18 +72,18 @@
- In Windows, unicode messages are output without distortion to the system log and console (thanks [Adam D. Ruppe](https://arsdnet.net/))
## [v0.3.2](https://git.zhirov.kz/dlang/singlog/compare/v0.3.1...v0.3.2) (2023.06.01)
## [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
## [v0.3.1](https://git.zhirov.kz/dlang/singlog/compare/v0.3.0...v0.3.1) (2023.05.30)
## [0.3.1] - 2023-05-30
### Bug fixes
- Log of debug messages
## [v0.3.0](https://git.zhirov.kz/dlang/singlog/compare/v0.2.1...v0.3.0) (2023.04.28)
## [0.3.0] - 2023-04-28
- Minor changes
@ -44,7 +91,7 @@
- Windows OS Logging support
## [v0.2.1](https://git.zhirov.kz/dlang/singlog/compare/v0.2.0...v0.2.1) (2023.03.29)
## [0.2.1] - 2023-03-29
### New
@ -54,7 +101,7 @@
- Calling the main object
## [v0.2.0](https://git.zhirov.kz/dlang/singlog/compare/v0.1.0...v0.2.0) (2023.03.29)
## [0.2.0] - 2023-03-29
- Removed functions `fileOn()` and `fileOff()`
@ -62,7 +109,7 @@
- Simultaneous writing to the standard stream, syslog and file by binary setting the output flag
## [v0.1.0](https://git.zhirov.kz/dlang/singlog/commits/df602a8d0083249068b480e4a92cf7932f2c582b) (2023.03.23)
## [0.1.0] - 2023-03-23
### The first stable working release

195
README.md
View File

@ -7,95 +7,146 @@
[![linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black)](https://www.linux.org/)
[![windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=white)](https://support.microsoft.com/en-US/windows)
Singleton for simple logging
# `singlog` - Singleton Logging Module
## Basic Usage
```d
import singlog;
void main(string[] argv) {
log.output(log.output.syslog.stderr.stdout.file) // write to syslog, standard error/output streams and file
.program(argv[0]) // program name as an identifier (for Windows OS)
.level(log.level.debugging) // logging level
.color(true) // color text output
.file("./test.log"); // the path to the log file
log.i("This is an information message");
log.n("This is a notice message");
log.w("This is a warning message");
log.e("This is an error message");
log.c("This is a critical message");
log.a("This is an alert message");
log.d("This is a debug message");
log.now(log.output.stdout).n("This error message will only be written to the standard output stream");
log.now(log.output.syslog.file).c("This error message will only be written to the syslog and file");
}
```
`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.
![output](tests/terminal.png)
![output](tests/cmd.png)
## Examples
## Features
Setting the name of the logged program (it matters for Windows OS):
- **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 projects 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. Heres a basic example:
```d
log.program("My program");
import singlog;
void main() {
// Configure the logger
log.program("MyApp") // Set program name for syslog/Event Log
.color(true) // Enable colored console output
.level(log.level.debugging) // Set minimum log level to DEBUGGING
.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");
}
```
Setting the status of color text output (`false` by default):
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.
### 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
log.d("Debug message");
log.i("Info message");
log.e("Error message");
```
### 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
log.output(log.output.std.file); // Console and file output
log.i("This goes to console and file");
```
### Temporary Output Override
Use `now()` to temporarily override output targets for the next log call:
```d
log.now(log.output.std).n("This goes only to console");
log.i("This uses default outputs again");
```
### Colored Output
Enable colored output with `color(true)`:
```d
log.color(true);
log.w("This warning will be yellow on POSIX or Windows");
log.c("This critical message will be magenta");
```
Setting the error output level:
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`).
### File Logging
Set a log file with `file()`:
```d
log.level(log.level.debugging);
log.level(log.level.alert);
log.level(log.level.critical);
log.level(log.level.error);
log.level(log.level.warning);
log.level(log.level.notice);
log.level(log.level.information);
log.file("app.log");
log.e("This error goes to app.log");
```
Assigning a target output:
```d
log.output(log.output.syslog.stderr.stdout);
```
Setup and allowing writing to a file:
```d
log.output(log.output.file);
log.file("./file.log");
```
Write messages to the log:
```d
log.a("Alert message") => log.alert("Alert message");
log.c("Critical message") => log.critical("Critical message");
log.e("Error message") => log.error("Error message");
log.w("Warning message") => log.warning("Warning message");
log.n("Notice message") => log.notice("Notice message");
log.i("Information message") => log.information("Information message");
log.d("Debugging message") => log.debugging("Debugging message");
```
Write message to specific outputs:
```d
log.now(log.output.stdout).n("This error message will only be written to the standard output stream");
log.now(log.output.syslog.file).c("This error message will only be written to the syslog and file");
```
## DUB
Add a dependency on `"singlog": "~>0.5.0"`.
The file is opened in append mode (`"a+"`) and includes timestamps.

111
man/singlog.3 Normal file
View File

@ -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

111
man/singlog.ru.3 Normal file
View File

@ -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 АВТОР
Александр Жиров

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 153 KiB

View File

@ -1,20 +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) {
log.output(log.output.syslog.stderr.stdout.file) // write to syslog, standard error/output streams and file
.program(argv[0]) // program name as an identifier (for Windows OS)
.level(log.level.debugging) // logging level
.color(true) // color text output
.file("./test.log"); // the path to the log file
// 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)
log.i("This is an information message");
log.n("This is a notice message");
log.w("This is a warning message");
log.e("This is an error message");
log.c("This is a critical message");
log.a("This is an alert message");
log.d("This is a debug message");
// Application start
log.i("ChainDemo application started"); // INFO (6) >= 3
log.e("Logging with ERROR level activated"); // ERROR (3) >= 3
log.now(log.output.stdout).n("This error message will only be written to the standard output stream");
log.now(log.output.syslog.file).c("This error message will only be written to the syslog and file");
// 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
}