From 84c017083f674efb0ac705cdd93316b065843a9b Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Tue, 9 May 2023 13:59:39 +0200 Subject: [PATCH] Swift: add configuration of diagnostics logs --- swift/README.md | 2 +- swift/logging/SwiftDiagnostics.h | 2 ++ swift/logging/SwiftLogging.cpp | 24 ++++++++++++++++-------- swift/logging/SwiftLogging.h | 2 +- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/swift/README.md b/swift/README.md index bbf0ef30dc6..b16d5efe360 100644 --- a/swift/README.md +++ b/swift/README.md @@ -52,7 +52,7 @@ A log file is produced for each run under `CODEQL_EXTRACTOR_SWIFT_LOG_DIR` (the You can use the environment variable `CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS` to configure levels for loggers and outputs. This must have the form of a comma separated `spec:min_level` list, where `spec` is either a glob pattern (made up of alphanumeric, `/`, `*` and `.` characters) for -matching logger names or one of `out:bin`, `out:text` or `out:console`, and `min_level` is one +matching logger names or one of `out:binary`, `out:text`, `out:console` or `out:diagnostics`, and `min_level` is one of `trace`, `debug`, `info`, `warning`, `error`, `critical` or `no_logs` to turn logs completely off. Current output default levels are no binary logs, `info` logs or higher in the text file and `warning` logs or higher on diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h index 95c6cb85e5a..81d7f170ff3 100644 --- a/swift/logging/SwiftDiagnostics.h +++ b/swift/logging/SwiftDiagnostics.h @@ -67,6 +67,8 @@ class SwiftDiagnosticsDumper { return output.good(); } + void flush() { output.flush(); } + // 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); diff --git a/swift/logging/SwiftLogging.cpp b/swift/logging/SwiftLogging.cpp index 37effd7ff9a..f742a63e25f 100644 --- a/swift/logging/SwiftLogging.cpp +++ b/swift/logging/SwiftLogging.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #define LEVEL_REGEX_PATTERN "trace|debug|info|warning|error|critical|no_logs" @@ -57,8 +58,8 @@ std::vector Log::collectLevelRulesAndReturnProblems(const char* env if (auto levels = getEnvOr(envVar, nullptr)) { // expect comma-separated : std::regex comma{","}; - std::regex levelAssignment{R"((?:([*./\w]+)|(?:out:(bin|text|console))):()" LEVEL_REGEX_PATTERN - ")"}; + std::regex levelAssignment{ + R"((?:([*./\w]+)|(?:out:(binary|text|console|diagnostics))):()" LEVEL_REGEX_PATTERN ")"}; std::cregex_token_iterator begin{levels, levels + strlen(levels), comma, -1}; std::cregex_token_iterator end{}; for (auto it = begin; it != end; ++it) { @@ -76,12 +77,14 @@ std::vector Log::collectLevelRulesAndReturnProblems(const char* env sourceRules.emplace_back(pattern, level); } else { auto out = matchToView(match[2]); - if (out == "bin") { + if (out == "binary") { binary.level = level; } else if (out == "text") { text.level = level; } else if (out == "console") { console.level = level; + } else if (out == "diagnostics") { + diagnostics.level = level; } } } else { @@ -95,12 +98,14 @@ std::vector Log::collectLevelRulesAndReturnProblems(const char* env void Log::configure() { // as we are configuring logging right now, we collect problems and log them at the end auto problems = collectLevelRulesAndReturnProblems("CODEQL_EXTRACTOR_SWIFT_LOG_LEVELS"); - auto now = std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); + auto logBaseName = std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); + logBaseName += '-'; + logBaseName += std::to_string(getpid()); if (text || binary) { std::filesystem::path logFile = getEnvOr("CODEQL_EXTRACTOR_SWIFT_LOG_DIR", "extractor-out/log"); logFile /= "swift"; logFile /= programName; - logFile /= now; + logFile /= logBaseName; std::error_code ec; std::filesystem::create_directories(logFile.parent_path(), ec); if (!ec) { @@ -130,7 +135,7 @@ void Log::configure() { std::filesystem::path diagFile = getEnvOr("CODEQL_EXTRACTOR_SWIFT_DIAGNOSTIC_DIR", "extractor-out/diagnostics"); diagFile /= programName; - diagFile /= now; + diagFile /= logBaseName; diagFile.replace_extension(".jsonl"); std::error_code ec; std::filesystem::create_directories(diagFile.parent_path(), ec); @@ -149,8 +154,8 @@ void Log::configure() { for (const auto& problem : problems) { LOG_ERROR("{}", problem); } - LOG_INFO("Logging configured (binary: {}, text: {}, console: {})", binary.level, text.level, - console.level); + LOG_INFO("Logging configured (binary: {}, text: {}, console: {}, diagnostics: {})", binary.level, + text.level, console.level, diagnostics.level); initialized = true; flushImpl(); } @@ -163,6 +168,9 @@ void Log::flushImpl() { if (binary) { binary.output.flush(); } + if (diagnostics) { + diagnostics.output.flush(); + } } Log::LoggerConfiguration Log::getLoggerConfigurationImpl(std::string_view name) { diff --git a/swift/logging/SwiftLogging.h b/swift/logging/SwiftLogging.h index 8b41c05ca18..e07b46e245d 100644 --- a/swift/logging/SwiftLogging.h +++ b/swift/logging/SwiftLogging.h @@ -99,7 +99,7 @@ extern const std::string_view 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 -// matching logger names or one of `out:bin`, `out:text` or `out:console`. +// matching logger names or one of `out:binary`, `out:text`, `out:console` or `out:diagnostics`. // Output default levels can be seen in the corresponding initializers below. By default, all // loggers are configured with the lowest output level class Log {