Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 67 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,39 @@ Now, you can download this repository and manually integrate
2022-09-25 22:26:16 [INFO] main.cpp main() at line 11: Hello, world!
2022-09-25 22:26:16 [INFO] main.cpp main() at line 12: Short form
```
_Notice: you can change timezone for timestamps with_
```C++
void utils::Time::set_timzone(int tz);
```
_For example for Moscow: `set_timezone(3)`._

## Macros

This tools contains a lot of macros.
You can choose any _(See file `log.hpp`)_.

The most important and "root" macros are `LOG(severity)` and
`LOG_IF(condition, severity)`.

| Original macro | Long form | Short form | Message |
| --- | --- | --- | --- |
| LOG(logger::fatal) | LOG_FATAL | LOGF | `fatal` error |
| LOG(logger::error) | LOG_ERROR | LOGE | `error` |
| LOG(logger::warning) | LOG_WARN | LOGW | `warning` |
| LOG(logger::info) | LOG_INFO | LOGI | `info`|
| LOG(logger::trace) | LOG_TRACE | LOGT | `trace` |
| LOG(logger::debug) | LOG_DEBUG | LOGD | `debug` |

The same table of macros, but with condition:

| Original macro | Long form | Short form | Message |
| --- | --- | --- | --- |
| LOG_IF(condition, logger::fatal) | LOG_FATAL_IF(condition) | LOGF_IF(condition) | `fatal` error |
| LOG_IF(condition, logger::error) | LOG_ERROR_IF(condition) | LOGE_IF(condition) | `error` |
| LOG_IF(condition, logger::warning) | LOG_WARN_IF(condition) | LOGW_IF(condition) | `warning` |
| LOG_IF(condition, logger::info) | LOG_INFO_IF(condition) | LOGI_IF(condition) | `info`|
| LOG_IF(condition, logger::trace) | LOG_TRACE_IF(condition) | LOGT_IF(condition) | `trace` |
| LOG_IF(condition, logger::debug) | LOG_DEBUG_IF(condition) | LOGD_IF(condition) | `debug` |

## Appenders
You can write logs in the several places at the same time.
Expand Down Expand Up @@ -78,11 +111,12 @@ path of which was specified during `logger::init` call.

#### File Creation

When you invoke `logger::init()`, you pass path to the logs directory
as the second argument. This path is processed by internal functions
and as result new folder for the logs will be created.
When you invoke `logger::init()`, you pass path to the log's directory
or to the desired regular file as the second argument.
This path is processed by internal functions and as result
new folder for the logs will be created.

New folder pass will be according to this table:
New folder path will be according to this table:

| Existence | Your path | Result folder | Result path |
| --- | --- | --- | --- |
Expand All @@ -99,10 +133,38 @@ which was specified during `logger::init` call.
Logs recorded with the `ConsoleAppender` have special colours
according to the `Severity` level.

You can colour every message with special severity as you want.
Just use method `set_console_colour` in the `Logger` class:
```C++
void set_console_colour(Severity severity, const MessageColours& msg_cols);
```
where `MessageColours` is a struct, which consist of two colours:
for the text and its background.
```C++
struct MessageColours {
Colour text;
Colour bg;
};
```

Also, you can turn coloured output off, just use the following methods:
```C++
void turn_colours_on();
void turn_colours_off();
```

#### Example:
```C++
logger::Logger::get()->set_console_colour(logger::info,
{logger::yellow, logger::common});
```
where `logger::common` equals to "without colour"
(transparent background or common text colour).

## Inspired by

Some ideas of implementation was inspired by
[PLOG](https://github.com/SergiusTheBest/plog#license) project, which
[PLOG](https://github.com/SergiusTheBest/plog) project, which
is more complicated and thoughtful for now :)

## License
Expand Down
124 changes: 0 additions & 124 deletions include/appenders.hpp

This file was deleted.

30 changes: 30 additions & 0 deletions include/appenders/appender_interface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include "record.hpp"
#include "severity.hpp"

namespace logger {

namespace fs = std::filesystem;

enum AppenderType {
file,
console
};

class IAppender {
public:
IAppender(AppenderType type) : appender_type_(type) {}
IAppender(AppenderType type, Severity severity) : appender_type_(type), severity_(severity) {}
virtual ~IAppender() = default;
virtual void write(const Record& record) = 0;
Severity severity() const { return severity_; }
void set_severity(Severity severity) { severity_ = severity; }
AppenderType type() const { return appender_type_; }

private:
Severity severity_ = silent;
AppenderType appender_type_;
};

} // logger
61 changes: 61 additions & 0 deletions include/appenders/console_appender.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#include <iostream>
#include <map>

#include "appenders/appender_interface.hpp"
#include "colours.hpp"
#include "record.hpp"
#include "severity.hpp"

namespace logger {

enum StreamType {
cout,
cerr
};

struct MessageColours {
MessageColours() = default;
MessageColours(Colour text_col, Colour bg_col)
: text(text_col), bg(bg_col) {}

Colour text = common;
Colour bg = common;
};

class ConsoleAppender : public IAppender {
public:
ConsoleAppender(Severity severity, StreamType os_type)
: IAppender(AppenderType::console, severity),
output_(os_type == cout ? std::cout : std::cerr) {}

void write(const Record& record) override {
Severity sev = record.severity();
MessageColours msg_col = severity_colours_[sev];
if (coloured)
output_ << to_text_colour(msg_col.text) << to_bg_colour(msg_col.bg);
output_ << record.to_string();
output_ << to_text_colour(common);
}

void set_msg_colours(Severity severity, const MessageColours& msg_cols) {
severity_colours_[severity] = msg_cols;
}
void turn_colours_on() { coloured = true; }
void turn_colours_off() { coloured = false; }

private:
std::ostream& output_;
bool coloured = true;
std::map<Severity, MessageColours> severity_colours_ = {
{fatal, {white, red}},
{error, {red, common}},
{warning, {yellow, common}},
{info, {common, common}},
{trace, {light_gray, common}},
{debug, {white, common}}
};
};

} // logger
73 changes: 73 additions & 0 deletions include/appenders/file_appender.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#pragma once

#include <filesystem>
#include <fstream>
#include <iostream>

#include "appenders/appender_interface.hpp"
#include "record.hpp"
#include "severity.hpp"
#include "utils.hpp"

namespace logger {

namespace fs = std::filesystem;

class FileAppender : public IAppender {
public:
FileAppender() : IAppender(AppenderType::file) {}
FileAppender(Severity severity, const fs::path& path,
std::ios_base::openmode mode = std::ios::out)
: IAppender(AppenderType::file, severity) {
if (utils::maybe_regular_file(path) && fs::exists(utils::get_parent_path(path))) {
this->set_path(path);
} else {
this->create_dir(path);
this->configure_file();
}
this->open(mode);
}

void set_path(const fs::path& path) {
if (!fs::exists(path) || fs::is_regular_file(path))
path_ = path;
}
const fs::path& path() const { return path_; }

void open(std::ios_base::openmode mode = std::ios::out) { output_.open(path_, mode); }
void close() { if (this->is_open()) output_.close(); }
bool is_open() const { return output_.is_open(); }

template <typename T>
FileAppender& operator<<(const T& data) {
output_ << data;
return (*this);
}
FileAppender& operator<<(std::ostream& (* os)(std::ostream&)) {
output_ << os;
return (*this);
}
void write(const Record& record) override {
output_ << record.to_string();
}

private:
fs::path dir_;
fs::path path_;
std::ofstream output_;

void create_dir(const fs::path& path) {
if (fs::exists(path))
dir_ = (fs::is_directory(path) ? path : path.parent_path()).string();
else
dir_ = utils::get_parent_path(path).string() + "/" + utils::get_dirname(path);
fs::create_directories(dir_);
}
void configure_file() {
utils::Time timestamp;
auto filepath = utils::to_filepath(timestamp, dir_);
this->set_path(filepath);
}
};

} // logger
Loading