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:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
138
java/com/google/gerrit/pgm/util/ErrorLogJsonLayout.java
Normal file
138
java/com/google/gerrit/pgm/util/ErrorLogJsonLayout.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user