blob: 85378a48148aae68070ee35b2150c61bbcbe54be [file] [log] [blame]
// 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;
}
}
}