Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
log.cpp
Go to the documentation of this file.
1// log.cpp — Logger の本体と、名前の表・1 行への整形。
2//
3// 出力先(コンソール・デバッガ・ファイル)の実装は log_sinks.cpp。ここは Windows を知らない。
4#include "core/log.h"
5
6#include <array>
7#include <iterator>
8
9#include "core/aliases.h"
10#include "core/log_sinks.h"
11
12namespace bicameral {
13 namespace {
14
15 constexpr std::array<std::string_view, static_cast<size_t>(Channel::Count)> CHANNEL_NAMES = {
16 "core", "platform", "gpu", "workgraph", "sim", "reaction", "physics", "render", "audio", "tool",
17 };
18
19 constexpr std::array<std::string_view, 6> LEVEL_NAMES = {
20 "trace", "debug", "info", "warning", "error", "fatal",
21 };
22
23 constexpr std::string_view LEVEL_LETTERS = "TDIWEF";
24
25#ifdef NDEBUG
27#else
29#endif
30
31 } // namespace
32
33 // --- 名前 ---
34
35 std::string_view ChannelName(Channel channel) {
36 const auto index = static_cast<size_t>(channel);
37 if (index >= CHANNEL_NAMES.size())
38 return "?";
39
40 return CHANNEL_NAMES[index];
41 }
42
43 std::string_view LevelName(Level level) {
44 const auto index = static_cast<size_t>(level);
45 if (index >= LEVEL_NAMES.size())
46 return "?";
47
48 return LEVEL_NAMES[index];
49 }
50
51 char LevelLetter(Level level) {
52 const auto index = static_cast<size_t>(level);
53 if (index >= LEVEL_LETTERS.size())
54 return '?';
55
56 return LEVEL_LETTERS[index];
57 }
58
59 bool ParseLevel(std::string_view text, Level& level) {
60 for (size_t i = 0; i < LEVEL_NAMES.size(); ++i) {
61 if (LEVEL_NAMES[i] != text)
62 continue;
63
64 level = static_cast<Level>(i);
65
66 return true;
67 }
68
69 return false;
70 }
71
72 // --- 整形 ---
73
74 std::string_view FileNameOnly(std::string_view path) {
75 const size_t slash = path.find_last_of("/\\");
76 return slash == std::string_view::npos ? path : path.substr(slash + 1);
77 }
78
79 std::string FormatLogLine(const LogRecord& record, bool withLocation) {
80 // チャンネル名の幅は最長の "workgraph" に合わせる(縦にそろうと目で追いやすい)
81 std::string line = std::format("[{:9.3f}] {} {:<9} | {}", record.elapsedSeconds, LevelLetter(record.level),
82 ChannelName(record.channel), record.message);
83
84 if (withLocation) {
85 std::format_to(std::back_inserter(line), " ({}:{})", FileNameOnly(record.location.file_name()),
86 record.location.line());
87 }
88
89 return line;
90 }
91
92 // --- Logger ---
93
94 Logger::Logger() : m_minLevel(DEFAULT_MIN_LEVEL), m_startTime(chr::steady_clock::now()) {
97 }
98
100 Flush();
101 }
102
103 void Logger::AddSink(std::unique_ptr<LogSink> sink) {
104 if (sink == nullptr)
105 return;
106
107 std::scoped_lock lock(m_mutex);
108 m_sinks.push_back(std::move(sink));
109 }
110
112 std::scoped_lock lock(m_mutex);
113 m_sinks.clear();
114 }
115
116 void Logger::Write(Channel channel, Level level, std::string_view message, const std::source_location& location) {
117 const chr::duration<double> elapsed = chr::steady_clock::now() - m_startTime;
118 const LogRecord record{
119 .channel = channel,
120 .level = level,
121 .message = message,
122 .location = location,
123 .elapsedSeconds = elapsed.count(),
124 };
125
126 std::scoped_lock lock(m_mutex);
127 for (const auto& sink : m_sinks)
128 sink->Write(record);
129
130 // 警告以上は、直後に落ちても残るようにすぐ書き出す
131 if (level < Level::Warning)
132 return;
133
134 for (const auto& sink : m_sinks)
135 sink->Flush();
136 }
137
139 std::scoped_lock lock(m_mutex);
140 for (const auto& sink : m_sinks)
141 sink->Flush();
142 }
143
144} // namespace bicameral
void AddSink(std::unique_ptr< LogSink > sink)
Definition log.cpp:103
void Write(Channel channel, Level level, std::string_view message, const std::source_location &location)
Definition log.cpp:116
void ClearSinks()
Definition log.cpp:111
chr::steady_clock::time_point m_startTime
Definition log.h:117
std::atomic< Level > m_minLevel
Definition log.h:116
std::vector< std::unique_ptr< LogSink > > m_sinks
Definition log.h:115
std::mutex m_mutex
Definition log.h:114
constexpr std::array< std::string_view, 6 > LEVEL_NAMES
Definition log.cpp:19
constexpr std::string_view LEVEL_LETTERS
Definition log.cpp:23
constexpr std::array< std::string_view, static_cast< size_t >(Channel::Count)> CHANNEL_NAMES
Definition log.cpp:15
char LevelLetter(Level level)
Definition log.cpp:51
std::string_view ChannelName(Channel channel)
Definition log.cpp:35
Channel
Definition log.h:38
std::string_view FileNameOnly(std::string_view path)
Definition log.cpp:74
std::string FormatLogLine(const LogRecord &record, bool withLocation)
Definition log.cpp:79
std::string_view LevelName(Level level)
Definition log.cpp:43
Level
Definition log.h:53
std::unique_ptr< LogSink > CreateConsoleSink()
std::unique_ptr< LogSink > CreateDebuggerSink()
bool ParseLevel(std::string_view text, Level &level)
Definition log.cpp:59
std::string_view message
Definition log.h:73
double elapsedSeconds
Definition log.h:75
std::source_location location
Definition log.h:74
Channel channel
Definition log.h:71