diff --git a/misc/bazel/workspace.bzl b/misc/bazel/workspace.bzl index 50f0d1393f0e..ef89ccfb666e 100644 --- a/misc/bazel/workspace.bzl +++ b/misc/bazel/workspace.bzl @@ -43,13 +43,3 @@ def codeql_workspace(repository_name = "codeql"): "https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz", ], ) - - maybe( - repo_rule = http_archive, - name = "absl", - sha256 = "cec2e5bf780532bd0ac672eb8d43c0f8bbe84ca5df8718320184034b7f59a398", - urls = [ - "https://github.com/abseil/abseil-cpp/archive/d2c5297a3c3948de765100cb7e5cccca1210d23c.tar.gz", - ], - strip_prefix = "abseil-cpp-d2c5297a3c3948de765100cb7e5cccca1210d23c", - ) diff --git a/swift/extractor/SwiftExtractor.cpp b/swift/extractor/SwiftExtractor.cpp index 54f46f2ac315..77e27c00f418 100644 --- a/swift/extractor/SwiftExtractor.cpp +++ b/swift/extractor/SwiftExtractor.cpp @@ -15,7 +15,7 @@ #include "swift/extractor/infra/SwiftLocationExtractor.h" #include "swift/extractor/infra/SwiftBodyEmissionStrategy.h" #include "swift/extractor/mangler/SwiftMangler.h" -#include "swift/extractor/infra/log/SwiftAssert.h" +#include "swift/logging/SwiftAssert.h" using namespace codeql; using namespace std::string_literals; diff --git a/swift/extractor/infra/BUILD.bazel b/swift/extractor/infra/BUILD.bazel index 0b69dc1c3b9c..f2b7f6baee2c 100644 --- a/swift/extractor/infra/BUILD.bazel +++ b/swift/extractor/infra/BUILD.bazel @@ -8,8 +8,8 @@ swift_cc_library( deps = [ "//swift/extractor/config", "//swift/extractor/infra/file", - "//swift/extractor/infra/log", "//swift/extractor/trap", + "//swift/logging", "//swift/third_party/swift-llvm-support", ], ) diff --git a/swift/extractor/infra/SwiftDispatcher.h b/swift/extractor/infra/SwiftDispatcher.h index e700b9fb52df..33b0614e4353 100644 --- a/swift/extractor/infra/SwiftDispatcher.h +++ b/swift/extractor/infra/SwiftDispatcher.h @@ -13,7 +13,7 @@ #include "swift/extractor/infra/SwiftBodyEmissionStrategy.h" #include "swift/extractor/infra/SwiftMangledName.h" #include "swift/extractor/config/SwiftExtractorState.h" -#include "swift/extractor/infra/log/SwiftAssert.h" +#include "swift/logging/SwiftAssert.h" namespace codeql { diff --git a/swift/extractor/infra/file/BUILD.bazel b/swift/extractor/infra/file/BUILD.bazel index 989b15630c2f..65cfea339950 100644 --- a/swift/extractor/infra/file/BUILD.bazel +++ b/swift/extractor/infra/file/BUILD.bazel @@ -2,10 +2,16 @@ load("//swift:rules.bzl", "swift_cc_library") swift_cc_library( name = "file", - srcs = glob(["*.cpp", "FsLogger.h"]), - hdrs = glob(["*.h"], exclude=["FsLogger.h"]) + [":path_hash_workaround"], + srcs = glob([ + "*.cpp", + "FsLogger.h", + ]), + hdrs = glob( + ["*.h"], + exclude = ["FsLogger.h"], + ) + [":path_hash_workaround"], visibility = ["//swift:__subpackages__"], - deps = ["//swift/extractor/infra/log"], + deps = ["//swift/logging"], ) genrule( diff --git a/swift/extractor/infra/file/FsLogger.h b/swift/extractor/infra/file/FsLogger.h index b4545622878f..5797b8929821 100644 --- a/swift/extractor/infra/file/FsLogger.h +++ b/swift/extractor/infra/file/FsLogger.h @@ -1,4 +1,4 @@ -#include "swift/extractor/infra/log/SwiftLogging.h" +#include "swift/logging/SwiftLogging.h" namespace codeql { namespace fs_logger { diff --git a/swift/extractor/infra/file/TargetFile.cpp b/swift/extractor/infra/file/TargetFile.cpp index d6ef20fae8ed..4ce4c8ae23be 100644 --- a/swift/extractor/infra/file/TargetFile.cpp +++ b/swift/extractor/infra/file/TargetFile.cpp @@ -1,7 +1,7 @@ #include "swift/extractor/infra/file/TargetFile.h" #include "swift/extractor/infra/file/FsLogger.h" -#include "swift/extractor/infra/log/SwiftLogging.h" -#include "swift/extractor/infra/log/SwiftAssert.h" +#include "swift/logging/SwiftLogging.h" +#include "swift/logging/SwiftAssert.h" #include #include diff --git a/swift/extractor/invocation/SwiftInvocationExtractor.cpp b/swift/extractor/invocation/SwiftInvocationExtractor.cpp index 402e755f72c7..3ec5b9bf0a4e 100644 --- a/swift/extractor/invocation/SwiftInvocationExtractor.cpp +++ b/swift/extractor/invocation/SwiftInvocationExtractor.cpp @@ -4,7 +4,7 @@ #include "swift/extractor/trap/generated/TrapTags.h" #include "swift/extractor/infra/file/TargetFile.h" #include "swift/extractor/infra/file/Path.h" -#include "swift/extractor/infra/log/SwiftAssert.h" +#include "swift/logging/SwiftAssert.h" #include "swift/extractor/mangler/SwiftMangler.h" namespace fs = std::filesystem; diff --git a/swift/extractor/main.cpp b/swift/extractor/main.cpp index 4e6f16cd62fa..f195193e5d7e 100644 --- a/swift/extractor/main.cpp +++ b/swift/extractor/main.cpp @@ -18,12 +18,12 @@ #include "swift/extractor/invocation/SwiftInvocationExtractor.h" #include "swift/extractor/trap/TrapDomain.h" #include "swift/extractor/infra/file/Path.h" -#include "swift/extractor/infra/log/SwiftAssert.h" +#include "swift/logging/SwiftAssert.h" using namespace std::string_literals; using namespace codeql::main_logger; -const std::string_view codeql::logRootName = "extractor"; +const std::string_view codeql::programName = "extractor"; // must be called before processFrontendOptions modifies output paths static void lockOutputSwiftModuleTraps(codeql::SwiftExtractorState& state, diff --git a/swift/extractor/remapping/SwiftFileInterception.cpp b/swift/extractor/remapping/SwiftFileInterception.cpp index 2943f924008b..7b22aabec8f3 100644 --- a/swift/extractor/remapping/SwiftFileInterception.cpp +++ b/swift/extractor/remapping/SwiftFileInterception.cpp @@ -14,7 +14,7 @@ #include "swift/extractor/infra/file/PathHash.h" #include "swift/extractor/infra/file/Path.h" -#include "swift/extractor/infra/log/SwiftAssert.h" +#include "swift/logging/SwiftAssert.h" #ifdef __APPLE__ // path is hardcoded as otherwise redirection could break when setting DYLD_FALLBACK_LIBRARY_PATH diff --git a/swift/extractor/trap/BUILD.bazel b/swift/extractor/trap/BUILD.bazel index 59870efbf883..f156aa9c9845 100644 --- a/swift/extractor/trap/BUILD.bazel +++ b/swift/extractor/trap/BUILD.bazel @@ -23,7 +23,10 @@ genrule( "--schema=$(location //swift:schema)", "--script-name=codegen/codegen.py", ]), - exec_tools = ["//misc/codegen", "//swift:schema"], + exec_tools = [ + "//misc/codegen", + "//swift:schema", + ], ) filegroup( @@ -49,7 +52,7 @@ swift_cc_library( visibility = ["//visibility:public"], deps = [ "//swift/extractor/infra/file", - "//swift/extractor/infra/log", + "//swift/logging", "@absl//absl/numeric:bits", ], ) diff --git a/swift/extractor/trap/TrapDomain.h b/swift/extractor/trap/TrapDomain.h index 7a16b474fa2e..2ca5efa113de 100644 --- a/swift/extractor/trap/TrapDomain.h +++ b/swift/extractor/trap/TrapDomain.h @@ -5,7 +5,7 @@ #include "swift/extractor/trap/TrapLabel.h" #include "swift/extractor/infra/file/TargetFile.h" -#include "swift/extractor/infra/log/SwiftLogging.h" +#include "swift/logging/SwiftLogging.h" #include "swift/extractor/infra/SwiftMangledName.h" namespace codeql { diff --git a/swift/extractor/infra/log/BUILD.bazel b/swift/logging/BUILD.bazel similarity index 50% rename from swift/extractor/infra/log/BUILD.bazel rename to swift/logging/BUILD.bazel index 2a384e136a5a..598d3a3aa317 100644 --- a/swift/extractor/infra/log/BUILD.bazel +++ b/swift/logging/BUILD.bazel @@ -1,7 +1,11 @@ cc_library( - name = "log", + name = "logging", srcs = glob(["*.cpp"]), hdrs = glob(["*.h"]), visibility = ["//visibility:public"], - deps = ["@binlog"], + deps = [ + "@absl//absl/strings", + "@binlog", + "@json", + ], ) diff --git a/swift/extractor/infra/log/SwiftAssert.h b/swift/logging/SwiftAssert.h similarity index 96% rename from swift/extractor/infra/log/SwiftAssert.h rename to swift/logging/SwiftAssert.h index faadef97698c..9ffb3c5f860d 100644 --- a/swift/extractor/infra/log/SwiftAssert.h +++ b/swift/logging/SwiftAssert.h @@ -2,7 +2,7 @@ #include -#include "swift/extractor/infra/log/SwiftLogging.h" +#include "swift/logging/SwiftLogging.h" // assert CONDITION, which is always evaluated (once) regardless of the build type. If // CONDITION is not satisfied, emit a critical log optionally using provided format and arguments, diff --git a/swift/logging/SwiftDiagnostics.cpp b/swift/logging/SwiftDiagnostics.cpp new file mode 100644 index 000000000000..dfe86f8186f4 --- /dev/null +++ b/swift/logging/SwiftDiagnostics.cpp @@ -0,0 +1,68 @@ +#include "swift/logging/SwiftDiagnostics.h" + +#include +#include +#include "absl/strings/str_join.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_split.h" +#include "swift/logging/SwiftAssert.h" + +namespace codeql { + +namespace { +Logger& logger() { + static Logger ret{"diagnostics"}; + return ret; +} +} // namespace + +void SwiftDiagnosticsSource::emit(std::ostream& out, + std::string_view timestamp, + std::string_view message) const { + nlohmann::json entry = { + {"source", + { + {"id", sourceId()}, + {"name", name}, + {"extractorName", extractorName}, + }}, + {"visibility", + { + {"statusPage", true}, + {"cliSummaryTable", true}, + {"telemetry", true}, + }}, + {"severity", "error"}, + {"helpLinks", std::vector(absl::StrSplit(helpLinks, ' '))}, + {"plaintextMessage", absl::StrCat(message, ".\n\n", action, ".")}, + {"timestamp", timestamp}, + }; + out << entry << '\n'; +} + +std::string SwiftDiagnosticsSource::sourceId() const { + auto ret = absl::StrJoin({extractorName, programName, id}, "/"); + std::replace(ret.begin(), ret.end(), '_', '-'); + return ret; +} +void SwiftDiagnosticsSource::registerImpl(const SwiftDiagnosticsSource* source) { + auto [it, inserted] = map().emplace(source->id, source); + CODEQL_ASSERT(inserted, "duplicate diagnostics source detected with id {}", source->id); +} + +void SwiftDiagnosticsDumper::write(const char* buffer, std::size_t bufferSize) { + binlog::Range range{buffer, bufferSize}; + binlog::RangeEntryStream input{range}; + while (auto event = events.nextEvent(input)) { + const auto& source = SwiftDiagnosticsSource::get(event->source->category); + std::ostringstream oss; + timestampedMessagePrinter.printEvent(oss, *event, events.writerProp(), events.clockSync()); + // TODO(C++20) use oss.view() directly + auto data = oss.str(); + std::string_view view = data; + using ViewPair = std::pair; + auto [timestamp, message] = ViewPair(absl::StrSplit(view, absl::MaxSplits(' ', 1))); + source.emit(output, timestamp, message); + } +} +} // namespace codeql diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h new file mode 100644 index 000000000000..95c6cb85e5a8 --- /dev/null +++ b/swift/logging/SwiftDiagnostics.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace codeql { + +extern const std::string_view programName; + +// Models a diagnostic source for Swift, holding static information that goes out into a diagnostic +// These are internally stored into a map on id's. A specific error log can use binlog's category +// as id, which will then be used to recover the diagnostic source while dumping. +struct SwiftDiagnosticsSource { + std::string_view id; + std::string_view name; + static constexpr std::string_view extractorName = "swift"; + std::string_view action; + // space separated if more than 1. Not a vector to allow constexpr + // TODO(C++20) with vector going constexpr this can be turned to `std::vector` + std::string_view helpLinks; + + // for the moment, we only output errors, so no need to store the severity + + // registers a diagnostics source for later retrieval with get, if not done yet + template + static void ensureRegistered() { + static std::once_flag once; + std::call_once(once, registerImpl, Source); + } + + // gets a previously inscribed SwiftDiagnosticsSource for the given id. Will abort if none exists + static const SwiftDiagnosticsSource& get(const std::string& id) { return *map().at(id); } + + // emit a JSON diagnostics for this source with the given timestamp and message to out + // A plaintextMessage is used that includes both the message and the action to take. Dots are + // appended to both. The id is used to construct the source id in the form + // `swift//` + void emit(std::ostream& out, std::string_view timestamp, std::string_view message) const; + + private: + static void registerImpl(const SwiftDiagnosticsSource* source); + + std::string sourceId() const; + using Map = std::unordered_map; + + static Map& map() { + static Map ret; + return ret; + } +}; + +// An output modeling binlog's output stream concept that intercepts binlog entries and translates +// them to appropriate diagnostics JSON entries +class SwiftDiagnosticsDumper { + public: + // opens path for writing out JSON entries. Returns whether the operation was successful. + bool open(const std::filesystem::path& path) { + output.open(path); + return output.good(); + } + + // write out binlog entries as corresponding JSON diagnostics entries. Expects all entries to have + // a category equal to an id of a previously created SwiftDiagnosticSource. + void write(const char* buffer, std::size_t bufferSize); + + private: + binlog::EventStream events; + std::ofstream output; + binlog::PrettyPrinter timestampedMessagePrinter{"%u %m", "%Y-%m-%dT%H:%M:%S.%NZ"}; +}; + +} // namespace codeql + +namespace codeql_diagnostics { +constexpr codeql::SwiftDiagnosticsSource internal_error{ + "internal_error", + "Internal error", + "Contact us about this issue", +}; +} // namespace codeql_diagnostics diff --git a/swift/extractor/infra/log/SwiftLogging.cpp b/swift/logging/SwiftLogging.cpp similarity index 80% rename from swift/extractor/infra/log/SwiftLogging.cpp rename to swift/logging/SwiftLogging.cpp index 8769f740a721..4f3e3607f2b9 100644 --- a/swift/extractor/infra/log/SwiftLogging.cpp +++ b/swift/logging/SwiftLogging.cpp @@ -1,4 +1,4 @@ -#include "swift/extractor/infra/log/SwiftLogging.h" +#include "swift/logging/SwiftLogging.h" #include #include @@ -50,7 +50,7 @@ Log::Level matchToLevel(std::csub_match m) { } // namespace -std::vector Log::collectSeverityRulesAndReturnProblems(const char* envVar) { +std::vector Log::collectLevelRulesAndReturnProblems(const char* envVar) { std::vector problems; if (auto levels = getEnvOr(envVar, nullptr)) { // expect comma-separated : @@ -92,12 +92,13 @@ std::vector Log::collectSeverityRulesAndReturnProblems(const char* void Log::configure() { // as we are configuring logging right now, we collect problems and log them at the end - auto problems = collectSeverityRulesAndReturnProblems("CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS"); + auto problems = collectLevelRulesAndReturnProblems("CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS"); + auto now = std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); if (text || binary) { std::filesystem::path logFile = getEnvOr("CODEQL_EXTRACTOR_SWIFT_LOG_DIR", "extractor-out/log"); logFile /= "swift"; - logFile /= logRootName; - logFile /= std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); + logFile /= programName; + logFile /= now; std::error_code ec; std::filesystem::create_directories(logFile.parent_path(), ec); if (!ec) { @@ -123,6 +124,25 @@ void Log::configure() { binary.level = Level::no_logs; text.level = Level::no_logs; } + if (diagnostics) { + std::filesystem::path diagFile = + getEnvOr("CODEQL_EXTRACTOR_SWIFT_DIAGNOSTIC_DIR", "extractor-out/diagnostics"); + diagFile /= programName; + diagFile /= now; + diagFile.replace_extension(".jsonl"); + std::error_code ec; + std::filesystem::create_directories(diagFile.parent_path(), ec); + if (!ec) { + if (!diagnostics.output.open(diagFile)) { + problems.emplace_back("Unable to open diagnostics json file " + diagFile.string()); + diagnostics.level = Level::no_logs; + } + } else { + problems.emplace_back("Unable to create diagnostics directory " + + diagFile.parent_path().string() + ": " + ec.message()); + diagnostics.level = Level::no_logs; + } + } } for (const auto& problem : problems) { LOG_ERROR("{}", problem); @@ -143,7 +163,7 @@ void Log::flushImpl() { } Log::LoggerConfiguration Log::getLoggerConfigurationImpl(std::string_view name) { - LoggerConfiguration ret{session, std::string{logRootName}}; + LoggerConfiguration ret{session, std::string{programName}}; ret.fullyQualifiedName += '/'; ret.fullyQualifiedName += name; ret.level = std::min({binary.level, text.level, console.level}); @@ -159,6 +179,7 @@ Log& Log::write(const char* buffer, std::streamsize size) { if (text) text.write(buffer, size); if (binary) binary.write(buffer, size); if (console) console.write(buffer, size); + if (diagnostics) diagnostics.write(buffer, size); return *this; } diff --git a/swift/extractor/infra/log/SwiftLogging.h b/swift/logging/SwiftLogging.h similarity index 71% rename from swift/extractor/infra/log/SwiftLogging.h rename to swift/logging/SwiftLogging.h index 60b2ba5e5ff2..cf756c9e5a0c 100644 --- a/swift/extractor/infra/log/SwiftLogging.h +++ b/swift/logging/SwiftLogging.h @@ -13,6 +13,8 @@ #include #include +#include "swift/logging/SwiftDiagnostics.h" + // Logging macros. These will call `logger()` to get a Logger instance, picking up any `logger` // defined in the current scope. Domain-specific loggers can be added or used by either: // * providing a class field called `logger` (as `Logger::operator()()` returns itself) @@ -21,23 +23,36 @@ // * passing a logger around using a `Logger& logger` function parameter // They are created with a name that appears in the logs and can be used to filter debug levels (see // `Logger`). -#define LOG_CRITICAL(...) LOG_WITH_LEVEL(codeql::Log::Level::critical, __VA_ARGS__) -#define LOG_ERROR(...) LOG_WITH_LEVEL(codeql::Log::Level::error, __VA_ARGS__) -#define LOG_WARNING(...) LOG_WITH_LEVEL(codeql::Log::Level::warning, __VA_ARGS__) -#define LOG_INFO(...) LOG_WITH_LEVEL(codeql::Log::Level::info, __VA_ARGS__) -#define LOG_DEBUG(...) LOG_WITH_LEVEL(codeql::Log::Level::debug, __VA_ARGS__) -#define LOG_TRACE(...) LOG_WITH_LEVEL(codeql::Log::Level::trace, __VA_ARGS__) +#define LOG_CRITICAL(...) LOG_WITH_LEVEL(critical, __VA_ARGS__) +#define LOG_ERROR(...) LOG_WITH_LEVEL(error, __VA_ARGS__) +#define LOG_WARNING(...) LOG_WITH_LEVEL(warning, __VA_ARGS__) +#define LOG_INFO(...) LOG_WITH_LEVEL(info, __VA_ARGS__) +#define LOG_DEBUG(...) LOG_WITH_LEVEL(debug, __VA_ARGS__) +#define LOG_TRACE(...) LOG_WITH_LEVEL(trace, __VA_ARGS__) // only do the actual logging if the picked up `Logger` instance is configured to handle the // provided log level. `LEVEL` must be a compile-time constant. `logger()` is evaluated once -#define LOG_WITH_LEVEL(LEVEL, ...) \ - do { \ - constexpr codeql::Log::Level _level = LEVEL; \ - codeql::Logger& _logger = logger(); \ - if (_level >= _logger.level()) { \ - BINLOG_CREATE_SOURCE_AND_EVENT(_logger.writer(), _level, /* category */, binlog::clockNow(), \ - __VA_ARGS__); \ - } \ +#define LOG_WITH_LEVEL_AND_CATEGORY(LEVEL, CATEGORY, ...) \ + do { \ + constexpr codeql::Log::Level _level = codeql::Log::Level::LEVEL; \ + codeql::Logger& _logger = logger(); \ + if (_level >= _logger.level()) { \ + BINLOG_CREATE_SOURCE_AND_EVENT(_logger.writer(), _level, CATEGORY, binlog::clockNow(), \ + __VA_ARGS__); \ + } \ + } while (false) + +#define LOG_WITH_LEVEL(LEVEL, ...) LOG_WITH_LEVEL_AND_CATEGORY(LEVEL, , __VA_ARGS__) + +// Emit errors with a specified diagnostics ID. This must be the name of a `SwiftDiagnosticsSource` +// defined in the `codeql_diagnostics` namespace, which must have `id` equal to its name. +#define DIAGNOSE_CRITICAL(ID, ...) DIAGNOSE_WITH_LEVEL(critical, ID, __VA_ARGS__) +#define DIAGNOSE_ERROR(ID, ...) DIAGNOSE_WITH_LEVEL(error, ID, __VA_ARGS__) + +#define DIAGNOSE_WITH_LEVEL(LEVEL, ID, ...) \ + do { \ + codeql::SwiftDiagnosticsSource::inscribe<&codeql_diagnostics::ID>(); \ + LOG_WITH_LEVEL_AND_CATEGORY(LEVEL, ID, __VA_ARGS__); \ } while (false) // avoid calling into binlog's original macros @@ -69,7 +84,7 @@ namespace codeql { // tools should define this to tweak the root name of all loggers -extern const std::string_view logRootName; +extern const std::string_view programName; // This class is responsible for the global log state (outputs, log level rules, flushing) // State is stored in the singleton `Log::instance()`. @@ -77,7 +92,7 @@ extern const std::string_view logRootName; // `Log::configure("extractor")`). Then, `Log::flush()` should be regularly called. // Logging is configured upon first usage. This consists in // * using environment variable `CODEQL_EXTRACTOR_SWIFT_LOG_DIR` to choose where to dump the log -// file(s). Log files will go to a subdirectory thereof named after `logRootName` +// file(s). Log files will go to a subdirectory thereof named after `programName` // * using environment variable `CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS` to configure levels for // loggers and outputs. This must have the form of a comma separated `spec:level` list, where // `spec` is either a glob pattern (made up of alphanumeric, `/`, `*` and `.` characters) for @@ -123,23 +138,40 @@ class Log { friend binlog::Session; Log& write(const char* buffer, std::streamsize size); + struct OnlyWithCategory {}; + // Output filtered according to a configured log level template struct FilteredOutput { binlog::Severity level; Output output; - binlog::EventFilter filter{ - [this](const binlog::EventSource& src) { return src.severity >= level; }}; + binlog::EventFilter filter; template FilteredOutput(Level level, Args&&... args) - : level{level}, output{std::forward(args)...} {} + : level{level}, output{std::forward(args)...}, filter{filterOnLevel()} {} + + template + FilteredOutput(OnlyWithCategory, Level level, Args&&... args) + : level{level}, + output{std::forward(args)...}, + filter{filterOnLevelAndNonEmptyCategory()} {} FilteredOutput& write(const char* buffer, std::streamsize size) { filter.writeAllowed(buffer, size, output); return *this; } + binlog::EventFilter::Predicate filterOnLevel() const { + return [this](const binlog::EventSource& src) { return src.severity >= level; }; + } + + binlog::EventFilter::Predicate filterOnLevelAndNonEmptyCategory() const { + return [this](const binlog::EventSource& src) { + return !src.category.empty() && src.severity >= level; + }; + } + // if configured as `no_logs`, the output is effectively disabled explicit operator bool() const { return level < Level::no_logs; } }; @@ -152,14 +184,15 @@ class Log { FilteredOutput binary{Level::no_logs}; FilteredOutput text{Level::info, textFile, format}; FilteredOutput console{Level::warning, std::cerr, format}; + FilteredOutput diagnostics{OnlyWithCategory{}, Level::error}; LevelRules sourceRules; - std::vector collectSeverityRulesAndReturnProblems(const char* envVar); + std::vector collectLevelRulesAndReturnProblems(const char* envVar); }; // This class represent a named domain-specific logger, responsible for pushing logs using the // underlying `binlog::SessionWriter` class. This has a configured log level, so that logs on this // `Logger` with a level lower than the configured one are no-ops. The level is configured based -// on rules matching `/` in `CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS` (see above). +// on rules matching `/` in `CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS` (see above). // `` is provided in the constructor. If no rule matches the name, the log level defaults to // the minimum level of all outputs. class Logger { diff --git a/swift/third_party/binlog/BUILD.binlog.bazel b/swift/third_party/BUILD.binlog.bazel similarity index 100% rename from swift/third_party/binlog/BUILD.binlog.bazel rename to swift/third_party/BUILD.binlog.bazel diff --git a/swift/third_party/picosha2/BUILD.picosha2.bazel b/swift/third_party/BUILD.picosha2.bazel similarity index 100% rename from swift/third_party/picosha2/BUILD.picosha2.bazel rename to swift/third_party/BUILD.picosha2.bazel diff --git a/swift/third_party/swift-llvm-support/BUILD.swift-llvm-support.bazel b/swift/third_party/BUILD.swift-llvm-support.bazel similarity index 100% rename from swift/third_party/swift-llvm-support/BUILD.swift-llvm-support.bazel rename to swift/third_party/BUILD.swift-llvm-support.bazel diff --git a/swift/third_party/binlog/BUILD.bazel b/swift/third_party/binlog/BUILD.bazel deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/swift/third_party/load.bzl b/swift/third_party/load.bzl index 643fad096dbb..cc5de3427a05 100644 --- a/swift/third_party/load.bzl +++ b/swift/third_party/load.bzl @@ -1,4 +1,5 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") _swift_prebuilt_version = "swift-5.7.3-RELEASE.142" _swift_sha_map = { @@ -12,28 +13,20 @@ _swift_arch_map = { "macOS-X64": "darwin_x86_64", } -def _get_label(workspace_name, package, target): - return "@%s//swift/third_party/%s:%s" % (workspace_name, package, target) - -def _get_build(workspace_name, package): - return _get_label(workspace_name, package, "BUILD.%s.bazel" % package) - -def _get_patch(workspace_name, package, patch): - return _get_label(workspace_name, package, "patches/%s.patch" % patch) - -def _github_archive(*, name, workspace_name, repository, commit, sha256 = None, patches = None): +def _github_archive(*, name, repository, commit, build_file = None, sha256 = None): github_name = repository[repository.index("/") + 1:] - patches = [_get_patch(workspace_name, name, p) for p in patches or []] - http_archive( + maybe( + repo_rule = http_archive, name = name, url = "https://github.com/%s/archive/%s.zip" % (repository, commit), strip_prefix = "%s-%s" % (github_name, commit), - build_file = _get_build(workspace_name, name), + build_file = build_file, sha256 = sha256, - patch_args = ["-p1"], - patches = patches, ) +def _build(workspace_name, package): + return "@%s//swift/third_party:BUILD.%s.bazel" % (workspace_name, package) + def load_dependencies(workspace_name): for repo_arch, arch in _swift_arch_map.items(): sha256 = _swift_sha_map[repo_arch] @@ -44,15 +37,13 @@ def load_dependencies(workspace_name): _swift_prebuilt_version, repo_arch, ), - build_file = _get_build(workspace_name, "swift-llvm-support"), + build_file = _build(workspace_name, "swift-llvm-support"), sha256 = sha256, - patch_args = ["-p1"], - patches = [], ) _github_archive( name = "picosha2", - workspace_name = workspace_name, + build_file = _build(workspace_name, "picosha2"), repository = "okdshin/PicoSHA2", commit = "27fcf6979298949e8a462e16d09a0351c18fcaf2", sha256 = "d6647ca45a8b7bdaf027ecb68d041b22a899a0218b7206dee755c558a2725abb", @@ -60,8 +51,22 @@ def load_dependencies(workspace_name): _github_archive( name = "binlog", - workspace_name = workspace_name, + build_file = _build(workspace_name, "binlog"), repository = "morganstanley/binlog", commit = "3fef8846f5ef98e64211e7982c2ead67e0b185a6", sha256 = "f5c61d90a6eff341bf91771f2f465be391fd85397023e1b391c17214f9cbd045", ) + + _github_archive( + name = "absl", + repository = "abseil/abseil-cpp", + commit = "d2c5297a3c3948de765100cb7e5cccca1210d23c", + sha256 = "735a9efc673f30b3212bfd57f38d5deb152b543e35cd58b412d1363b15242049", + ) + + _github_archive( + name = "json", + repository = "nlohmann/json", + commit = "6af826d0bdb55e4b69e3ad817576745335f243ca", + sha256 = "702bb0231a5e21c0374230fed86c8ae3d07ee50f34ffd420e7f8249854b7d85b", + ) diff --git a/swift/third_party/picosha2/BUILD.bazel b/swift/third_party/picosha2/BUILD.bazel deleted file mode 100644 index e69de29bb2d1..000000000000