From 7f400aca561065357ad3dd339317cd4e331512db Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 16 Oct 2024 23:19:40 -0700 Subject: [PATCH 1/2] Implement "quiet mode" This change adds a "--quiet" startup option, which causes Blaze not to print any status messages, progress messages, info messages or warnings of any kind. Error messages are still emitted as usual. Fixes #4867. RELNOTES[NEW]: The "blaze --quiet" command line option can now be used to make Blaze emit much less output. PiperOrigin-RevId: 686784300 Change-Id: Ibaa0b6a1788b43863337dce6fc16da09defb6724 --- src/main/cpp/blaze.cc | 9 +- src/main/cpp/blaze_util.cc | 13 +- src/main/cpp/blaze_util.h | 3 +- src/main/cpp/option_processor.cc | 7 + src/main/cpp/startup_options.cc | 2 + src/main/cpp/startup_options.h | 3 + src/main/cpp/util/bazel_log_handler.cc | 125 ++++++++---------- src/main/cpp/util/bazel_log_handler.h | 31 +++-- src/main/cpp/util/logging.cc | 11 +- src/main/cpp/util/logging.h | 27 +++- .../build/lib/runtime/UiEventHandler.java | 21 ++- .../devtools/build/lib/runtime/UiOptions.java | 8 ++ src/test/cpp/util/logging_test.cc | 90 ++++--------- src/test/shell/integration/ui_test.sh | 13 ++ 14 files changed, 195 insertions(+), 168 deletions(-) diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc index c59beb83996e2b..1f3d3ba0e468e1 100644 --- a/src/main/cpp/blaze.cc +++ b/src/main/cpp/blaze.cc @@ -1502,7 +1502,14 @@ int Main(int argc, const char *const *argv, WorkspaceLayout *workspace_layout, StartupOptions *startup_options = option_processor->GetParsedStartupOptions(); startup_options->MaybeLogStartupOptionWarnings(); - SetDebugLog(startup_options->client_debug); + if (startup_options->client_debug) { + SetDebugLog(blaze_util::LOGGINGDETAIL_DEBUG); + } else if (startup_options->quiet) { + SetDebugLog(blaze_util::LOGGINGDETAIL_QUIET); + } else { + SetDebugLog(blaze_util::LOGGINGDETAIL_USER); + } + // If client_debug was false, this is ignored, so it's accurate. BAZEL_LOG(INFO) << "Debug logging requested, sending all client log " "statements to stderr"; diff --git a/src/main/cpp/blaze_util.cc b/src/main/cpp/blaze_util.cc index 706c27d99de58e..d4bc67524d7df5 100644 --- a/src/main/cpp/blaze_util.cc +++ b/src/main/cpp/blaze_util.cc @@ -189,17 +189,12 @@ bool AwaitServerProcessTermination(int pid, const blaze_util::Path& output_base, return true; } -// For now, we don't have the client set up to log to a file. If --client_debug -// is passed, however, all BAZEL_LOG statements will be output to stderr. -// If/when we switch to logging these to a file, care will have to be taken to -// either log to both stderr and the file in the case of --client_debug, or be -// ok that these log lines will only go to one stream. -void SetDebugLog(bool enabled) { - if (enabled) { - blaze_util::SetLoggingOutputStreamToStderr(); +void SetDebugLog(blaze_util::LoggingDetail detail) { + if (detail == blaze_util::LOGGINGDETAIL_DEBUG) { + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, &std::cerr); absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo); } else { - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(detail, nullptr); // Disable absl debug logging, since that gets printed to stderr due to us // not setting up a log file. We don't use absl but one of our dependencies diff --git a/src/main/cpp/blaze_util.h b/src/main/cpp/blaze_util.h index 80b57c1bb4023b..78738b0d0c4a73 100644 --- a/src/main/cpp/blaze_util.h +++ b/src/main/cpp/blaze_util.h @@ -26,6 +26,7 @@ #include #include +#include "src/main/cpp/util/logging.h" #include "src/main/cpp/util/path.h" namespace blaze { @@ -92,7 +93,7 @@ extern const unsigned int kPostKillGracePeriodSeconds; // Control the output of debug information by debug_log. // Revisit once client logging is fixed (b/32939567). -void SetDebugLog(bool enabled); +void SetDebugLog(blaze_util::LoggingDetail detail); // Returns true if this Bazel instance is running inside of a Bazel test. // This method observes the TEST_TMPDIR envvar. diff --git a/src/main/cpp/option_processor.cc b/src/main/cpp/option_processor.cc index 9fb942277771fa..57b2eae6b954ba 100644 --- a/src/main/cpp/option_processor.cc +++ b/src/main/cpp/option_processor.cc @@ -514,6 +514,13 @@ blaze_exit_code::ExitCode OptionProcessor::ParseOptions( blazerc_and_env_command_args_ = GetBlazercAndEnvCommandArgs(cwd, rc_file_ptrs, GetProcessedEnv()); + // This is necessary because some code at Google both links in this code and + // needs to be ready for old versions of Bazel that don't support this + // argument yet. + if (startup_options_->quiet) { + blazerc_and_env_command_args_.push_back( + "--default_override=0:common=--quiet"); + } return blaze_exit_code::SUCCESS; } diff --git a/src/main/cpp/startup_options.cc b/src/main/cpp/startup_options.cc index fd90d73f65ca3e..a15cfe0593b4bb 100644 --- a/src/main/cpp/startup_options.cc +++ b/src/main/cpp/startup_options.cc @@ -85,6 +85,7 @@ StartupOptions::StartupOptions(const string &product_name, connect_timeout_secs(30), local_startup_timeout_secs(120), have_invocation_policy_(false), + quiet(false), client_debug(false), preemptible(false), java_logging_formatter( @@ -136,6 +137,7 @@ StartupOptions::StartupOptions(const string &product_name, RegisterNullaryStartupFlag("batch", &batch); RegisterNullaryStartupFlag("batch_cpu_scheduling", &batch_cpu_scheduling); RegisterNullaryStartupFlag("block_for_lock", &block_for_lock); + RegisterNullaryStartupFlag("quiet", &quiet); RegisterNullaryStartupFlag("client_debug", &client_debug); RegisterNullaryStartupFlag("preemptible", &preemptible); RegisterNullaryStartupFlag("fatal_event_bus_exceptions", diff --git a/src/main/cpp/startup_options.h b/src/main/cpp/startup_options.h index 416535f1393062..4d8fc6bca796ec 100644 --- a/src/main/cpp/startup_options.h +++ b/src/main/cpp/startup_options.h @@ -242,6 +242,9 @@ class StartupOptions { // Invocation policy can only be specified once. bool have_invocation_policy_; + // Whether to emit as little output as possible. + bool quiet; + // Whether to output addition debugging information in the client. bool client_debug; diff --git a/src/main/cpp/util/bazel_log_handler.cc b/src/main/cpp/util/bazel_log_handler.cc index bb43a36990c6e1..e8bc026a348db4 100644 --- a/src/main/cpp/util/bazel_log_handler.cc +++ b/src/main/cpp/util/bazel_log_handler.cc @@ -20,27 +20,25 @@ #include #include #include +#include +#include -#include "src/main/cpp/util/exit_code.h" -#include "src/main/cpp/util/file.h" #include "src/main/cpp/util/logging.h" namespace blaze_util { BazelLogHandler::BazelLogHandler() - : output_stream_set_(false), - logging_deactivated_(false), - user_buffer_stream_(new std::stringstream()), - debug_buffer_stream_(new std::stringstream()), - output_stream_(), - owned_output_stream_() {} + : debug_stream_(nullptr), + debug_stream_set_(false), + detail_(LOGGINGDETAIL_DEBUG), + debug_buffer_stream_(new std::stringstream()) {} BazelLogHandler::~BazelLogHandler() { - if (!logging_deactivated_) { + if (detail_ == LOGGINGDETAIL_DEBUG) { // If SetLoggingOutputStream was never called, dump the buffer to stderr, // otherwise, flush the stream. - if (output_stream_ != nullptr) { - output_stream_->flush(); + if (debug_stream_ != nullptr) { + debug_stream_->flush(); } else if (debug_buffer_stream_ != nullptr) { std::cerr << debug_buffer_stream_->rdbuf(); } else { @@ -94,101 +92,94 @@ void PrintDebugLevelMessageToStream(std::ostream* stream, void BazelLogHandler::HandleMessage(LogLevel level, const std::string& filename, int line, const std::string& message, int exit_code) { - if (logging_deactivated_) { - // If the output stream was explicitly deactivated, never print INFO - // messages, but messages of level USER and above should always be printed, - // as should warnings and errors. Omit the debug-level file and line number + if (detail_ != LOGGINGDETAIL_DEBUG) { + // If debugging was explicitly disabled, never print INFO messages, but + // messages of level USER and above should always be printed, as should + // warnings and errors. Omit the debug-level file and line number // information, though. - PrintUserLevelMessageToStream(&std::cerr, level, message); + LogLevel min_log_level = + detail_ == LOGGINGDETAIL_QUIET ? LOGLEVEL_ERROR : LOGLEVEL_USER; + if (level >= min_log_level) { + PrintUserLevelMessageToStream(&std::cerr, level, message); + } if (level == LOGLEVEL_FATAL) { std::exit(exit_code); } return; } - if (output_stream_ == nullptr) { + + if (debug_stream_ == nullptr) { // If we haven't decided whether messages should be logged to debug levels // or not, buffer each version. This is redundant for USER levels and above, // but is to make sure we can provide the right output to the user once we // know that they do or do not want debug level information. - PrintUserLevelMessageToStream(user_buffer_stream_.get(), level, message); + user_messages_.push_back(std::pair(level, message)); PrintDebugLevelMessageToStream(debug_buffer_stream_.get(), filename, line, level, message); } else { // If an output stream has been specifically set, it is for the full suite // of log messages. We don't print the user messages separately here as they // are included. - PrintDebugLevelMessageToStream(output_stream_, filename, line, level, + PrintDebugLevelMessageToStream(debug_stream_, filename, line, level, message); } // If we have a fatal message, exit with the provided error code. if (level == LOGLEVEL_FATAL) { - if (owned_output_stream_ != nullptr) { - // If this is is not being printed to stderr but to a custom stream, - // also print the error message to stderr. + if (debug_stream_ != nullptr) { PrintUserLevelMessageToStream(&std::cerr, level, message); } std::exit(exit_code); } } -void BazelLogHandler::SetOutputStreamToStderr() { +void BazelLogHandler::SetLoggingDetail(LoggingDetail detail, + std::ostream* debug_stream) { // Disallow second calls to this, we only intend to support setting the output // once, otherwise the buffering will not work as intended and the log will be // fragmented. - BAZEL_CHECK(!output_stream_set_) << "Tried to set log output a second time"; - output_stream_set_ = true; + BAZEL_CHECK(!debug_stream_set_) << "Tried to set log output a second time"; + debug_stream_set_ = true; + debug_stream_ = debug_stream; + detail_ = detail; + + if (detail == LOGGINGDETAIL_DEBUG) { + // The user asked for debug level information, which includes the user + // messages. We can discard the separate buffer at this point. + user_messages_.clear(); + FlushBufferToNewStreamAndSet(debug_buffer_stream_.get(), debug_stream_); + debug_buffer_stream_ = nullptr; + return; + } - FlushBufferToNewStreamAndSet(debug_buffer_stream_.get(), &std::cerr); debug_buffer_stream_ = nullptr; - // The user asked for debug level information, which includes the user - // messages. We can discard the separate buffer at this point. - user_buffer_stream_ = nullptr; -} + LogLevel min_log_level = + detail == LOGGINGDETAIL_QUIET ? LOGLEVEL_ERROR : LOGLEVEL_USER; -void BazelLogHandler::SetOutputStream( - std::unique_ptr new_output_stream) { - // Disallow second calls to this, we only intend to support setting the output - // once, otherwise the buffering will not work as intended and the log will be - // fragmented. - BAZEL_CHECK(!output_stream_set_) << "Tried to set log output a second time"; - output_stream_set_ = true; - - if (new_output_stream == nullptr) { - logging_deactivated_ = true; - // Flush the buffered user-level messages to stderr - these are messages - // that are meant for the user even when debug logging is not set. - FlushBufferToNewStreamAndSet(user_buffer_stream_.get(), &std::cerr); - - user_buffer_stream_ = nullptr; - // We discard the debug level logs, the user level ones were enough to - // inform the user and debug logging was not requested. - debug_buffer_stream_ = nullptr; - return; + for (const auto& log_entry : user_messages_) { + if (log_entry.first >= min_log_level) { + PrintUserLevelMessageToStream(&std::cerr, log_entry.first, + log_entry.second); + } } - owned_output_stream_ = std::move(new_output_stream); - if (owned_output_stream_->fail()) { - // If opening the stream failed, continue buffering and have the logs - // dump to stderr at shutdown. - BAZEL_LOG(ERROR) << "Provided stream failed."; - return; +} + +void BazelLogHandler::Close() { + if (debug_stream_ != nullptr) { + debug_stream_->flush(); } - FlushBufferToNewStreamAndSet(debug_buffer_stream_.get(), - owned_output_stream_.get()); - debug_buffer_stream_ = nullptr; - // The user asked for debug level information, which includes the user - // messages. We can discard the separate buffer at this point. - user_buffer_stream_ = nullptr; + + debug_stream_ = nullptr; } void BazelLogHandler::FlushBufferToNewStreamAndSet( - std::stringstream* buffer, std::ostream* new_output_stream) { + std::stringstream* buffer, std::ostream* new_debug_stream) { // Flush the buffer to the new stream, and print new log lines to it. - output_stream_ = new_output_stream; - // Transfer the contents of the buffer to the new stream, then remove the - // buffer. - (*output_stream_) << buffer->str(); - output_stream_->flush(); + debug_stream_ = new_debug_stream; + // Transfer the contents of the buffer to the new stream, then remove the + // buffer. + *debug_stream_ << buffer->str(); + debug_stream_->flush(); } } // namespace blaze_util diff --git a/src/main/cpp/util/bazel_log_handler.h b/src/main/cpp/util/bazel_log_handler.h index 3ca8f56486c882..bc8618d1bc2ba7 100644 --- a/src/main/cpp/util/bazel_log_handler.h +++ b/src/main/cpp/util/bazel_log_handler.h @@ -16,6 +16,11 @@ #define BAZEL_SRC_MAIN_CPP_BAZEL_LOG_HANDLER_H_ #include +#include +#include +#include +#include +#include #include "src/main/cpp/util/logging.h" @@ -34,22 +39,26 @@ class BazelLogHandler : public blaze_util::LogHandler { void HandleMessage(blaze_util::LogLevel level, const std::string& filename, int line, const std::string& message, int exit_code) override; - void SetOutputStream( - std::unique_ptr new_output_stream) override; - void SetOutputStreamToStderr() override; + void SetLoggingDetail(blaze_util::LoggingDetail detail, + std::ostream* stream) override; + void Close() override; private: void FlushBufferToNewStreamAndSet(std::stringstream* buffer, std::ostream* new_output_stream); - bool output_stream_set_; - bool logging_deactivated_; - std::unique_ptr user_buffer_stream_; + + // The stream to which debug logs are sent (if logging detail is not + // LOGGINGDETAIL_DEBUG, everything goes to stderr) + std::ostream* debug_stream_; + bool debug_stream_set_; + LoggingDetail detail_; + + // Buffers for messages received before the logging detail was determined. + // non-debug messages are buffered alongside their log level so that we can + // use the log level to filter them based on the eventual logging detail, + // debug messages are simply buffered as a stream. + std::vector> user_messages_; std::unique_ptr debug_buffer_stream_; - // The actual output_stream to which all logs will be sent. - std::ostream* output_stream_; - // A unique pts to the output_stream, if we need to keep ownership of the - // stream. In the case of stderr logging, this is null. - std::unique_ptr owned_output_stream_; }; } // namespace blaze_util diff --git a/src/main/cpp/util/logging.cc b/src/main/cpp/util/logging.cc index edf1b18749d86c..93b251afab8567 100644 --- a/src/main/cpp/util/logging.cc +++ b/src/main/cpp/util/logging.cc @@ -15,13 +15,11 @@ // This file is based off the logging work by the protobuf team #include "src/main/cpp/util/logging.h" -#include #include #include #include #include "src/main/cpp/util/exit_code.h" -#include "src/main/cpp/util/strings.h" namespace blaze_util { @@ -100,14 +98,15 @@ void SetLogHandler(std::unique_ptr new_handler) { internal::log_handler_ = std::move(new_handler); } -void SetLoggingOutputStream(std::unique_ptr output_stream) { +void SetLoggingDetail(LoggingDetail detail, std::ostream* debug_stream) { if (internal::log_handler_ != nullptr) { - internal::log_handler_->SetOutputStream(std::move(output_stream)); + internal::log_handler_->SetLoggingDetail(detail, debug_stream); } } -void SetLoggingOutputStreamToStderr() { + +void CloseLogging() { if (internal::log_handler_ != nullptr) { - internal::log_handler_->SetOutputStreamToStderr(); + internal::log_handler_->Close(); } } diff --git a/src/main/cpp/util/logging.h b/src/main/cpp/util/logging.h index b2cd459d06c639..aa0e2da7273045 100644 --- a/src/main/cpp/util/logging.h +++ b/src/main/cpp/util/logging.h @@ -14,6 +14,7 @@ #ifndef BAZEL_SRC_MAIN_CPP_LOGGING_H_ #define BAZEL_SRC_MAIN_CPP_LOGGING_H_ +#include #include #include #include @@ -145,6 +146,13 @@ inline bool IsOk(bool status) { #endif // !NDEBUG +// How much to print on the terminal. +enum LoggingDetail { + LOGGINGDETAIL_QUIET, // Only errors + LOGGINGDETAIL_USER, // Messages intended for the user (level USER and above) + LOGGINGDETAIL_DEBUG // Debug logging +}; + class LogHandler { public: virtual ~LogHandler() {} @@ -152,8 +160,12 @@ class LogHandler { int line, const std::string& message, int exit_code) = 0; - virtual void SetOutputStream(std::unique_ptr output_stream) = 0; - virtual void SetOutputStreamToStderr() = 0; + // See ::SetLoggingDetail() + virtual void SetLoggingDetail(LoggingDetail detail, + std::ostream* debug_stream) = 0; + + // See ::CloseLogging() + virtual void Close() = 0; }; // Sets the log handler that routes all log messages. @@ -161,9 +173,14 @@ class LogHandler { // at initialization time, and probably not from library code. void SetLogHandler(std::unique_ptr new_handler); -// Set the stream to which all log statements will be sent. -void SetLoggingOutputStream(std::unique_ptr output_stream); -void SetLoggingOutputStreamToStderr(); +// Sets the logging detail for the currently set log handler. Prints the log +// messages to `debug_stream` if not null. It doesn't affect non-debug messages +// and is only used for testing. +void SetLoggingDetail(LoggingDetail detail, std::ostream* debug_stream); + +// Closes the logging. Buffers are flushed and no more log messages will be +// printed. +void CloseLogging(); } // namespace blaze_util diff --git a/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java index cdd6aead6a0bd7..d74d8bf1970a4c 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java @@ -100,6 +100,7 @@ public final class UiEventHandler implements EventHandler { DateTimeFormatter.ofPattern("(HH:mm:ss) "); private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + private final boolean quiet; private final boolean cursorControl; private final Clock clock; private final EventBus eventBus; @@ -176,6 +177,7 @@ public UiEventHandler( OutErr.create( new FullyBufferedOutputStream(outErr.getOutputStream()), new FullyBufferedOutputStream(outErr.getErrorStream())); + this.quiet = options.quiet; this.cursorControl = options.useCursorControl(); this.terminal = new AnsiTerminal(this.outErr.getErrorStream()); this.showProgress = options.showProgress; @@ -424,7 +426,20 @@ private byte[] getContentIfSmallEnough( } private void handleInternal(Event event) { - if (filteredEventKinds.contains(event.getKind())) { + EventKind eventKind = event.getKind(); + if (quiet) { + switch (eventKind) { + case ERROR -> {} + case FATAL -> {} + case STDOUT -> {} + case STDERR -> {} + default -> { + return; + } + } + } + + if (filteredEventKinds.contains(eventKind)) { return; } try { @@ -1032,6 +1047,10 @@ private void crlf() throws IOException { } private synchronized void addProgressBar() throws IOException { + if (quiet) { + return; + } + LineCountingAnsiTerminalWriter countingTerminalWriter = new LineCountingAnsiTerminalWriter(terminal); AnsiTerminalWriter terminalWriter = countingTerminalWriter; diff --git a/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java index ca6e8ebef8fd34..d8e914360ec4b7 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/UiOptions.java @@ -127,6 +127,14 @@ public UseCursesConverter() { } } + @Option( + name = "quiet", + defaultValue = "false", + documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, + effectTags = {OptionEffectTag.UNKNOWN}, + help = "If set, Bazel prints as little output as possible.") + public boolean quiet; + @Option( name = "show_progress", defaultValue = "true", diff --git a/src/test/cpp/util/logging_test.cc b/src/test/cpp/util/logging_test.cc index eb6d1332daffc2..b056aefe75ba10 100644 --- a/src/test/cpp/util/logging_test.cc +++ b/src/test/cpp/util/logging_test.cc @@ -143,7 +143,7 @@ TEST(LoggingTest, BazelLogHandler_DoesNotDumpToStderrIfOuputStreamSetToNull) { // Log something. std::string teststring = "test that this log message is lost."; BAZEL_LOG(INFO) << teststring; - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); // Destruct the log handler and check if stderr got anything. blaze_util::SetLogHandler(nullptr); @@ -157,7 +157,7 @@ TEST(LoggingTest, BazelLogHandler_DoesNotPrintInfoLogsIfOuputStreamSetToNull) { std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); std::string teststring = "test that the log message is lost."; BAZEL_LOG(INFO) << teststring; @@ -172,7 +172,7 @@ TEST(LoggingTest, BazelLogHandler_PrintsUserLogsEvenIfOuputStreamSetToNull) { std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); std::string teststring = "some user message"; BAZEL_LOG(USER) << teststring; @@ -187,7 +187,7 @@ TEST(LoggingTest, BazelLogHandler_PrintsWarningsEvenIfOuputStreamSetToNull) { std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); BAZEL_LOG(WARNING) << "this is a warning"; std::string expectedWarning = "WARNING: this is a warning"; @@ -202,7 +202,7 @@ TEST(LoggingTest, BazelLogHandler_PrintsErrorsEvenIfOuputStreamSetToNull) { std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); BAZEL_LOG(ERROR) << "this is an error, alert!"; std::string expectedError = "ERROR: this is an error, alert!"; @@ -224,7 +224,7 @@ TEST(LoggingTest, BAZEL_LOG(INFO) << teststring; // Ask that the debug logs not be kept. - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); // Set a null log handler, which causes the BazelLogHandler to be destructed. // This prompts its logs to be flushed, so we can capture them. @@ -248,7 +248,7 @@ TEST(LoggingTest, "WARNING: test that this message gets directed to cerr"; // Ask that the debug logs not be kept. - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(LOGGINGDETAIL_USER, nullptr); // Set a null log handler, which causes the BazelLogHandler to be destructed. // This prompts its logs to be flushed, so we can capture them. @@ -270,10 +270,11 @@ TEST(LoggingTest, BazelLogHandler_DirectingLogsToBufferStreamWorks) { // check its contents) std::unique_ptr stringbuf(new std::stringstream()); std::stringstream* stringbuf_ptr = stringbuf.get(); - blaze_util::SetLoggingOutputStream(std::move(stringbuf)); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, stringbuf_ptr); std::string teststring = "testing log getting directed to a stringbuffer."; BAZEL_LOG(INFO) << teststring; + blaze_util::CloseLogging(); // Check that output went to the buffer. std::string output(stringbuf_ptr->str()); @@ -304,7 +305,8 @@ TEST(LoggingTest, BazelLogHandler_BufferedLogsSentToSpecifiedStream) { // check its contents) std::unique_ptr stringbuf(new std::stringstream()); std::stringstream* stringbuf_ptr = stringbuf.get(); - blaze_util::SetLoggingOutputStream(std::move(stringbuf)); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, stringbuf_ptr); + blaze_util::CloseLogging(); // Check that the buffered logs were sent. std::string output(stringbuf_ptr->str()); @@ -328,10 +330,11 @@ TEST(LoggingTest, BazelLogHandler_WarningsSentToBufferStream) { // check its contents) std::unique_ptr stringbuf(new std::stringstream()); std::stringstream* stringbuf_ptr = stringbuf.get(); - blaze_util::SetLoggingOutputStream(std::move(stringbuf)); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, stringbuf_ptr); std::string teststring = "test warning"; BAZEL_LOG(WARNING) << teststring; + blaze_util::CloseLogging(); // Check that output went to the buffer. std::string output(stringbuf_ptr->str()); @@ -353,10 +356,11 @@ TEST(LoggingTest, BazelLogHandler_ErrorsSentToBufferStream) { // check its contents) std::unique_ptr stringbuf(new std::stringstream()); std::stringstream* stringbuf_ptr = stringbuf.get(); - blaze_util::SetLoggingOutputStream(std::move(stringbuf)); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, stringbuf_ptr); std::string teststring = "test error"; BAZEL_LOG(ERROR) << teststring; + blaze_util::CloseLogging(); // Check that output went to the buffer. std::string output(stringbuf_ptr->str()); @@ -367,26 +371,6 @@ TEST(LoggingTest, BazelLogHandler_ErrorsSentToBufferStream) { EXPECT_THAT(stderr_output, Not(HasSubstr(teststring))); } -TEST(LoggingTest, BazelLogHandler_ImpossibleFile) { - // Set up logging and be prepared to capture stderr at destruction. - testing::internal::CaptureStderr(); - std::unique_ptr handler( - new blaze_util::BazelLogHandler()); - blaze_util::SetLogHandler(std::move(handler)); - - // Deliberately try to log to an impossible location, check that we error out. - std::unique_ptr bad_logfile_stream_( - new std::ofstream("/this/doesnt/exist.log", std::fstream::out)); - blaze_util::SetLoggingOutputStream(std::move(bad_logfile_stream_)); - - // Set a null log handler, which causes the BazelLogHandler to be destructed. - // This prompts its logs to be flushed, so we can capture them.. - blaze_util::SetLogHandler(nullptr); - std::string stderr_output = testing::internal::GetCapturedStderr(); - EXPECT_THAT(stderr_output, - MatchesRegex(".ERROR.* Provided stream failed.\n")); -} - // Tests for the BazelLogHandler & SetLoggingOutputStreamToStderr TEST(LoggingTest, BazelLogHandler_DirectingLogsToCerrWorks) { @@ -397,7 +381,7 @@ TEST(LoggingTest, BazelLogHandler_DirectingLogsToCerrWorks) { blaze_util::SetLogHandler(std::move(handler)); // Ask that the logs get output to stderr - blaze_util::SetLoggingOutputStreamToStderr(); + blaze_util::SetLoggingDetail(LOGGINGDETAIL_DEBUG, &std::cerr); // Log something. std::string teststring = "test that the log messages get directed to cerr"; @@ -422,7 +406,7 @@ TEST(LoggingTest, BazelLogHandler_BufferedLogsGetDirectedToCerr) { BAZEL_LOG(INFO) << teststring; // Ask that the logs get output to stderr - blaze_util::SetLoggingOutputStreamToStderr(); + blaze_util::SetLoggingDetail(LOGGINGDETAIL_DEBUG, &std::cerr); // Set a null log handler, which causes the BazelLogHandler to be destructed. // This prompts its logs to be flushed, so we can capture them. @@ -463,7 +447,7 @@ TEST(LoggingDeathTest, std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); BAZEL_LOG(FATAL) << "something's wrong!"; }, @@ -477,7 +461,8 @@ TEST(LoggingDeathTest, std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStreamToStderr(); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, + &std::cerr); BAZEL_LOG(FATAL) << "something's wrong!"; }, ::testing::ExitedWithCode(37), "\\[FATAL .*\\] something's wrong!"); @@ -508,7 +493,7 @@ TEST(LoggingDeathTest, std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStream(nullptr); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_USER, nullptr); BAZEL_DIE(42) << "dying with exit code 42."; }, ::testing::ExitedWithCode(42), "FATAL: dying with exit code 42."); @@ -520,42 +505,13 @@ TEST(LoggingDeathTest, BazelLogHandler_Stderr_BazelDieDiesWithCustomExitCode) { std::unique_ptr handler( new blaze_util::BazelLogHandler()); blaze_util::SetLogHandler(std::move(handler)); - blaze_util::SetLoggingOutputStreamToStderr(); + blaze_util::SetLoggingDetail(blaze_util::LOGGINGDETAIL_DEBUG, + &std::cerr); BAZEL_DIE(42) << "dying with exit code 42."; }, ::testing::ExitedWithCode(42), "\\[FATAL .*\\] dying with exit code 42."); } -TEST(LoggingDeathTest, - BazelLogHandler_CustomStream_BazelDiePrintsToStderrAndCustomStream) { - std::string logfile = - blaze_util::JoinPath(blaze::GetPathEnv("TEST_TMPDIR"), "logfile"); - - ASSERT_EXIT( - { - std::unique_ptr handler( - new blaze_util::BazelLogHandler()); - blaze_util::SetLogHandler(std::move(handler)); - - // Ask that the logs get output to a file (the string buffer setup used - // in the non-death tests doesn't work here.) - std::unique_ptr logfile_stream_( - new std::ofstream(logfile, std::fstream::out)); - blaze_util::SetLoggingOutputStream(std::move(logfile_stream_)); - - BAZEL_DIE(42) << "dying with exit code 42."; - }, - ::testing::ExitedWithCode(42), "FATAL: dying with exit code 42."); - // Check that the error is also in the custom stream. - std::string output; - ASSERT_TRUE(blaze_util::ReadFile(logfile, &output)); - // Unlike in earlier tests, this string is read from a file, and since Windows - // uses the newline '\r\n', compared to the linux \n, we prefer to keep the - // test simple and not test the end of the line explicitly. - EXPECT_THAT(output, - ContainsRegex("\\[FATAL .*\\] dying with exit code 42.")); -} - #endif // GTEST_HAS_DEATH_TEST } // namespace blaze_util diff --git a/src/test/shell/integration/ui_test.sh b/src/test/shell/integration/ui_test.sh index 922746b8e14adc..96ce4d4c26d388 100755 --- a/src/test/shell/integration/ui_test.sh +++ b/src/test/shell/integration/ui_test.sh @@ -748,4 +748,17 @@ function test_exit_code_reported() { expect_log '//pkg:false (Exit 1) (see' } +function test_quiet_mode() { + mkdir -p foo + cat > foo/BUILD <<'EOF' +genrule(name="g", srcs=[], outs=["go"], cmd="echo GO > $@") +EOF + + bazel shutdown + bazel --quiet build &> "$TEST_log" || fail "build failed" + expect_not_log "and connecting to it" + expect_not_log "Analyzed" + expect_not_log "Build completed successfully" + +} run_suite "Integration tests for ${PRODUCT_NAME}'s UI" From 7d680b69b202a33951a4f2061976fd2d1edc7bc6 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 17 Oct 2024 01:42:42 -0700 Subject: [PATCH 2/2] Add documentation for the --quiet startup option. Finishing touches for #4867. RELNOTES: None. PiperOrigin-RevId: 686819148 Change-Id: I9ff2424683b8579ad5a953f7974c9579c5e715db --- .../build/lib/runtime/BlazeServerStartupOptions.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java index fd5150f380e870..4a43a9fccc50b9 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java @@ -378,6 +378,16 @@ public String getTypeDescription() { + "cause the server to restart.") public boolean clientDebug; + @Option( + name = "quiet", + defaultValue = "false", // NOTE: only for documentation, actual flag is in UiOptions + documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS, + effectTags = {OptionEffectTag.AFFECTS_OUTPUTS, OptionEffectTag.BAZEL_MONITORING}, + help = + "If true, no informational messages are emitted on the console, only errors. Changing " + + "this option will not cause the server to restart.") + public boolean quiet; + @Option( name = "preemptible", defaultValue = "false", // NOTE: only for documentation, value is set and used by the client.