Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8.0.0] Cherry-pick quiet mode (fix for #4867) to 8.0.0 #24024

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
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
  • Loading branch information
lberki committed Oct 17, 2024
commit 7f400aca561065357ad3dd339317cd4e331512db
9 changes: 8 additions & 1 deletion src/main/cpp/blaze.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
13 changes: 4 additions & 9 deletions src/main/cpp/blaze_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/main/cpp/blaze_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <string>
#include <vector>

#include "src/main/cpp/util/logging.h"
#include "src/main/cpp/util/path.h"

namespace blaze {
Expand Down Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions src/main/cpp/option_processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/cpp/startup_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions src/main/cpp/startup_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
125 changes: 58 additions & 67 deletions src/main/cpp/util/bazel_log_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,25 @@
#include <ctime>
#include <iostream>
#include <sstream>
#include <string>
#include <utility>

#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 {
Expand Down Expand Up @@ -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<LogLevel, std::string>(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<std::ostream> 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
31 changes: 20 additions & 11 deletions src/main/cpp/util/bazel_log_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#define BAZEL_SRC_MAIN_CPP_BAZEL_LOG_HANDLER_H_

#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "src/main/cpp/util/logging.h"

Expand All @@ -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<std::ostream> 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<std::stringstream> 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<std::pair<blaze_util::LogLevel, std::string>> user_messages_;
std::unique_ptr<std::stringstream> 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<std::ostream> owned_output_stream_;
};
} // namespace blaze_util

Expand Down
11 changes: 5 additions & 6 deletions src/main/cpp/util/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
// This file is based off the logging work by the protobuf team
#include "src/main/cpp/util/logging.h"

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <memory>

#include "src/main/cpp/util/exit_code.h"
#include "src/main/cpp/util/strings.h"

namespace blaze_util {

Expand Down Expand Up @@ -100,14 +98,15 @@ void SetLogHandler(std::unique_ptr<LogHandler> new_handler) {
internal::log_handler_ = std::move(new_handler);
}

void SetLoggingOutputStream(std::unique_ptr<std::ostream> 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();
}
}

Expand Down
Loading