11#pragma once
22
3+ #include < chrono>
34#include < fstream>
45#include < iostream>
56#include < regex>
3031#define LOG_DEBUG (...) LOG_WITH_LEVEL(debug, __VA_ARGS__)
3132#define LOG_TRACE (...) LOG_WITH_LEVEL(trace, __VA_ARGS__)
3233
34+ #define LOG_WITH_LEVEL (LEVEL, ...) LOG_WITH_LEVEL_AND_TIME(LEVEL, ::binlog::clockNow(), __VA_ARGS__)
3335// only do the actual logging if the picked up `Logger` instance is configured to handle the
3436// provided log level. `LEVEL` must be a compile-time constant. `logger()` is evaluated once
35- #define LOG_WITH_LEVEL (LEVEL, ...) \
36- do { \
37- constexpr auto _level = ::codeql::Log::Level::LEVEL; \
38- ::codeql::Logger& _logger = logger (); \
39- if (_level >= _logger.level ()) { \
40- BINLOG_CREATE_SOURCE_AND_EVENT (_logger.writer (), _level, /* category*/ , ::binlog::clockNow (), \
41- __VA_ARGS__); \
42- } \
43- if (_level >= ::codeql::Log::Level::error) { \
44- ::codeql::Log::flush (); \
45- } \
37+ #define LOG_WITH_LEVEL_AND_TIME (LEVEL, TIME, ...) \
38+ do { \
39+ constexpr auto _level = ::codeql::Log::Level::LEVEL; \
40+ ::codeql::Logger& _logger = logger (); \
41+ if (_level >= _logger.level ()) { \
42+ BINLOG_CREATE_SOURCE_AND_EVENT (_logger.writer (), _level, /* category*/ , TIME, __VA_ARGS__); \
43+ } \
44+ if (_level >= ::codeql::Log::Level::error) { \
45+ ::codeql::Log::flush (); \
46+ } \
4647 } while (false )
4748
4849// Emit errors with a specified SwiftDiagnostic object. These will be both logged and outputted as
49- // JSON DB diagnostics
50- #define DIAGNOSE_CRITICAL (ID, ...) DIAGNOSE_WITH_LEVEL(critical, ID, __VA_ARGS__)
50+ // JSON DB diagnostics. The format must be appliable to the following arguments both as binlog and
51+ // as fmt::format formatting.
52+ // Beware that contrary to LOG_* macros, arguments right of the format will be evaluated twice. ID
53+ // is evaluated once though.
5154#define DIAGNOSE_ERROR (ID, ...) DIAGNOSE_WITH_LEVEL(error, ID, __VA_ARGS__)
55+ #define DIAGNOSE_CRITICAL (ID, ...) DIAGNOSE_WITH_LEVEL(critical, ID, __VA_ARGS__)
5256
5357#define CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX " [{}] "
5458// TODO(C++20) replace non-standard , ##__VA_ARGS__ with __VA_OPT__(,) __VA_ARGS__
55- #define DIAGNOSE_WITH_LEVEL (LEVEL, ID, FORMAT, ...) \
56- LOG_WITH_LEVEL (LEVEL, CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX FORMAT, \
57- ::codeql::detail::SwiftDiagnosticLogWrapper{ID}, ##__VA_ARGS__);
59+ #define DIAGNOSE_WITH_LEVEL (LEVEL, ID, FORMAT, ...) \
60+ do { \
61+ auto _now = ::binlog::clockNow (); \
62+ const ::codeql::SwiftDiagnostic& _id = ID; \
63+ ::codeql::Log::diagnose (_id, std::chrono::nanoseconds{_now}, \
64+ fmt::format (FORMAT, ##__VA_ARGS__)); \
65+ LOG_WITH_LEVEL_AND_TIME (LEVEL, _now, CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX FORMAT, \
66+ ::codeql::detail::SwiftDiagnosticLogWrapper{_id}, ##__VA_ARGS__); \
67+ } while (false )
5868
5969// avoid calling into binlog's original macros
6070#undef BINLOG_CRITICAL
@@ -124,9 +134,9 @@ class Log {
124134 }
125135
126136 static void diagnose (const SwiftDiagnostic& source,
127- const std::chrono::system_clock::time_point& time ,
137+ const std::chrono::nanoseconds& elapsed ,
128138 std::string_view message) {
129- instance ().diagnoseImpl (source, time , message);
139+ instance ().diagnoseImpl (source, elapsed , message);
130140 }
131141
132142 private:
@@ -145,7 +155,7 @@ class Log {
145155 void configure ();
146156 void flushImpl ();
147157 void diagnoseImpl (const SwiftDiagnostic& source,
148- const std::chrono::system_clock::time_point& time ,
158+ const std::chrono::nanoseconds& elapsed ,
149159 std::string_view message);
150160
151161 LoggerConfiguration getLoggerConfigurationImpl (std::string_view name);
@@ -230,26 +240,6 @@ struct SwiftDiagnosticLogWrapper {
230240} // namespace detail
231241} // namespace codeql
232242
233- // we intercept this binlog plumbing function providing better overload resolution matches in
234- // case the first non-format argument is a diagnostic source, and emit it in that case with the
235- // same timestamp
236- namespace binlog ::detail {
237- template <typename Writer, size_t N, typename ... T>
238- void addEventIgnoreFirst (Writer& writer,
239- std::uint64_t eventSourceId,
240- std::uint64_t clock,
241- const char (&format)[N],
242- codeql::detail::SwiftDiagnosticLogWrapper&& source,
243- T&&... t) {
244- std::chrono::system_clock::time_point point{
245- std::chrono::duration_cast<std::chrono::system_clock::duration>(
246- std::chrono::nanoseconds{clock})};
247- constexpr std::string_view prefix = CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX;
248- ::codeql::Log::diagnose (source.value, point, fmt::format(format + prefix.size(), t...));
249- writer.addEvent (eventSourceId, clock, source, std::forward<T>(t)...);
250- }
251- } // namespace binlog::detail
252-
253243namespace mserialize {
254244// log diagnostics wrapper using the abbreviation of the underlying diagnostic, using
255245// binlog/mserialize internal plumbing
0 commit comments