https://github.com/marcpage/yalo
Yet Another Logger C++ light-weight logging
https://github.com/marcpage/yalo
c-plus-plus c-plus-plus-11 cplusplus-11 cpp cross-platform header-only logger logging logging-library
Last synced: 16 days ago
JSON representation
Yet Another Logger C++ light-weight logging
- Host: GitHub
- URL: https://github.com/marcpage/yalo
- Owner: marcpage
- License: unlicense
- Created: 2025-02-22T00:35:16.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-03T07:46:23.000Z (over 1 year ago)
- Last Synced: 2025-11-17T01:21:33.649Z (7 months ago)
- Topics: c-plus-plus, c-plus-plus-11, cplusplus-11, cpp, cross-platform, header-only, logger, logging, logging-library
- Language: C++
- Homepage:
- Size: 43.9 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# yalo


[](https://github.com/marcpage/yalo/commits)
[](https://github.com/marcpage/yalo/commits)

[](https://github.com/marcpage/yalo)
[](https://github.com/marcpage/yalo/issues)
[](https://github.com/marcpage?tab=followers)
[](https://github.com/marcpage/yalo/watchers)
Yet Another Logger: C++ light-weight logger
## Features
- Single header file, less than 1,000 lines of code
- Supports C++11 and later
- Supports Linux, macOS, and Windows
- Threadsafe (and thread identification)
- Minimal coding to log
- Logs timestamp, thread, [level](#logging-levels), file, line number, function, condition
- Logs to `stdout`, `stderr`, and/or files
- Customize to log to other destinations
- Customize to change the format of the logging output
- Can create/update a [file to change logging settings while code is running](#changing-log-levels-at-runtime)
- Can automaticaly log all `if`, `while`, and `switch` statements in `Trace` mode
- Can [set logging level per file or group of files](#setlevel)
- Over 80% unit test code coverage
## Logging Levels
| Constant | Call | Description |
|---|---|---|
| yalo::Fatal | lFatal | Always log and call abort() |
| yalo::Fatal | lFatalIf(condition) | If condition is true, log and call abort() |
| yalo::Log | lLog | Information that should always be in the log (version, settings, etc) |
| yalo::Error | lError | An error occurred (default logging level) |
| yalo::Error | lErrorIf(condition) | `condition` is the error condition and will log if true(default logging level) |
| yalo::Warning | lWarn | Warn about potential problems |
| yalo::Warning | lWarnIf(condition) | `condition` is a potential problem if true |
| yalo::Info | lInfo | Log general information |
| yalo::Debug | lDebug | Log information helpful for debugging |
| yalo::Verbose | lVerbose | Log an excessive amount of information for deeper debugging |
| yalo::Trace | lTrace | Log execution, including every `if`, `while`, and `switch` |
### Trace if, while, and switch
By default, every `if`, `while`, and `switch` will be available in `yalo::Trace` mode.
This adds a small amount of code to every `if`, `while` iteration, and `switch`.
While this code is small, it may have a performance impact.
To disable this tracing ability, you can define `DISABLE_YALO_TRACE`.
### Example logging code
```C++
lLog << "Program version" << version_string;
lErr << "We're all going to die!";
lErrIf(file == nullptr) << "crash eminent!";
lWarn << "Warning!";
lWarnIf(size > 5) << "We should work but this is kind of big" << size;
lInfo << "How did we get here?";
lDebug << "iteration #" << iteration << "size = " << size;
lVerbose << "Checking if we should move forward";
lTrace << "Here";
if (x == 5 && y == 7) {...}
```
### Example log
The log can output the following information:
- Timestamp (local or GMT)
- Thread index (index of the order in which the threads logged)
- Log [level](#logging-levels)
- Source file
- Source line number
- Function or method
- Conditional that triggered the logging
- The log message
```html
[2025-02-23 02:52:22.912 (Sun)][0][LOG] New Settings File: bin/testCommandFile.txt
[2025-02-23 02:52:22.912 (Sun)][0][LOG] Resetting format to default GMT
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] Resetting format to default
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] Adding sink to bin/testCommandFile.log
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] resetLevels to 0
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] Turned padding on
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] Turned padding off
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] Set level #1 pattern = ''
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] Set level #4 pattern = 'test_yalo.cpp'
[2025-02-22 20:52:22.912 -0600 (Sat)][0][DBG][src/tests/test_yalo.cpp:495][testCommandFile] testing
[2025-02-22 20:52:22.912 -0600 (Sat)][0][LOG] New Settings File: bin/nonexistant/path/testCommandFile.txt
[2025-02-23 02:52:22.912 (Sun)][0][WRN][src/tests/test_yalo.cpp:523][testConditionals][value1 > 2] too big
[2025-02-23 02:52:22.912 (Sun)][0][ERR][src/tests/test_yalo.cpp:524][testConditionals][value1 < 10] too small
[2025-02-23 02:52:22.913 (Sun)][0][LOG] New Settings File: bin/nonexistant/path/testCommandFile.txt
```
## Changing log levels at Runtime
In the code you can specify a path to a file to watch for logging settings.
You can do this by calling `yalo::Logger::setSettingsFile({path}, {secondsBetweenChecks});`
Here is an example of the file:
```
setLevel: Error
setLevel: Trace=main.cpp
addSinkStdErr
addSink:debugging.txt
```
You can have the following commands in the file:
- [addSink](#addsink)
- [addSinkStdErr](#addsinkstderr)
- [addSinkStdOut](#addsinkstdout)
- [clearSinks](#clearsinks)
- [noPad](#nopad)
- [pad](#pad)
- [resetLevels](#resetlevels)
- [setFormatDefault](#setformatdefault)
- [setFormatDefaultGMT](#setformatdefaultgmt)
- [setLevel](#setlevel) (globally and for specific files)
### addSink
Same as calling `Logger::addSink(std::unique_ptr(new FileSink({path})));`
```
addSink:{path}
```
Starts logging to the given path.
### addSinkStdErr
Same as calling `Logger::addSink(std::unique_ptr(new StdErrSink()));`
```
addSinkStdErr
```
Starts logging to `stderr`.
*Note*: If you are already logging to `stderr` or specify this command more than once you will see duplicate lines.
### addSinkStdOut
Same as calling `Logger::addSink(std::unique_ptr(new StdOutSink()));`
```
addSinkStdOut
```
Starts logging to `stdout`.
*Note*: If you are already logging to `stdout` or specify this command more than once you will see duplicate lines.
### clearSinks
Same as calling `Logger::clearSinks();`
```
clearSinks
```
Removes all current logging sinks.
*Note*: If this is not immedeately followed by `addSinkStdOut`, `addSinkStdErr`, or `addSink` then `addSinkStdErr` will automatically happen.
### noPad
Same as calling `Logger::setInserterSpacing(InserterAsIs);`
```
noPad
```
When log streaming, no extra spacing will be inserted between inserts.
```
lLog << "test" << 5 << "more";
```
will result in logging:
```
test5more
```
### pad
Same as calling `Logger::setInserterSpacing(InserterPad);`
```
pad
```
When log streaming, an extra space will be inserted between inserts.
```
lLog << "test" << 5 << "more";
```
will result in logging:
```
test 5 more
```
### resetLevels
Same as calling `Logger::resetLevels(_fromString({level}));`
```
resetLevels:{level}
```
Clears all file pattern files and sets all logging to [{level}](#logging-levels).
### setFormatDefault
Same as calling `Logger::setFormat(std::unique_ptr(new DefaultFormatter()));`
```
setFormatDefault
```
Reset the log formatter back to the default, using local time.
### setFormatDefaultGMT
Same as calling `Logger::setFormat(std::unique_ptr(new DefaultFormatter(DefaultFormatter::GMT)));`
```
setFormatDefaultGMT
```
Reset the log formatter back to the default, using GMT time.
### setLevel
Same as calling `Logger::setLevel({level}, {pattern});`
```
setLevel:{level}
setLevel:{level}={pattern}
```
The first entry will set the default global [{level}](#logging-levels).
The second entry will set the [{level}](#logging-levels) for the given [file pattern](#file-patterns).
#### File Patterns
You can specify a file matching pattern to change the logging level per file or group of files.
The pattern consists of case-sensitive substrings to look for in the file, separated by semicolon (`;`).
If a pattern begins with a minus (`-`) then it will not match that pattern.
The evaluation walks through all the patterns with positive patterns being ORed in and negative patterns removing files.
##### File pattern example
```
src/;-src/include/;-main.cpp
```
This is interpreted as: files that contain `src/` in them, but do not include `src/include` and do not include `main.cpp`.
Basically take your filename and walk through the pattern and add it if at matches a positive and remove it when it matches a negative.
```
src/;-src/include/;.cpp
```
This example shows all files under `src/`, but not files in `src/include/`, but do include `.cpp` files (including those in `src/include/`).