-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of github.com:motis-project/utl
- Loading branch information
Showing
14 changed files
with
341 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,5 +2,11 @@ | |
*.sublime-* | ||
/.idea | ||
/deps | ||
/docs/conf.py | ||
/docs/Doxyfile | ||
/docs/html | ||
/docs/xml | ||
/public | ||
/.vscode | ||
_build/ | ||
.clang-tidy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
 | ||
 | ||
 | ||
|
||
|
||
This repository contains universally useful C++ utilities. | ||
|
||
Documentation: https://motis-project.github.io/utl/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# MOTIS utl module documentation | ||
MOTIS is an open-source software platform for efficient planning and routing in multi-modal transportation systems. | ||
GitHub main repository: https://github.com/motis-project/motis | ||
|
||
This is the documentation for the **utl** (utility) module. | ||
|
||
:::{toctree} | ||
:maxdepth: 2 | ||
:caption: Contents: | ||
::: | ||
|
||
## Logging | ||
The simplest way to produce log lines is to use the `utl:log()` function, | ||
or the wrapping functions for the various log levels, | ||
`utl::log_debug()`, `utl::log_info()` and `utl::log_error()`: | ||
```c++ | ||
#include "utl/logging.h" | ||
|
||
utl::log_info("MyCtx", "Simple message"); | ||
``` | ||
The first parameter is the **context**, that provides an information of the origin of the log line inside MOTIS code. | ||
The following log levels are supported: | ||
debug | ||
: Messages that contain information only useful when debugging MOTIS | ||
info | ||
: Important information about a normal behavior of the program | ||
error | ||
: Details on an abnormal behavior of the application | ||
### Advanced usage | ||
You can insert variables in the message by using `{}` and passing them as extra arguments | ||
(formatting is performed by the [fmt](https://fmt.dev>) library): | ||
```c++ | ||
utl::log_info("MyCtx", "String={} Int={}", "Hello", 42); | ||
``` | ||
|
||
You can specify **metadata** using `.attrs()`: | ||
```c++ | ||
utl::log_info("MyCtx", "Message").attrs({{"key1", "value1"}, {"key2", "value2"}}); | ||
``` | ||
### API details | ||
:::{doxygenstruct} utl::log | ||
:no-link: | ||
:members: | ||
::: | ||
:::{doxygenstruct} utl::log_debug | ||
:no-link: | ||
:members: | ||
::: | ||
:::{doxygenstruct} utl::log_info | ||
:no-link: | ||
:members: | ||
::: | ||
:::{doxygenstruct} utl::log_error | ||
:no-link: | ||
:members: | ||
::: | ||
:::{note} | ||
Those logging function are an exception to the rule that, in MOTIS, | ||
we use [Aggregate Initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization) wherever possible, | ||
but here we do not want to use `utl::log_info{...}`. | ||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,123 @@ | ||
#pragma once | ||
|
||
#ifdef LOGGING_HEADER | ||
#include LOGGING_HEADER | ||
#else | ||
|
||
#include <chrono> | ||
#include <cstring> | ||
#include <ctime> | ||
#include <iomanip> | ||
#include <iostream> | ||
#include <mutex> | ||
#include <source_location> | ||
#include <sstream> | ||
#include <string> | ||
|
||
#ifdef _MSC_VER | ||
#define gmt(a, b) gmtime_s(b, a) | ||
#else | ||
#define gmt(a, b) gmtime_r(a, b) | ||
#endif | ||
#include "fmt/core.h" | ||
#include "fmt/ostream.h" | ||
|
||
#define FILE_NAME \ | ||
(strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) | ||
namespace utl { | ||
|
||
#define uLOG(lvl) \ | ||
utl::log() << "[" << utl::log::str[lvl] << "]" \ | ||
<< "[" << utl::time() << "]" \ | ||
<< "[" << FILE_NAME << ":" << __LINE__ << "]" \ | ||
<< " " | ||
/// Log level | ||
enum class log_level { debug, info, error }; | ||
|
||
namespace utl { | ||
constexpr char const* to_str(log_level const level) { | ||
switch (level) { | ||
case log_level::debug: return "debug"; | ||
case log_level::info: return "info"; | ||
case log_level::error: return "error"; | ||
} | ||
return ""; | ||
} | ||
|
||
struct log { | ||
log() = default; | ||
extern log_level log_verbosity; | ||
|
||
log(log const&) = delete; | ||
log& operator=(log const&) = delete; | ||
inline std::string now() { | ||
using clock = std::chrono::system_clock; | ||
auto const now = clock::to_time_t(clock::now()); | ||
struct tm tmp {}; | ||
#if _MSC_VER >= 1400 | ||
gmtime_s(&tmp, &now); | ||
#else | ||
gmtime_r(&now, &tmp); | ||
#endif | ||
|
||
log(log&&) = default; | ||
log& operator=(log&&) = default; | ||
std::stringstream ss; | ||
ss << std::put_time(&tmp, "%FT%TZ"); | ||
return ss.str(); | ||
} | ||
|
||
template <typename T> | ||
friend log&& operator<<(log&& l, T&& t) { | ||
std::clog << std::forward<T&&>(t); | ||
return std::move(l); | ||
/// Produce a new log line at the given `level`. | ||
template <log_level LogLevel, typename... Args> | ||
struct log { | ||
log(const char* ctx, fmt::format_string<Args...> fmt_str, Args&&... args, | ||
std::source_location const& loc = std::source_location::current()) | ||
: loc_{loc}, | ||
ctx_{ctx}, | ||
msg_{fmt::format(fmt_str, std::forward<Args>(args)...)} {} | ||
|
||
~log() { | ||
if (LogLevel >= log_verbosity) { | ||
#if defined(_WIN32) | ||
auto const base_file_name = strrchr(loc_.file_name(), '\\') | ||
? strrchr(loc_.file_name(), '\\') + 1 | ||
: loc_.file_name(); | ||
#else | ||
// On MacOS, due to a bug with Clang 15, the wrong filename | ||
// is retrieved (logging.h instead of the calling file): | ||
// https://github.com/llvm/llvm-project/issues/56379 | ||
auto const base_file_name = strrchr(loc_.file_name(), '/') | ||
? strrchr(loc_.file_name(), '/') + 1 | ||
: loc_.file_name(); | ||
#endif | ||
fmt::print(std::clog, "{time} [{level}] [{file}:{line}] [{ctx}] {msg}\n", | ||
fmt::arg("time", now()), fmt::arg("level", to_str(LogLevel)), | ||
fmt::arg("file", base_file_name), | ||
fmt::arg("line", loc_.line()), fmt::arg("ctx", ctx_), | ||
fmt::arg("msg", msg_)); | ||
} | ||
} | ||
|
||
~log() { std::clog << std::endl; } | ||
/// Add key-values metadata | ||
void attrs( | ||
std::initializer_list<std::pair<std::string_view, std::string_view> >&& | ||
attrs) { | ||
attrs_ = std::move(attrs); | ||
} | ||
|
||
static constexpr const char* const str[]{"emrg", "alrt", "crit", "erro", | ||
"warn", "note", "info", "debg"}; | ||
log_level level_; | ||
std::source_location loc_; | ||
char const* ctx_; | ||
std::string msg_; | ||
std::initializer_list<std::pair<std::string_view, std::string_view> > attrs_; | ||
}; | ||
|
||
enum log_level { emrg, alrt, crit, err, warn, notice, info, debug }; | ||
/// Produce a new DEBUG log line | ||
template <typename... Args> | ||
struct log_debug : public log<log_level::debug, Args...> { | ||
using log<log_level::debug, Args...>::log; | ||
}; | ||
|
||
inline std::string time(time_t const t) { | ||
char buf[sizeof "2011-10-08t07:07:09z-0430"]; | ||
struct tm result {}; | ||
gmt(&t, &result); | ||
strftime(buf, sizeof buf, "%FT%TZ%z", &result); | ||
return buf; | ||
} | ||
/// Produce a new INFO log line | ||
template <typename... Args> | ||
struct log_info : public log<log_level::info, Args...> { | ||
using log<log_level::info, Args...>::log; | ||
}; | ||
|
||
inline std::string time() { | ||
time_t now; | ||
std::time(&now); | ||
return time(now); | ||
} | ||
/// Produce a new ERROR log line | ||
template <typename... Args> | ||
struct log_error : public log<log_level::error, Args...> { | ||
using log<log_level::error, Args...>::log; | ||
}; | ||
|
||
} // namespace utl | ||
// Template deduction guides, to help the compiler distinguish between | ||
// the variadic template Args... and the next argument std::source_location | ||
// which has a default value: | ||
|
||
#endif | ||
template <typename... Args> | ||
log_debug(const char* ctx, fmt::format_string<Args...>, | ||
Args&&... args) -> log_debug<Args...>; | ||
|
||
template <typename... Args> | ||
log_info(const char* ctx, fmt::format_string<Args...>, | ||
Args&&... args) -> log_info<Args...>; | ||
|
||
template <typename... Args> | ||
log_error(const char* ctx, fmt::format_string<Args...>, | ||
Args&&... args) -> log_error<Args...>; | ||
|
||
} // namespace utl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.