ArkScript
A small, lisp-inspired, functional scripting language
Logger.hpp
Go to the documentation of this file.
1/**
2 * @file Logger.hpp
3 * @author Lexy Plateau (lexplt@gmail.com)
4 * @brief Internal logger
5 * @date 2024-08-30
6 *
7 * @copyright Copyright (c) 2024-2026
8 */
9#ifndef ARK_LOGGER_HPP
10#define ARK_LOGGER_HPP
11
12#include <iostream>
13#include <fmt/format.h>
14#include <fmt/color.h>
15#include <fmt/ostream.h>
16
17#include <string>
18#include <chrono>
19#include <source_location>
20#include <vector>
21#include <unordered_map>
22
24
25namespace Ark::internal
26{
28 {
29 public:
31 {
32 std::string_view message;
33 std::source_location location;
34
35 template <typename T>
36 // cppcheck-suppress noExplicitConstructor ; we actually want string_views to be casted automatically as MessageAndLocation
37 MessageAndLocation(T&& msg, const std::source_location loc = std::source_location::current()) :
38 message { std::forward<T>(msg) }, location { loc }
39 {}
40 };
41
42 /**
43 * @brief Construct a new Logger object
44 *
45 * @param name the pass name, used for logging
46 * @param debug_level debug level
47 */
48 Logger(std::string name, unsigned debug_level);
49
50 [[nodiscard]] inline unsigned debugLevel() const { return m_debug; }
51
52 [[nodiscard]] inline bool shouldInfo() const { return m_debug >= 1; }
53 [[nodiscard]] inline bool shouldDebug() const { return m_debug >= 2; }
54 [[nodiscard]] inline bool shouldTrace() const { return m_debug >= 3; }
55
56 /**
57 * @brief Write an info level log using fmtlib
58 * @tparam Args
59 * @param fmt format string
60 * @param args
61 */
62 template <typename... Args>
63 void info(const char* fmt, Args&&... args)
64 {
65 if (shouldInfo())
66 fmt::println(
67 "{} [{}] {}",
68 fmt::styled("INFO ", fmt::fg(fmt::color::cornflower_blue)),
69 fmt::styled(m_name, fmt::fg(m_pass_color)),
70 fmt::vformat(fmt, fmt::make_format_args(args...)));
71 }
72
73 /**
74 * @brief Write a warn level log using fmtlib
75 * @tparam Args
76 * @param fmt format string
77 * @param args
78 */
79 template <typename... Args>
80 void warn(const char* fmt, Args&&... args)
81 {
82 fmt::println(
83 m_stream == nullptr ? std::cerr : *m_stream,
84 "{}: {}",
85 fmt::styled("Warning", colorize() ? fmt::fg(fmt::color::dark_orange) : fmt::text_style()),
86 fmt::vformat(fmt, fmt::make_format_args(args...)));
87 }
88
89 /**
90 * @brief Write a debug level log using fmtlib
91 * @tparam Args
92 * @param data format string
93 * @param args
94 */
95 template <typename... Args>
96 void debug(const Logger::MessageAndLocation& data, Args&&... args)
97 {
98 if (shouldDebug())
99 fmt::println(
100 "{} [{}] {}({}:{}) {}",
101 fmt::styled("DEBUG", fmt::fg(fmt::color::pale_violet_red)),
102 fmt::styled(m_name, fmt::fg(m_pass_color)),
103 fmt::styled(data.location.file_name(), fmt::fg(fmt::color::pale_turquoise)),
104 fmt::styled(data.location.line(), fmt::fg(fmt::color::pale_turquoise)),
105 fmt::styled(data.location.column(), fmt::fg(fmt::color::pale_turquoise)),
106 fmt::vformat(data.message, fmt::make_format_args(args...)));
107 }
108
109 inline void traceStart(std::string&& trace_name)
110 {
111 m_trace_starts[trace_name] = std::chrono::high_resolution_clock::now();
112 m_active_traces.push_back(trace_name);
113 }
114
115 inline void traceEnd()
116 {
117 std::string trace_name = m_active_traces.back();
118 m_active_traces.pop_back();
119
120 const auto time = std::chrono::high_resolution_clock::now();
121 const std::chrono::duration<double, std::milli> ms_double = time - m_trace_starts[trace_name];
122 trace("{} took {:.3f}ms", trace_name, ms_double.count());
123 }
124
125 /**
126 * @brief Write a trace level log using fmtlib
127 * @tparam Args
128 * @param fmt format string
129 * @param args
130 */
131 template <typename... Args>
132 void trace(const char* fmt, Args&&... args)
133 {
134 if (shouldTrace())
135 fmt::println(
136 "{} [{}] {}",
137 fmt::styled("TRACE", fmt::fg(fmt::color::golden_rod)),
138 fmt::styled(m_name, fmt::fg(m_pass_color)),
139 fmt::vformat(fmt, fmt::make_format_args(args...)));
140 }
141
142 /**
143 * @brief Set a custom output stream to use for warnings. This will disable colors.
144 *
145 * @param os output stream
146 */
147 void configureOutputStream(std::ostream* os)
148 {
149 m_stream = os;
150 }
151
152 /**
153 * @brief Check if logs can be colorized
154 *
155 * @return true if logs can be colorized
156 */
157 inline bool colorize() const noexcept
158 {
159 return m_stream == nullptr;
160 }
161
162 private:
163 unsigned m_debug;
164 std::string m_name;
165 fmt::color m_pass_color;
166 std::unordered_map<std::string, std::chrono::time_point<std::chrono::high_resolution_clock>> m_trace_starts;
167 std::vector<std::string> m_active_traces;
168 std::ostream* m_stream;
169 };
170}
171
172#endif // ARK_LOGGER_HPP
#define ARK_API
Definition Module.hpp:22
ArkScript configuration macros.
void debug(const Logger::MessageAndLocation &data, Args &&... args)
Write a debug level log using fmtlib.
Definition Logger.hpp:96
bool shouldTrace() const
Definition Logger.hpp:54
bool colorize() const noexcept
Check if logs can be colorized.
Definition Logger.hpp:157
std::unordered_map< std::string, std::chrono::time_point< std::chrono::high_resolution_clock > > m_trace_starts
Definition Logger.hpp:166
void info(const char *fmt, Args &&... args)
Write an info level log using fmtlib.
Definition Logger.hpp:63
void trace(const char *fmt, Args &&... args)
Write a trace level log using fmtlib.
Definition Logger.hpp:132
bool shouldDebug() const
Definition Logger.hpp:53
std::string m_name
Definition Logger.hpp:164
void configureOutputStream(std::ostream *os)
Set a custom output stream to use for warnings. This will disable colors.
Definition Logger.hpp:147
std::ostream * m_stream
Definition Logger.hpp:168
void warn(const char *fmt, Args &&... args)
Write a warn level log using fmtlib.
Definition Logger.hpp:80
bool shouldInfo() const
Definition Logger.hpp:52
std::vector< std::string > m_active_traces
Definition Logger.hpp:167
void traceStart(std::string &&trace_name)
Definition Logger.hpp:109
unsigned debugLevel() const
Definition Logger.hpp:50
fmt::color m_pass_color
Definition Logger.hpp:165
STL namespace.
MessageAndLocation(T &&msg, const std::source_location loc=std::source_location::current())
Definition Logger.hpp:37