Merge branch 'master' of github.com:nojhan/clutchlog

This commit is contained in:
Johann Dreo 2022-09-07 22:47:56 +02:00
commit 0fc2b0cc23
2 changed files with 111 additions and 42 deletions

View file

@ -7,7 +7,14 @@ Clutchlog — versatile (de)clutchable logging
- [Project page on Github](https://github.com/nojhan/clutchlog) - [Project page on Github](https://github.com/nojhan/clutchlog)
- [Documentation](https://nojhan.github.io/clutchlog/) - [Documentation](https://nojhan.github.io/clutchlog/)
![Clutchlog logo](https://raw.githubusercontent.com/nojhan/clutchlog/master/docs/clutchlog_logo.svg) <p align="center">
<img
alt"Clutchlog logo"
src="https://raw.githubusercontent.com/nojhan/clutchlog/master/docs/clutchlog_logo.svg"
width="400"
/>
</p>
[TOC] [TOC]
Features Features
@ -77,23 +84,6 @@ API documentation
================= =================
Log level semantics
-------------------
Log levels use a classical semantics for a human skilled in the art, in decreasing order of importance:
- *Critical*: an error that cannot be recovered. For instance, something which will make a server stop right here.
- *Error*: an error that invalidates a function, but may still be recovered. For example, a bad user input that will make a server reset its state, but not crash.
- *Warning*: something that is strange, but is probably legit. For example a default parameter is set because the user forgot to indicate its preference.
- *Progress*: the state at which computation currently is.
- *Note*: some state worth noting to understand what's going on.
- *Info*: any information that would help ensuring that everything is going well.
- *Debug*: data that would help debugging the program if there was a bug later on.
- *XDebug*: debugging information that would be heavy to read.
Note: the log levels constants are lower case (for example: `clutchlog::level::xdebug`), but their string representation is not (e.g. "XDebug", this should be taken into account when using `threshold` or `level_of`).
Calls Calls
----- -----
@ -128,6 +118,23 @@ CLUTCHDUMP(debug, vec, "test_{n}.dat");
Note that if you pass a file name without the `{n}` tag, the file will be overwritten as is. Note that if you pass a file name without the `{n}` tag, the file will be overwritten as is.
Log level semantics
-------------------
Log levels use a classical semantics for a human skilled in the art, in decreasing order of importance:
- *Critical*: an error that cannot be recovered. For instance, something which will make a server stop right here.
- *Error*: an error that invalidates a function, but may still be recovered. For example, a bad user input that will make a server reset its state, but not crash.
- *Warning*: something that is strange, but is probably legit. For example a default parameter is set because the user forgot to indicate its preference.
- *Progress*: the state at which computation currently is.
- *Note*: some state worth noting to understand what's going on.
- *Info*: any information that would help ensuring that everything is going well.
- *Debug*: data that would help debugging the program if there was a bug later on.
- *XDebug*: debugging information that would be heavy to read.
Note: the log levels constants are lower case (for example: `clutchlog::level::xdebug`), but their string representation is not (e.g. "XDebug", this should be taken into account when using `threshold` or `level_of`).
Location filtering Location filtering
------------------ ------------------
@ -234,7 +241,16 @@ and its default with the `CLUTCHLOG_DEFAULT_HFILL_MARK` macro:
log.hfill_mark(CLUTCHLOG_DEFAULT_HFILL_MARK); // Defaults to '.'. log.hfill_mark(CLUTCHLOG_DEFAULT_HFILL_MARK); // Defaults to '.'.
``` ```
Note: if the system detects no terminal, only a single fill character is inserted. Clutchlog measures the width of the standard error channel.
If it is redirected, it may be measured as very large.
Thus, the `hfill_max` accessors allow to set a maximum width (in number of characters).
```cpp
log.hfill_max(CLUTCHLOG_DEFAULT_HFILL_MAX); // Defaults to 300.
```
Note: clutchlog will select the minimum between `hfill_max`
and the measured number of columns in the terminal,
so that you may use `hfill_max` as a way to constraint the output width
in any cases.
## Stack Depth ## Stack Depth
@ -306,6 +322,12 @@ log.format(format.str());
Note: messages at the "critical", "error" and "warning" log levels are colored by default. Note: messages at the "critical", "error" and "warning" log levels are colored by default.
You may want to set their style to `none` if you want to stay in control of inserted colors in the format template. You may want to set their style to `none` if you want to stay in control of inserted colors in the format template.
The horizontal filling line (the `{hfill}` tag) can be configured separately with `hfill_style`,
for example:
```cpp
log.hfill_style(clutchlog::fmt::fg::black);
```
Disabled calls Disabled calls
-------------- --------------
@ -318,7 +340,7 @@ by setting the `WITH_CLUTCHLOG` preprocessor variable.
When the `NDEBUG` preprocessor variable is set (e.g. in `Release` build), When the `NDEBUG` preprocessor variable is set (e.g. in `Release` build),
clutchlog will do its best to allow the compiler to optimize out any calls clutchlog will do its best to allow the compiler to optimize out any calls
for log levels that are under or equal to `progress`. for log levels that are under `progress`.
You can change this behavior at compile time by setting the You can change this behavior at compile time by setting the
`CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG` preprocessor variable `CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG` preprocessor variable

View file

@ -1,6 +1,6 @@
#ifndef __CLUTCHLOG_H__
#define __CLUTCHLOG_H__
#pragma once #pragma once
#ifndef CLUTCHLOG_H
#define CLUTCHLOG_H
/** @file */ /** @file */
#include <ciso646> #include <ciso646>
@ -257,10 +257,23 @@ class clutchlog
#endif // CLUTCHLOG_HFILL_MARK #endif // CLUTCHLOG_HFILL_MARK
//! Default character used as a filling for right-align the right part of messages with "{hfill}". //! Default character used as a filling for right-align the right part of messages with "{hfill}".
static inline char default_hfill_char = CLUTCHLOG_HFILL_MARK; static inline char default_hfill_char = CLUTCHLOG_HFILL_MARK;
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
#ifndef CLUTCHLOG_HFILL_MAX
#define CLUTCHLOG_HFILL_MAX 300
#endif
#endif
//! Default maximum number of character used as a filling for right-align the right part of messages with "{hfill}".
static inline unsigned short default_hfill_max = CLUTCHLOG_HFILL_MAX;
// NOTE: there is no CLUTCHLOG_HFILL_STYLE for defaulting,
// but you can still set `hfill_style(...)` on the logger singleton.
/* @} */ /* @} */
public: public:
/** @name High-level API /** @name High-level API
* @{ */ * @{ */
@ -435,7 +448,11 @@ class clutchlog
}), }),
_format_log(clutchlog::default_format), _format_log(clutchlog::default_format),
_format_dump(clutchlog::dump_default_format), _format_dump(clutchlog::dump_default_format),
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
_hfill_char(clutchlog::default_hfill_char), _hfill_char(clutchlog::default_hfill_char),
_hfill_fmt(fmt::fg::none),
_hfill_max(clutchlog::default_hfill_max),
#endif
_out(&std::clog), _out(&std::clog),
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
_depth(std::numeric_limits<size_t>::max() - _strip_calls), _depth(std::numeric_limits<size_t>::max() - _strip_calls),
@ -452,8 +469,8 @@ class clutchlog
} }
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
struct winsize w; struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
_nb_columns = w.ws_col; _nb_columns = std::min(w.ws_col, default_hfill_max);
#endif #endif
} }
@ -470,8 +487,14 @@ class clutchlog
std::string _format_log; std::string _format_log;
/** Current format of the file output. */ /** Current format of the file output. */
std::string _format_dump; std::string _format_dump;
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
/** Character for filling. */ /** Character for filling. */
char _hfill_char; char _hfill_char;
/** Style of the filling. */
fmt _hfill_fmt;
/** Maximum number of fill char. */
unsigned short _hfill_max;
#endif
/** Standard output. */ /** Standard output. */
std::ostream* _out; std::ostream* _out;
#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
@ -541,6 +564,20 @@ class clutchlog
void hfill_mark(const char mark) {_hfill_char = mark;} void hfill_mark(const char mark) {_hfill_char = mark;}
//! Get the character for the stretching hfill marker. //! Get the character for the stretching hfill marker.
char hfill_mark() const {return _hfill_char;} char hfill_mark() const {return _hfill_char;}
//! Set the style for the stretching hfill marker, with a `fmt` object.
void hfill_style(fmt style) {_hfill_fmt = style;}
/** Set the style for the stretching hfill marker.
*
* This version accept style arguments as if they were passed to `clutchlog::fmt`.
*/
template<class ... FMT>
void style(FMT... styles) { this->hfill_style(fmt(styles...)); }
//! Get the character for the stretching hfill marker.
fmt hfill_style() const {return _hfill_fmt;}
//! Set the maximum number of hfill characters. */
void hfill_max(const size_t nmax) {_hfill_max = nmax;}
//! Get the maximum number of hfill characters. */
unsigned short hfill_max() {return _hfill_max;}
#endif #endif
//! Set the log level (below which logs are not printed) with an identifier. //! Set the log level (below which logs are not printed) with an identifier.
@ -800,15 +837,19 @@ class clutchlog
if(right_len+left_len > _nb_columns) { if(right_len+left_len > _nb_columns) {
// The right part would go over the terminal width: add a new line. // The right part would go over the terminal width: add a new line.
const std::string hfill(std::max((size_t)0, _nb_columns-right_len), _hfill_char); const std::string hfill(std::max((size_t)0, _nb_columns-right_len), _hfill_char);
format = replace(format, "\\{hfill\\}", "\n"+hfill); const std::string hfill_styled = _hfill_fmt(hfill);
format = replace(format, "\\{hfill\\}", "\n"+hfill_styled);
} else { } else {
// There is some space in between left and right parts. // There is some space in between left and right parts.
const std::string hfill(std::max((size_t)0, _nb_columns - (right_len+left_len)), _hfill_char); const std::string hfill(std::max((size_t)0, _nb_columns - (right_len+left_len)), _hfill_char);
format = replace(format, "\\{hfill\\}", hfill); const std::string hfill_styled = _hfill_fmt(hfill);
format = replace(format, "\\{hfill\\}", hfill_styled);
} }
} else { } else {
// We don't know the terminal width. // We don't know the terminal width.
format = replace(format, "\\{hfill\\}", _hfill_char); const std::string hfill(1, _hfill_char);
const std::string hfill_styled = _hfill_fmt(hfill);
format = replace(format, "\\{hfill\\}", hfill_styled);
} }
} }
#endif #endif
@ -967,12 +1008,16 @@ class clutchlog
#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1 #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
void hfill_mark(const char) {} void hfill_mark(const char) {}
char hfill_mark() const {} char hfill_mark() const {}
void hfill_fmt(fmt) {}
fmt hfill_fmt() const {}
void hfill_max(const size_t) {}
unsigned short hfill_max() {}
#endif #endif
void threshold(level) {} void threshold(level) {}
void threshold(const std::string&) {} void threshold(const std::string&) {}
level threshold() const {} level threshold() const {}
const std::map<std::string,level> levels() const {}; const std::map<std::string,level> levels() const {}
level level_of(const std::string) {} level level_of(const std::string) {}
void file(std::string) {} void file(std::string) {}
@ -988,6 +1033,8 @@ class clutchlog
) )
{} {}
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
template<class ... FMT>
void style(level, FMT...) {}
void style(level, fmt) {} void style(level, fmt) {}
fmt style(level) const {} fmt style(level) const {}
public: public:
@ -1042,4 +1089,4 @@ class clutchlog
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif // WITH_CLUTCHLOG #endif // WITH_CLUTCHLOG
#endif // __CLUTCHLOG_H__ #endif // CLUTCHLOG_H