ArkScript
A small, lisp-inspired, functional scripting language
Logger.hpp
Go to the documentation of this file.
1/**
2 * @file Logger.hpp
3 * @author Alexandre Plateau (lexplt@gmail.com)
4 * @brief Internal logger
5 * @date 2024-08-30
6 *
7 * @copyright Copyright (c) 2024-2025)
8 */
9#ifndef ARK_LOGGER_HPP
10#define ARK_LOGGER_HPP
11
12#include <iostream>
13#include <fmt/format.h>
14
15#include <string>
16#include <chrono>
17#include <source_location>
18#include <vector>
19#include <unordered_map>
20#include <fmt/color.h>
21
22namespace Ark::internal
23{
24 class Logger
25 {
26 public:
28 {
29 std::string_view message;
30 std::source_location location;
31
32 template <typename T>
33 // cppcheck-suppress noExplicitConstructor ; we actually want string_views to be casted automatically as MessageAndLocation
34 MessageAndLocation(T&& msg, const std::source_location loc = std::source_location::current()) :
35 message { std::forward<T>(msg) }, location { loc }
36 {}
37 };
38
39 /**
40 * @brief Construct a new Logger object
41 *
42 * @param name the pass name, used for logging
43 * @param debug_level debug level
44 */
45 Logger(std::string name, unsigned debug_level);
46
47 [[nodiscard]] inline unsigned debugLevel() const { return m_debug; }
48
49 [[nodiscard]] inline bool shouldInfo() const { return m_debug >= 1; }
50 [[nodiscard]] inline bool shouldDebug() const { return m_debug >= 2; }
51 [[nodiscard]] inline bool shouldTrace() const { return m_debug >= 3; }
52
53 /**
54 * @brief Write an info level log using fmtlib
55 * @tparam Args
56 * @param fmt format string
57 * @param args
58 */
59 template <typename... Args>
60 void info(const char* fmt, Args&&... args)
61 {
62 if (shouldInfo())
63 fmt::println(
64 "{} [{}] {}",
65 fmt::styled("INFO ", fmt::fg(fmt::color::cornflower_blue)),
66 fmt::styled(m_name, fmt::fg(m_pass_color)),
67 fmt::vformat(fmt, fmt::make_format_args(args...)));
68 }
69
70 /**
71 * @brief Write a debug level log using fmtlib
72 * @tparam Args
73 * @param data format string
74 * @param args
75 */
76 template <typename... Args>
77 void debug(const Logger::MessageAndLocation data, Args&&... args)
78 {
79 if (shouldDebug())
80 fmt::println(
81 "{} [{}] {}({}:{}) {}",
82 fmt::styled("DEBUG", fmt::fg(fmt::color::pale_violet_red)),
83 fmt::styled(m_name, fmt::fg(m_pass_color)),
84 fmt::styled(data.location.file_name(), fmt::fg(fmt::color::pale_turquoise)),
85 fmt::styled(data.location.line(), fmt::fg(fmt::color::pale_turquoise)),
86 fmt::styled(data.location.column(), fmt::fg(fmt::color::pale_turquoise)),
87 fmt::vformat(data.message, fmt::make_format_args(args...)));
88 }
89
90 inline void traceStart(std::string&& trace_name)
91 {
92 m_trace_starts[trace_name] = std::chrono::high_resolution_clock::now();
93 m_active_traces.push_back(trace_name);
94 }
95
96 inline void traceEnd()
97 {
98 std::string trace_name = m_active_traces.back();
99 m_active_traces.pop_back();
100
101 const auto time = std::chrono::high_resolution_clock::now();
102 const std::chrono::duration<double, std::milli> ms_double = time - m_trace_starts[trace_name];
103 trace("{} took {:.3f}ms", trace_name, ms_double.count());
104 }
105
106 /**
107 * @brief Write a trace level log using fmtlib
108 * @tparam Args
109 * @param fmt format string
110 * @param args
111 */
112 template <typename... Args>
113 void trace(const char* fmt, Args&&... args)
114 {
115 if (shouldTrace())
116 fmt::println(
117 "{} [{}] {}",
118 fmt::styled("TRACE", fmt::fg(fmt::color::golden_rod)),
119 fmt::styled(m_name, fmt::fg(m_pass_color)),
120 fmt::vformat(fmt, fmt::make_format_args(args...)));
121 }
122
123 private:
124 unsigned m_debug;
125 std::string m_name;
126 fmt::color m_pass_color;
127 std::unordered_map<std::string, std::chrono::time_point<std::chrono::high_resolution_clock>> m_trace_starts;
128 std::vector<std::string> m_active_traces;
129 };
130}
131
132#endif // ARK_LOGGER_HPP
bool shouldTrace() const
Definition Logger.hpp:51
std::unordered_map< std::string, std::chrono::time_point< std::chrono::high_resolution_clock > > m_trace_starts
Definition Logger.hpp:127
void info(const char *fmt, Args &&... args)
Write an info level log using fmtlib.
Definition Logger.hpp:60
void trace(const char *fmt, Args &&... args)
Write a trace level log using fmtlib.
Definition Logger.hpp:113
void debug(const Logger::MessageAndLocation data, Args &&... args)
Write a debug level log using fmtlib.
Definition Logger.hpp:77
Logger(std::string name, unsigned debug_level)
Construct a new Logger object.
Definition Logger.cpp:29
bool shouldDebug() const
Definition Logger.hpp:50
std::string m_name
Definition Logger.hpp:125
bool shouldInfo() const
Definition Logger.hpp:49
std::vector< std::string > m_active_traces
Definition Logger.hpp:128
void traceStart(std::string &&trace_name)
Definition Logger.hpp:90
unsigned debugLevel() const
Definition Logger.hpp:47
fmt::color m_pass_color
Definition Logger.hpp:126
MessageAndLocation(T &&msg, const std::source_location loc=std::source_location::current())
Definition Logger.hpp:34