Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common/log.h
4211 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
6
#include "log_channels.h"
7
#include "types.h"
8
9
#include "fmt/base.h"
10
11
#include <array>
12
#include <cinttypes>
13
#include <cstdarg>
14
#include <mutex>
15
#include <string_view>
16
17
namespace Log {
18
enum class Level : u32
19
{
20
None, // Silences all log traffic
21
Error,
22
Warning,
23
Info,
24
Verbose,
25
Dev,
26
Debug,
27
Trace,
28
29
MaxCount
30
};
31
32
enum class Color : u32
33
{
34
Default,
35
Black,
36
Red,
37
Green,
38
Blue,
39
Magenta,
40
Orange,
41
Cyan,
42
Yellow,
43
White,
44
StrongBlack,
45
StrongRed,
46
StrongGreen,
47
StrongBlue,
48
StrongMagenta,
49
StrongOrange,
50
StrongCyan,
51
StrongYellow,
52
StrongWhite,
53
54
MaxCount
55
};
56
57
enum class Channel : u32
58
{
59
#define LOG_CHANNEL_ENUM(X) X,
60
ENUMERATE_LOG_CHANNELS(LOG_CHANNEL_ENUM)
61
#undef LOG_CHANNEL_ENUM
62
63
MaxCount
64
};
65
66
// Packs a level and channel into one 16-bit number.
67
using MessageCategory = u32;
68
[[maybe_unused]] ALWAYS_INLINE constexpr u32 PackCategory(Channel channel, Level level, Color colour)
69
{
70
return ((static_cast<MessageCategory>(colour) << 10) | (static_cast<MessageCategory>(channel) << 3) |
71
static_cast<MessageCategory>(level));
72
}
73
[[maybe_unused]] ALWAYS_INLINE constexpr Color UnpackColor(MessageCategory cat)
74
{
75
return static_cast<Color>((cat >> 10) & 0x1f);
76
}
77
[[maybe_unused]] ALWAYS_INLINE constexpr Channel UnpackChannel(MessageCategory cat)
78
{
79
return static_cast<Channel>((cat >> 3) & 0x7f);
80
}
81
[[maybe_unused]] ALWAYS_INLINE constexpr Level UnpackLevel(MessageCategory cat)
82
{
83
return static_cast<Level>(cat & 0x7);
84
}
85
86
// log message callback type
87
using CallbackFunctionType = void (*)(void* pUserParam, MessageCategory category, const char* functionName,
88
std::string_view message);
89
90
// registers a log callback
91
void RegisterCallback(CallbackFunctionType callbackFunction, void* pUserParam);
92
93
// unregisters a log callback
94
void UnregisterCallback(CallbackFunctionType callbackFunction, void* pUserParam);
95
96
// returns a list of all log channels
97
const std::array<const char*, static_cast<size_t>(Channel::MaxCount)>& GetChannelNames();
98
99
// returns the time in seconds since the start of the process
100
float GetCurrentMessageTime();
101
bool AreConsoleOutputTimestampsEnabled();
102
103
// adds a standard console output
104
bool IsConsoleOutputCurrentlyAvailable();
105
bool IsConsoleOutputEnabled();
106
void SetConsoleOutputParams(bool enabled, bool timestamps = true);
107
108
// adds a debug console output [win32/android only]
109
bool IsDebugOutputEnabled();
110
void SetDebugOutputParams(bool enabled);
111
112
// adds a file output
113
void SetFileOutputParams(bool enabled, const char* filename, bool timestamps = true);
114
115
// Returns the current global filtering level.
116
Level GetLogLevel();
117
118
// Returns true if log messages for the specified log level/filter would not be filtered (and visible).
119
bool IsLogVisible(Level level, Channel channel);
120
121
// Sets global filtering level, messages below this level won't be sent to any of the logging sinks.
122
void SetLogLevel(Level level);
123
124
// Sets global filter, any messages from these channels won't be sent to any of the logging sinks.
125
void SetLogChannelEnabled(Channel channel, bool enabled);
126
127
// Returns the name of the specified log channel.
128
const char* GetChannelName(Channel channel);
129
130
// Returns the default colour for a log level.
131
Color GetColorForLevel(Level level);
132
133
// writes a message to the log
134
void Write(MessageCategory cat, std::string_view message);
135
void Write(MessageCategory cat, const char* functionName, std::string_view message);
136
void WriteFmtArgs(MessageCategory cat, fmt::string_view fmt, fmt::format_args args);
137
void WriteFmtArgs(MessageCategory cat, const char* functionName, fmt::string_view fmt, fmt::format_args args);
138
139
ALWAYS_INLINE void FastWrite(Channel channel, Level level, std::string_view message)
140
{
141
if (level <= GetLogLevel()) [[unlikely]]
142
Write(PackCategory(channel, level, Color::Default), message);
143
}
144
ALWAYS_INLINE void FastWrite(Channel channel, const char* functionName, Level level, std::string_view message)
145
{
146
if (level <= GetLogLevel()) [[unlikely]]
147
Write(PackCategory(channel, level, Color::Default), functionName, message);
148
}
149
template<typename... T>
150
ALWAYS_INLINE void FastWrite(Channel channel, Level level, fmt::format_string<T...> fmt, T&&... args)
151
{
152
if (level <= GetLogLevel()) [[unlikely]]
153
WriteFmtArgs(PackCategory(channel, level, Color::Default), fmt, fmt::make_format_args(args...));
154
}
155
template<typename... T>
156
ALWAYS_INLINE void FastWrite(Channel channel, const char* functionName, Level level, fmt::format_string<T...> fmt,
157
T&&... args)
158
{
159
if (level <= GetLogLevel()) [[unlikely]]
160
WriteFmtArgs(PackCategory(channel, level, Color::Default), functionName, fmt, fmt::make_format_args(args...));
161
}
162
ALWAYS_INLINE void FastWrite(Channel channel, Level level, Color colour, std::string_view message)
163
{
164
if (level <= GetLogLevel()) [[unlikely]]
165
Write(PackCategory(channel, level, colour), message);
166
}
167
ALWAYS_INLINE void FastWrite(Channel channel, const char* functionName, Level level, Color colour,
168
std::string_view message)
169
{
170
if (level <= GetLogLevel()) [[unlikely]]
171
Write(PackCategory(channel, level, colour), functionName, message);
172
}
173
template<typename... T>
174
ALWAYS_INLINE void FastWrite(Channel channel, Level level, Color colour, fmt::format_string<T...> fmt, T&&... args)
175
{
176
if (level <= GetLogLevel()) [[unlikely]]
177
WriteFmtArgs(PackCategory(channel, level, colour), fmt, fmt::make_format_args(args...));
178
}
179
template<typename... T>
180
ALWAYS_INLINE void FastWrite(Channel channel, const char* functionName, Level level, Color colour,
181
fmt::format_string<T...> fmt, T&&... args)
182
{
183
if (level <= GetLogLevel()) [[unlikely]]
184
WriteFmtArgs(PackCategory(channel, level, colour), functionName, fmt, fmt::make_format_args(args...));
185
}
186
} // namespace Log
187
188
// log wrappers
189
#define LOG_CHANNEL(name) [[maybe_unused]] static constexpr Log::Channel ___LogChannel___ = Log::Channel::name;
190
191
#define ERROR_LOG(...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Error, __VA_ARGS__)
192
#define WARNING_LOG(...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Warning, __VA_ARGS__)
193
#define INFO_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Info, __VA_ARGS__)
194
#define VERBOSE_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Verbose, __VA_ARGS__)
195
#define DEV_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Dev, __VA_ARGS__)
196
197
#if defined(_DEBUG) || defined(_DEVEL)
198
#define DEBUG_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Debug, __VA_ARGS__)
199
#define TRACE_LOG(...) Log::FastWrite(___LogChannel___, Log::Level::Trace, __VA_ARGS__)
200
#else
201
#define DEBUG_LOG(...) \
202
do \
203
{ \
204
} while (0)
205
#define TRACE_LOG(...) \
206
do \
207
{ \
208
} while (0)
209
#endif
210
211
// clang-format off
212
#define ERROR_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Error, Log::Color::colour, __VA_ARGS__)
213
#define WARNING_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, __func__, Log::Level::Warning, Log::Color::colour, __VA_ARGS__)
214
#define INFO_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Info, Log::Color::colour, __VA_ARGS__)
215
#define VERBOSE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Verbose, Log::Color::colour, __VA_ARGS__)
216
#define DEV_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Dev, Log::Color::colour, __VA_ARGS__)
217
218
#if defined(_DEBUG) || defined(_DEVEL)
219
#define DEBUG_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Debug, Log::Color::colour, __VA_ARGS__)
220
#define TRACE_COLOR_LOG(colour, ...) Log::FastWrite(___LogChannel___, Log::Level::Trace, Log::Color::colour,__VA_ARGS__)
221
#else
222
#define DEBUG_COLOR_LOG(colour, ...) \
223
do \
224
{ \
225
} while (0)
226
#define TRACE_COLOR_LOG(colour, ...) \
227
do \
228
{ \
229
} while (0)
230
#endif
231
232
// clang-format on
233
234