diff options
author | 2017-04-12 17:25:09 +0000 | |
---|---|---|
committer | 2017-04-13 09:36:48 +0200 | |
commit | 2d5d17b221574583f3503fe536c7240c168311da (patch) | |
tree | 8af68712b9aa8e0e3b7450106b0f5cb9ca351c60 /src/main/java | |
parent | 7d0bcf93e518065f0458aa215db9487e25e1be4a (diff) |
Add a custom single-line formatter for java.log.
This logger makes it easier to parse log statements and is now enabled for Bazel's java.log.
RELNOTES[INC]: Bazel now prints logs in single lines to java.log
PiperOrigin-RevId: 152954337
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/BUILD | 11 | ||||
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/util/SingleLineFormatter.java | 87 |
2 files changed, 98 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index cd90d661d8..51b444d586 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -275,6 +275,15 @@ java_library( ) java_library( + name = "single-line-formatter", + srcs = ["util/SingleLineFormatter.java"], + deps = [ + "//third_party:guava", + "//third_party:joda_time", + ], +) + +java_library( name = "util", srcs = glob( ["util/*.java"], @@ -286,6 +295,7 @@ java_library( "util/OS.java", "util/Preconditions.java", "util/ProcessUtils.java", + "util/SingleLineFormatter.java", "util/StringCanonicalizer.java", "util/StringTrie.java", "util/VarInt.java", @@ -1192,6 +1202,7 @@ java_binary( main_class = "com.google.devtools.build.lib.bazel.BazelMain", runtime_deps = [ ":bazel-main", + ":single-line-formatter", # See startup_options.cc ], ) diff --git a/src/main/java/com/google/devtools/build/lib/util/SingleLineFormatter.java b/src/main/java/com/google/devtools/build/lib/util/SingleLineFormatter.java new file mode 100644 index 0000000000..6748917bdc --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/util/SingleLineFormatter.java @@ -0,0 +1,87 @@ +// Copyright 2017 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.util; + +import com.google.common.collect.ImmutableRangeMap; +import com.google.common.collect.Range; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +/** + * Formatter to write java.util.logging messages out in single-line format. + * + * <p>Log entries contain the date and time (in UTC), log level (as letter and numerical value), + * source location, thread ID, message and, if applicable, a stack trace. + */ +public class SingleLineFormatter extends Formatter { + + /** Single-character codes based on {@link Level}s. */ + private static final ImmutableRangeMap<Integer, Character> CODES_BY_LEVEL = + ImmutableRangeMap.<Integer, Character>builder() + .put(Range.atMost(Level.FINE.intValue()), 'D') + .put(Range.open(Level.FINE.intValue(), Level.WARNING.intValue()), 'I') + .put(Range.closedOpen(Level.WARNING.intValue(), Level.SEVERE.intValue()), 'W') + .put(Range.atLeast(Level.SEVERE.intValue()), 'X') + .build(); + + /** A thread safe, immutable formatter that can be used by all without contention. */ + private static final DateTimeFormatter DATE_TIME_FORMAT = + DateTimeFormat.forPattern("yyMMdd HH:mm:ss.SSS").withZoneUTC(); + + @Override + public String format(LogRecord rec) { + StringBuilder buf = new StringBuilder(); + + // Timestamp + buf.append(DATE_TIME_FORMAT.print(rec.getMillis())) + .append(':'); + + // One character code for level + buf.append(CODES_BY_LEVEL.get(rec.getLevel().intValue())); + + // The stack trace, if any + Throwable thrown = rec.getThrown(); + if (thrown != null) { + buf.append('T'); + } + + buf.append(' '); + + // Information about the source of the exception + buf.append(rec.getThreadID()) + .append(" [") + .append(rec.getSourceClassName()) + .append('.') + .append(rec.getSourceMethodName()) + .append("] "); + + // The actual message + buf.append(formatMessage(rec)).append('\n'); + + if (thrown != null) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + thrown.printStackTrace(pw); + pw.flush(); + buf.append(sw.toString()); + } + + return buf.toString(); + } +} |