Merge changes I238c2692,I365109d3,I3a2bdba5

* changes:
  Respect enableReverseDnsLookup option in ErrorLogJsonLayout
  Use ISO 8601 timestamp format for error/httpd/sshd logs
  Do not use jsonevent-layout for error logs in JSON format
This commit is contained in:
Thomas Dräbing
2020-03-11 08:58:52 +00:00
committed by Gerrit Code Review
12 changed files with 213 additions and 133 deletions

View File

@@ -26,16 +26,10 @@ import static com.google.gerrit.pgm.http.jetty.HttpLog.P_USER_AGENT;
import com.google.gerrit.util.logging.JsonLayout;
import com.google.gerrit.util.logging.JsonLogEntry;
import java.time.format.DateTimeFormatter;
import org.apache.log4j.spi.LoggingEvent;
public class HttpLogJsonLayout extends JsonLayout {
@Override
public DateTimeFormatter createDateTimeFormatter() {
return DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss,SSS Z");
}
@Override
public JsonLogEntry toJsonLogEntry(LoggingEvent event) {
return new HttpJsonLogEntry(event);
@@ -59,7 +53,7 @@ public class HttpLogJsonLayout extends JsonLayout {
this.host = getMdcString(event, P_HOST);
this.thread = event.getThreadName();
this.user = getMdcString(event, P_USER);
this.timestamp = formatDate(event.getTimeStamp());
this.timestamp = timestampFormatter.format(event.getTimeStamp());
this.method = getMdcString(event, P_METHOD);
this.resource = getMdcString(event, P_RESOURCE);
this.protocol = getMdcString(event, P_PROTOCOL);

View File

@@ -14,24 +14,15 @@
package com.google.gerrit.pgm.http.jetty;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import com.google.gerrit.util.logging.LogTimestampFormatter;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.LoggingEvent;
public final class HttpLogLayout extends Layout {
private final SimpleDateFormat dateFormat;
private long lastTimeMillis;
private String lastTimeString;
private final LogTimestampFormatter timestampFormatter;
public HttpLogLayout() {
final TimeZone tz = TimeZone.getDefault();
dateFormat = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z");
dateFormat.setTimeZone(tz);
lastTimeMillis = System.currentTimeMillis();
lastTimeString = dateFormat.format(new Date(lastTimeMillis));
timestampFormatter = new LogTimestampFormatter();
}
@Override
@@ -53,7 +44,7 @@ public final class HttpLogLayout extends Layout {
buf.append(' ');
buf.append('[');
formatDate(event.getTimeStamp(), buf);
buf.append(timestampFormatter.format(event.getTimeStamp()));
buf.append(']');
buf.append(' ');
@@ -104,19 +95,6 @@ public final class HttpLogLayout extends Layout {
}
}
private void formatDate(long now, StringBuilder sbuf) {
final long rounded = now - (int) (now % 1000);
if (rounded != lastTimeMillis) {
synchronized (dateFormat) {
lastTimeMillis = rounded;
lastTimeString = dateFormat.format(new Date(lastTimeMillis));
sbuf.append(lastTimeString);
}
} else {
sbuf.append(lastTimeString);
}
}
@Override
public boolean ignoresThrowable() {
return true;

View File

@@ -17,12 +17,13 @@ java_library(
"//java/com/google/gerrit/server/restapi",
"//java/com/google/gerrit/server/schema",
"//java/com/google/gerrit/util/cli",
"//java/com/google/gerrit/util/logging",
"//lib:args4j",
"//lib:gson",
"//lib:guava",
"//lib:jgit",
"//lib/flogger:api",
"//lib/guice",
"//lib/log:jsonevent-layout",
"//lib/log:log4j",
],
)

View File

@@ -18,9 +18,9 @@ import com.google.gerrit.common.FileUtil;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.util.SystemLog;
import com.google.gerrit.util.logging.LogTimestampFormatter;
import java.io.IOException;
import java.nio.file.Path;
import net.logstash.log4j.JSONEventLayoutV1;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
@@ -78,13 +78,22 @@ public class ErrorLogFile {
if (text) {
root.addAppender(
SystemLog.createAppender(
logdir, LOG_NAME, new PatternLayout("[%d] [%t] %-5p %c %x: %m%n"), rotate));
logdir,
LOG_NAME,
new PatternLayout(
"[%d{" + LogTimestampFormatter.TIMESTAMP_FORMAT + "}] [%t] %-5p %c %x: %m%n"),
rotate));
}
if (json) {
Boolean enableReverseDnsLookup =
config.getBoolean("gerrit", null, "enableReverseDnsLookup", false);
root.addAppender(
SystemLog.createAppender(
logdir, LOG_NAME + JSON_SUFFIX, new JSONEventLayoutV1(), rotate));
logdir,
LOG_NAME + JSON_SUFFIX,
new ErrorLogJsonLayout(enableReverseDnsLookup),
rotate));
}
}
}

View File

@@ -0,0 +1,138 @@
// Copyright (C) 2020 The Android Open Source Project
//
// 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.gerrit.pgm.util;
import com.google.gerrit.util.logging.JsonLayout;
import com.google.gerrit.util.logging.JsonLogEntry;
import com.google.gson.annotations.SerializedName;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
/** Layout for formatting error log events in the JSON format. */
public class ErrorLogJsonLayout extends JsonLayout {
private final Boolean enableReverseDnsLookup;
public ErrorLogJsonLayout(Boolean enableDnsReverseLookup) {
super();
this.enableReverseDnsLookup = enableDnsReverseLookup;
}
@Override
public JsonLogEntry toJsonLogEntry(LoggingEvent event) {
return new ErrorJsonLogEntry(event);
}
@SuppressWarnings("unused")
private class ErrorJsonLogEntry extends JsonLogEntry {
/** Timestamp of when the log entry was created. */
@SerializedName("@timestamp")
public final String timestamp;
/** Hostname of the machine running Gerrit. */
public final String sourceHost;
/** Logged message. */
public final String message;
/** File containing the code creating the log entry. */
public final String file;
/** Line number of code creating the log entry. */
public final String lineNumber;
/** Class from which the log entry was created. */
@SerializedName("class")
public final String clazz;
/** Method from which the log entry was created. */
public final String method;
/** Name of the logger creating the log entry. */
public final String loggerName;
/** Mapped diagnostic context. */
@SuppressWarnings("rawtypes")
public final Map mdc;
/** Nested diagnostic context. */
public final String ndc;
/** Logging level/severity. */
public final String level;
/** Thread executing the code creating the log entry. */
public final String threadName;
/** Version of log format. */
@SerializedName("@version")
public final int version = 2;
/**
* Map containing information of a logged exception. It contains the following key-value pairs:
* exception_class: Which class threw the exception exception_method: Which method threw the
* exception stacktrace: The exception stacktrace
*/
public Map<String, String> exception;
public ErrorJsonLogEntry(LoggingEvent event) {
this.timestamp = timestampFormatter.format(event.getTimeStamp());
this.sourceHost = getSourceHost(enableReverseDnsLookup);
this.message = event.getRenderedMessage();
this.file = event.getLocationInformation().getFileName();
this.lineNumber = event.getLocationInformation().getLineNumber();
this.clazz = event.getLocationInformation().getClassName();
this.method = event.getLocationInformation().getMethodName();
this.loggerName = event.getLoggerName();
this.mdc = event.getProperties();
this.ndc = event.getNDC();
this.level = event.getLevel().toString();
this.threadName = event.getThreadName();
if (event.getThrowableInformation() != null) {
this.exception = getException(event.getThrowableInformation());
}
}
private String getSourceHost(Boolean enableReverseDnsLookup) {
InetAddress in;
try {
in = InetAddress.getLocalHost();
if (Boolean.TRUE.equals(enableReverseDnsLookup)) {
return in.getCanonicalHostName();
}
return in.getHostAddress();
} catch (UnknownHostException e) {
return "unknown-host";
}
}
private Map<String, String> getException(ThrowableInformation throwable) {
HashMap<String, String> exceptionInformation = new HashMap<>();
String throwableName = throwable.getThrowable().getClass().getCanonicalName();
if (throwableName != null) {
exceptionInformation.put("exception_class", throwableName);
}
String throwableMessage = throwable.getThrowable().getMessage();
if (throwableMessage != null) {
exceptionInformation.put("exception_message", throwableMessage);
}
String[] stackTrace = throwable.getThrowableStrRep();
if (stackTrace != null) {
exceptionInformation.put("stacktrace", String.join("\n", stackTrace));
}
return exceptionInformation;
}
}
}