Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
log.h
Go to the documentation of this file.
1// log.h — サブシステム名つき・重大度つきのログ(T-0007)。
2//
3// 使い方:
4// Log(Channel::Platform, Level::Info, "Adapter {}: {}", index, name);
5// → [ 0.004] I platform | Adapter 0: NVIDIA GeForce RTX 3070 Ti
6// 書式は std::format(書式の誤りはコンパイル時に分かる)。呼んだ場所(ファイル:行)は自動で付く。
7//
8// データの流れ: Log() → Singleton<Logger>(core/singleton.h)→ 登録された LogSink すべて
9// 既定のシンクはコンソールと OutputDebugString(VS の出力ウィンドウ)。ファイルは OpenLogFile()(core/log_sinks.h)で足す。
10// 依存の向き: 各サブシステム → log の一方向だけ。log は他のサブシステムを知らない(Channel は名前の一覧にすぎない)。
11// 生存期間: 最初の Log() で作られ、main の最後の SingletonFinalizer::Finalize() で最後に壊れる
12// (ADR-0006。ログを使う物より後に作られることはないので、作った順の逆の破棄で最後になる)。
13// HRESULT の失敗は core/hresult.h の BICAMERAL_CHECK_HR を使う。
14#pragma once
15
16#include <atomic>
17#include <chrono>
18#include <concepts>
19#include <cstdint>
20#include <format>
21#include <memory>
22#include <mutex>
23#include <source_location>
24#include <string>
25#include <string_view>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
30#include "core/aliases.h"
31#include "core/singleton.h"
32
33namespace bicameral {
34
35 // --- 種類 ---
36
37 // どのサブシステムが出したか。足すときは log.cpp の CHANNEL_NAMES にも名前を足す
38 enum class Channel : uint8_t {
40 Platform, // 窓・入力・OS・アダプタの列挙
41 Gpu, // デバイス・キュー・リソース・同期
42 WorkGraph, // Work Graphs の構築と投入
43 Sim, // 刻みのループ・コマンド・GPU からのイベント(06)
44 Reaction, // 反応の連鎖
45 Physics, // AVBD
46 Render, // 描画
48 Tool, // エディタ・ベイク
50 };
51
52 // 重大度。Warning 以上はすぐにファイルへ書き出し(Flush)、呼んだ場所も表示する
53 enum class Level : uint8_t {
59 Fatal, // この後すぐ終了する。ログは Flush 済みになる(止めるのは呼んだ側)
60 };
61
62 [[nodiscard]] std::string_view ChannelName(Channel channel); // "platform"
63 [[nodiscard]] std::string_view LevelName(Level level); // "warning"
64 [[nodiscard]] char LevelLetter(Level level); // 'W'
65
66 // 文字列からの変換(コマンドラインの --log-level 用)。知らない名前なら false
67 [[nodiscard]] bool ParseLevel(std::string_view text, Level& level);
68
69 // 1 件のログ。シンクに渡す間だけ有効(message は呼び出し側の文字列を指す)
70 struct LogRecord {
73 std::string_view message;
74 std::source_location location;
75 double elapsedSeconds; // Logger を作ってからの経過時間
76 };
77
78 // 1 行に整形する: "[ 0.004] I platform | message"。withLocation なら末尾に " (caps.cpp:88)"
79 [[nodiscard]] std::string FormatLogLine(const LogRecord& record, bool withLocation);
80
81 // ファイル名だけを取り出す(source_location はフルパスを返すため)
82 [[nodiscard]] std::string_view FileNameOnly(std::string_view path);
83
84 // --- 出力先 ---
85
86 class LogSink {
87 public:
88 virtual ~LogSink() = default;
89 virtual void Write(const LogRecord& record) = 0;
90 virtual void Flush() {}
91 };
92
93 // --- 本体 ---
94
95 class Logger {
96 public:
97 Logger(); // 既定のシンク(コンソール・デバッガ)を登録する
98 ~Logger();
99 Logger(const Logger&) = delete;
100 Logger& operator=(const Logger&) = delete;
101
102 void AddSink(std::unique_ptr<LogSink> sink);
103 void ClearSinks(); // テスト用。既定のシンクも外れる
104
105 void SetMinLevel(Level level) { m_minLevel.store(level, std::memory_order_relaxed); }
106 [[nodiscard]] Level MinLevel() const { return m_minLevel.load(std::memory_order_relaxed); }
107 [[nodiscard]] bool IsEnabled(Level level) const { return level >= MinLevel(); }
108
109 // 整形済みの 1 件を全シンクへ。複数スレッドから呼んでよい(行が混ざらない)
110 void Write(Channel channel, Level level, std::string_view message, const std::source_location& location);
111 void Flush();
112
113 private:
114 std::mutex m_mutex;
115 std::vector<std::unique_ptr<LogSink>> m_sinks;
116 std::atomic<Level> m_minLevel;
117 chr::steady_clock::time_point m_startTime;
118 };
119
120 [[nodiscard]] inline Logger& GetLogger() {
122 }
123
124 // --- 呼ぶ側 ---
125
126 // 書式文字列と呼んだ場所をいっしょに受け取るための型。
127 // 可変長引数の後ろに source_location の既定引数を置けないので、書式文字列の側に持たせる
128 template <typename... Args>
130 std::format_string<Args...> text;
131 std::source_location location;
132
133 template <typename Text>
134 requires std::convertible_to<const Text&, std::string_view>
135 consteval FormatWithLocation(const Text& pattern, std::source_location where = std::source_location::current())
136 : text(pattern), location(where) {}
137 };
138
139 template <typename... Args>
140 void Log(Channel channel, Level level, FormatWithLocation<std::type_identity_t<Args>...> pattern, Args&&... args) {
141 Logger& logger = GetLogger();
142 // 捨てるログは整形もしない
143 if (!logger.IsEnabled(level))
144 return;
145
146 logger.Write(channel, level, std::format(pattern.text, std::forward<Args>(args)...), pattern.location);
147 }
148
149} // namespace bicameral
virtual void Write(const LogRecord &record)=0
virtual ~LogSink()=default
virtual void Flush()
Definition log.h:90
bool IsEnabled(Level level) const
Definition log.h:107
void AddSink(std::unique_ptr< LogSink > sink)
Definition log.cpp:103
void SetMinLevel(Level level)
Definition log.h:105
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
Level MinLevel() const
Definition log.h:106
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
Logger(const Logger &)=delete
Logger & operator=(const Logger &)=delete
std::mutex m_mutex
Definition log.h:114
static T & GetInstance()
Definition singleton.h:53
char LevelLetter(Level level)
Definition log.cpp:51
Logger & GetLogger()
Definition log.h:120
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
void Log(Channel channel, Level level, FormatWithLocation< std::type_identity_t< Args >... > pattern, Args &&... args)
Definition log.h:140
std::string_view LevelName(Level level)
Definition log.cpp:43
Level
Definition log.h:53
bool ParseLevel(std::string_view text, Level &level)
Definition log.cpp:59
consteval FormatWithLocation(const Text &pattern, std::source_location where=std::source_location::current())
Definition log.h:135
std::source_location location
Definition log.h:131
std::format_string< Args... > text
Definition log.h:130
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