Switch to SimpleLogHandler in Bazel.
The new log handler changes java.log to a symlink to the latest log file. Old
log files will be garbage collected to keep the total size under a limit.
As a temporary "escape hatch", in case switching server log handlers causes
problems, the old non-rotating log handler can be restored using the
--norotating_server_log startup option. This option (and the
BazelServerLogModule providing it) will be removed once it's clear that an
"escape hatch" is not needed.
RELNOTES: Use different server log files per Bazel server process; java.log is
now a symlink to the latest log.
PiperOrigin-RevId: 219512757
diff --git a/src/main/cpp/startup_options.cc b/src/main/cpp/startup_options.cc
index 21f7045..1267384 100644
--- a/src/main/cpp/startup_options.cc
+++ b/src/main/cpp/startup_options.cc
@@ -84,6 +84,7 @@
oom_more_eagerly(false),
oom_more_eagerly_threshold(100),
write_command_log(true),
+ rotating_server_log(true),
watchfs(false),
fatal_event_bus_exceptions(false),
command_port(0),
@@ -142,6 +143,7 @@
RegisterNullaryStartupFlag("unlimit_coredumps");
RegisterNullaryStartupFlag("watchfs");
RegisterNullaryStartupFlag("write_command_log");
+ RegisterNullaryStartupFlag("rotating_server_log");
RegisterUnaryStartupFlag("command_port");
RegisterUnaryStartupFlag("connect_timeout_secs");
RegisterUnaryStartupFlag("digest_function");
@@ -322,6 +324,12 @@
} else if (GetNullaryOption(arg, "--nowrite_command_log")) {
write_command_log = false;
option_sources["write_command_log"] = rcfile;
+ } else if (GetNullaryOption(arg, "--rotating_server_log")) {
+ rotating_server_log = true;
+ option_sources["rotating_server_log"] = rcfile;
+ } else if (GetNullaryOption(arg, "--norotating_server_log")) {
+ rotating_server_log = false;
+ option_sources["rotating_server_log"] = rcfile;
} else if (GetNullaryOption(arg, "--watchfs")) {
watchfs = true;
option_sources["watchfs"] = rcfile;
@@ -542,29 +550,58 @@
return AddJVMMemoryArguments(server_javabase, result, user_options, error);
}
+static std::string GetJavaUtilLoggingFileHandlerProps(
+ const std::string &java_log, const std::string &java_logging_formatter) {
+ return "handlers=java.util.logging.FileHandler\n"
+ ".level=INFO\n"
+ "java.util.logging.FileHandler.level=INFO\n"
+ "java.util.logging.FileHandler.pattern=" +
+ java_log +
+ "\n"
+ "java.util.logging.FileHandler.limit=1024000\n"
+ "java.util.logging.FileHandler.count=1\n"
+ "java.util.logging.FileHandler.formatter=" +
+ java_logging_formatter + "\n";
+}
+
+static std::string GetSimpleLogHandlerProps(
+ const std::string &java_log, const std::string &java_logging_formatter) {
+ return "handlers=com.google.devtools.build.lib.util.SimpleLogHandler\n"
+ ".level=INFO\n"
+ "com.google.devtools.build.lib.util.SimpleLogHandler.level=INFO\n"
+ "com.google.devtools.build.lib.util.SimpleLogHandler.prefix=" +
+ java_log +
+ "\n"
+ "com.google.devtools.build.lib.util.SimpleLogHandler.limit=1024000\n"
+ "com.google.devtools.build.lib.util.SimpleLogHandler.total_limit="
+ "20971520\n" // 20 MB.
+ "com.google.devtools.build.lib.util.SimpleLogHandler.formatter=" +
+ java_logging_formatter + "\n";
+}
+
void StartupOptions::AddJVMLoggingArguments(std::vector<string> *result) const {
// Configure logging
const string propFile = blaze_util::PathAsJvmFlag(
blaze_util::JoinPath(output_base, "javalog.properties"));
const string java_log(
blaze_util::PathAsJvmFlag(blaze_util::JoinPath(output_base, "java.log")));
- if (!blaze_util::WriteFile("handlers=java.util.logging.FileHandler\n"
- ".level=INFO\n"
- "java.util.logging.FileHandler.level=INFO\n"
- "java.util.logging.FileHandler.pattern=" +
- java_log +
- "\n"
- "java.util.logging.FileHandler.limit=1024000\n"
- "java.util.logging.FileHandler.count=1\n"
- "java.util.logging.FileHandler.formatter=" +
- java_logging_formatter + "\n",
- propFile)) {
+ const std::string loggingProps =
+ rotating_server_log
+ ? GetSimpleLogHandlerProps(java_log, java_logging_formatter)
+ : GetJavaUtilLoggingFileHandlerProps(java_log,
+ java_logging_formatter);
+ const std::string loggingQuerierClass =
+ rotating_server_log
+ ? "com.google.devtools.build.lib.util.SimpleLogHandler$HandlerQuerier"
+ : "com.google.devtools.build.lib.util.FileHandlerQuerier";
+
+ if (!blaze_util::WriteFile(loggingProps, propFile)) {
perror(("Couldn't write logging file " + propFile).c_str());
} else {
result->push_back("-Djava.util.logging.config.file=" + propFile);
result->push_back(
- "-Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class="
- "com.google.devtools.build.lib.util.FileHandlerQuerier");
+ "-Dcom.google.devtools.build.lib.util.LogHandlerQuerier.class=" +
+ loggingQuerierClass);
}
}
diff --git a/src/main/cpp/startup_options.h b/src/main/cpp/startup_options.h
index 10492b7..fe90a9e 100644
--- a/src/main/cpp/startup_options.h
+++ b/src/main/cpp/startup_options.h
@@ -257,6 +257,15 @@
bool write_command_log;
+ // If true, Bazel will use SimpleLogHandler for the server log, meaning that
+ // each time a Bazel server process starts, it will create a new log file and
+ // update java.log to be a symbolic link to the new log file.
+ // TODO(b/118755753): The --norotating_server_log option is intended as a
+ // temporary "escape hatch" in case switching to the rotating ServerLogHandler
+ // breaks things. Remove the option and associated logic once we are confident
+ // that the "escape hatch" is not needed.
+ bool rotating_server_log;
+
// If true, Blaze will listen to OS-level file change notifications.
bool watchfs;
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 2321003..3f6c331 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -1505,6 +1505,7 @@
":bazel-main",
":server",
":single-line-formatter", # See startup_options.cc
+ "//src/main/java/com/google/devtools/build/lib:simple-log-handler", # See startup_options.cc
],
)
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java b/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
index 96fa9a8..029c1ac 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/Bazel.java
@@ -61,6 +61,7 @@
com.google.devtools.build.lib.profiler.callcounts.CallcountsModule.class,
com.google.devtools.build.lib.profiler.memory.AllocationTrackerModule.class,
com.google.devtools.build.lib.metrics.MetricsModule.class,
+ com.google.devtools.build.lib.bazel.BazelServerLogModule.class,
BazelBuiltinCommandModule.class);
public static void main(String[] args) {
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelServerLogModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelServerLogModule.java
new file mode 100644
index 0000000..80ff7d5
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelServerLogModule.java
@@ -0,0 +1,47 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.runtime.BlazeModule;
+import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionDocumentationCategory;
+import com.google.devtools.common.options.OptionEffectTag;
+import com.google.devtools.common.options.OptionsBase;
+
+/** Provides startup options for the Bazel server log handler. */
+public class BazelServerLogModule extends BlazeModule {
+ /** Logging flags. */
+ public static final class Options extends OptionsBase {
+ // TODO(b/118755753): The --norotating_server_log option is intended as a temporary "escape
+ // hatch" in case switching to the rotating ServerLogHandler breaks things. Remove the option
+ // and associated logic once we are confident that the "escape hatch" is not needed.
+ @Option(
+ name = "rotating_server_log",
+ defaultValue = "true", // NOTE: purely decorative, rc files are read by the client.
+ documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS,
+ effectTags = {OptionEffectTag.BAZEL_MONITORING},
+ help =
+ "Create a new log file when the %{product} server process (re)starts, and update the "
+ + "java.log symbolic link to point to the new file. Otherwise, java.log would be a "
+ + "regular file which would be overwritten each time the server process starts.")
+ public boolean rotatingServerLog;
+ }
+
+ @Override
+ public Iterable<Class<? extends OptionsBase>> getStartupOptions() {
+ return ImmutableList.of(Options.class);
+ }
+}