3535#define LOG_DEBUG (...) LOG_WITH_LEVEL(debug, __VA_ARGS__)
3636#define LOG_TRACE (...) LOG_WITH_LEVEL(trace, __VA_ARGS__)
3737
38- #define CODEQL_GET_SECOND (...) CODEQL_GET_SECOND_I(__VA_ARGS__, 0 , 0 )
39- #define CODEQL_GET_SECOND_I (X, Y, ...) Y
40-
4138// only do the actual logging if the picked up `Logger` instance is configured to handle the
4239// provided log level. `LEVEL` must be a compile-time constant. `logger()` is evaluated once
43- // TODO(C++20) replace non-standard ##__VA_ARGS__ with __VA_OPT__(,) __VA_ARGS__
44- #define LOG_WITH_LEVEL_AND_CATEGORY (LEVEL, CATEGORY, ...) \
45- do { \
46- static_assert (::codeql::detail::checkLogArgs<decltype (CODEQL_GET_SECOND (__VA_ARGS__))>( \
47- MSERIALIZE_FIRST (__VA_ARGS__)), \
48- " diagnostics logs must have format starting with \" [{}]\" " ); \
49- constexpr auto _level = ::codeql::Log::Level::LEVEL; \
50- ::codeql::Logger& _logger = logger (); \
51- if (_level >= _logger.level ()) { \
52- BINLOG_CREATE_SOURCE_AND_EVENT (_logger.writer (), _level, CATEGORY, ::binlog::clockNow (), \
53- __VA_ARGS__); \
54- } \
55- if (_level >= ::codeql::Log::Level::error) { \
56- ::codeql::Log::flush (); \
57- } \
40+ #define LOG_WITH_LEVEL (LEVEL, ...) \
41+ do { \
42+ constexpr auto _level = ::codeql::Log::Level::LEVEL; \
43+ ::codeql::Logger& _logger = logger (); \
44+ if (_level >= _logger.level ()) { \
45+ BINLOG_CREATE_SOURCE_AND_EVENT (_logger.writer (), _level, /* category*/ , ::binlog::clockNow (), \
46+ __VA_ARGS__); \
47+ } \
48+ if (_level >= ::codeql::Log::Level::error) { \
49+ ::codeql::Log::flush (); \
50+ } \
5851 } while (false )
5952
60- #define LOG_WITH_LEVEL (LEVEL, ...) LOG_WITH_LEVEL_AND_CATEGORY(LEVEL, , __VA_ARGS__)
53+ // Emit errors with a specified SwiftDiagnostic object. These will be both logged and outputted as
54+ // JSON DB diagnostics
55+ #define DIAGNOSE_CRITICAL (ID, ...) DIAGNOSE_WITH_LEVEL(critical, ID, __VA_ARGS__)
56+ #define DIAGNOSE_ERROR (ID, ...) DIAGNOSE_WITH_LEVEL(error, ID, __VA_ARGS__)
57+
58+ #define CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX " [{}] "
59+ // TODO(C++20) replace non-standard , ##__VA_ARGS__ with __VA_OPT__(,) __VA_ARGS__
60+ #define DIAGNOSE_WITH_LEVEL (LEVEL, ID, FORMAT, ...) \
61+ LOG_WITH_LEVEL (LEVEL, CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX FORMAT, \
62+ ::codeql::detail::SwiftDiagnosticLogWrapper{ID}, ##__VA_ARGS__);
6163
6264// avoid calling into binlog's original macros
6365#undef BINLOG_CRITICAL
@@ -126,8 +128,7 @@ class Log {
126128 return instance ().getLoggerConfigurationImpl (name);
127129 }
128130
129- template <typename Source>
130- static void diagnose (const Source& source,
131+ static void diagnose (const SwiftDiagnostic& source,
131132 const std::chrono::system_clock::time_point& time,
132133 std::string_view message) {
133134 instance ().diagnostics .write (source, time, message);
@@ -224,31 +225,9 @@ class Logger {
224225};
225226
226227namespace detail {
227- constexpr std::string_view diagnosticsFormatPrefix = " [{}] " ;
228-
229- template <typename T>
230- constexpr bool checkLogArgs (std::string_view format) {
231- using Type = std::remove_cv_t <std::remove_reference_t <T>>;
232- constexpr bool isDiagnostic = std::is_same_v<Type, SwiftDiagnosticsSource> ||
233- std::is_same_v<Type, SwiftDiagnosticsSourceWithLocation>;
234- return !isDiagnostic ||
235- format.substr (0 , diagnosticsFormatPrefix.size ()) == diagnosticsFormatPrefix;
236- }
237-
238- template <typename Writer, typename Source, typename ... T>
239- void binlogAddEventIgnoreFirstOverload (Writer& writer,
240- std::uint64_t eventSourceId,
241- std::uint64_t clock,
242- const char * format,
243- const Source& source,
244- T&&... t) {
245- std::chrono::system_clock::time_point point{
246- std::chrono::duration_cast<std::chrono::system_clock::duration>(
247- std::chrono::nanoseconds{clock})};
248- constexpr auto offset = ::codeql::detail::diagnosticsFormatPrefix.size ();
249- ::codeql::Log::diagnose (source, point, fmt::format(format + offset, t...));
250- writer.addEvent (eventSourceId, clock, source, std::forward<T>(t)...);
251- }
228+ struct SwiftDiagnosticLogWrapper {
229+ const SwiftDiagnostic& value;
230+ };
252231
253232} // namespace detail
254233} // namespace codeql
@@ -262,32 +241,37 @@ void addEventIgnoreFirst(Writer& writer,
262241 std::uint64_t eventSourceId,
263242 std::uint64_t clock,
264243 const char (&format)[N],
265- const codeql::SwiftDiagnosticsSource & source,
244+ codeql::detail::SwiftDiagnosticLogWrapper& & source,
266245 T&&... t) {
267- codeql::detail::binlogAddEventIgnoreFirstOverload (writer, eventSourceId, clock, format, source,
268- std::forward<T>(t)...);
246+ std::chrono::system_clock::time_point point{
247+ std::chrono::duration_cast<std::chrono::system_clock::duration>(
248+ std::chrono::nanoseconds{clock})};
249+ constexpr std::string_view prefix = CODEQL_DIAGNOSTIC_LOG_FORMAT_PREFIX;
250+ ::codeql::Log::diagnose (source.value, point, fmt::format(format + prefix.size(), t...));
251+ writer.addEvent (eventSourceId, clock, source, std::forward<T>(t)...);
269252}
253+ } // namespace binlog::detail
270254
271- template <typename Writer, size_t N, typename ... T>
272- void addEventIgnoreFirst (Writer& writer,
273- std::uint64_t eventSourceId,
274- std::uint64_t clock,
275- const char (&format)[N],
276- codeql::SwiftDiagnosticsSourceWithLocation&& source,
277- T&&... t) {
278- codeql::detail::binlogAddEventIgnoreFirstOverload (writer, eventSourceId, clock, format, source,
279- std::forward<T>(t)...);
280- }
255+ namespace mserialize {
256+ // log diagnostics wrapper using the abbreviation of the underlying diagnostic, using
257+ // binlog/mserialize internal plumbing
258+ template <>
259+ struct CustomTag <codeql::detail::SwiftDiagnosticLogWrapper, void >
260+ : detail::BuiltinTag<std::string> {
261+ using T = codeql::detail::SwiftDiagnosticLogWrapper;
262+ };
281263
282- template <typename Writer, size_t N, typename ... T>
283- void addEventIgnoreFirst (Writer& writer,
284- std::uint64_t eventSourceId,
285- std::uint64_t clock,
286- const char (&format)[N],
287- const codeql::SwiftDiagnosticsSourceWithLocation& source,
288- T&&... t) {
289- codeql::detail::binlogAddEventIgnoreFirstOverload (writer, eventSourceId, clock, format, source,
290- std::forward<T>(t)...);
291- }
264+ template <>
265+ struct CustomSerializer <codeql::detail::SwiftDiagnosticLogWrapper, void > {
266+ template <typename OutputStream>
267+ static void serialize (const codeql::detail::SwiftDiagnosticLogWrapper& source,
268+ OutputStream& out) {
269+ mserialize::serialize (source.value .abbreviation (), out);
270+ }
292271
293- } // namespace binlog::detail
272+ static size_t serialized_size (const codeql::detail::SwiftDiagnosticLogWrapper& source) {
273+ return mserialize::serialized_size (source.value .abbreviation ());
274+ }
275+ };
276+
277+ } // namespace mserialize
0 commit comments