Line data Source code
1 : // Copyright (C) 2020 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.pgm.util; 16 : 17 : import com.google.gerrit.util.logging.JsonLayout; 18 : import com.google.gerrit.util.logging.JsonLogEntry; 19 : import com.google.gson.annotations.SerializedName; 20 : import java.net.InetAddress; 21 : import java.net.UnknownHostException; 22 : import java.util.HashMap; 23 : import java.util.Map; 24 : import org.apache.log4j.spi.LoggingEvent; 25 : import org.apache.log4j.spi.ThrowableInformation; 26 : 27 : /** Layout for formatting error log events in the JSON format. */ 28 0 : public class ErrorLogJsonLayout extends JsonLayout { 29 : @Override 30 : public JsonLogEntry toJsonLogEntry(LoggingEvent event) { 31 0 : return new ErrorJsonLogEntry(event); 32 : } 33 : 34 : @SuppressWarnings("unused") 35 : private class ErrorJsonLogEntry extends JsonLogEntry { 36 : /** Timestamp of when the log entry was created. */ 37 : @SerializedName("@timestamp") 38 : public final String timestamp; 39 : 40 : /** Hostname of the machine running Gerrit. */ 41 : public final String sourceHost; 42 : /** Logged message. */ 43 : public final String message; 44 : /** File containing the code creating the log entry. */ 45 : public final String file; 46 : /** Line number of code creating the log entry. */ 47 : public final String lineNumber; 48 : 49 : /** Class from which the log entry was created. */ 50 : @SerializedName("class") 51 : public final String clazz; 52 : 53 : /** Method from which the log entry was created. */ 54 : public final String method; 55 : /** Name of the logger creating the log entry. */ 56 : public final String loggerName; 57 : 58 : /** Mapped diagnostic context. */ 59 : @SuppressWarnings("rawtypes") 60 : public final Map mdc; 61 : 62 : /** Nested diagnostic context. */ 63 : public final String ndc; 64 : /** Logging level/severity. */ 65 : public final String level; 66 : /** Thread executing the code creating the log entry. */ 67 : public final String threadName; 68 : 69 : /** Version of log format. */ 70 0 : @SerializedName("@version") 71 : public final int version = 2; 72 : 73 : /** 74 : * Map containing information of a logged exception. It contains the following key-value pairs: 75 : * exception_class: Which class threw the exception exception_method: Which method threw the 76 : * exception stacktrace: The exception stacktrace 77 : */ 78 : public Map<String, String> exception; 79 : 80 0 : public ErrorJsonLogEntry(LoggingEvent event) { 81 0 : this.timestamp = timestampFormatter.format(event.getTimeStamp()); 82 0 : this.sourceHost = getSourceHost(); 83 0 : this.message = event.getRenderedMessage(); 84 0 : this.file = event.getLocationInformation().getFileName(); 85 0 : this.lineNumber = event.getLocationInformation().getLineNumber(); 86 0 : this.clazz = event.getLocationInformation().getClassName(); 87 0 : this.method = event.getLocationInformation().getMethodName(); 88 0 : this.loggerName = event.getLoggerName(); 89 0 : this.mdc = event.getProperties(); 90 0 : this.ndc = event.getNDC(); 91 0 : this.level = event.getLevel().toString(); 92 0 : this.threadName = event.getThreadName(); 93 0 : if (event.getThrowableInformation() != null) { 94 0 : this.exception = getException(event.getThrowableInformation()); 95 : } 96 0 : } 97 : 98 : private String getSourceHost() { 99 : try { 100 0 : return InetAddress.getLocalHost().getHostAddress(); 101 0 : } catch (UnknownHostException e) { 102 0 : return "unknown-host"; 103 : } 104 : } 105 : 106 : private Map<String, String> getException(ThrowableInformation throwable) { 107 0 : HashMap<String, String> exceptionInformation = new HashMap<>(); 108 : 109 0 : String throwableName = throwable.getThrowable().getClass().getCanonicalName(); 110 0 : if (throwableName != null) { 111 0 : exceptionInformation.put("exception_class", throwableName); 112 : } 113 : 114 0 : String throwableMessage = throwable.getThrowable().getMessage(); 115 0 : if (throwableMessage != null) { 116 0 : exceptionInformation.put("exception_message", throwableMessage); 117 : } 118 : 119 0 : String[] stackTrace = throwable.getThrowableStrRep(); 120 0 : if (stackTrace != null) { 121 0 : exceptionInformation.put("stacktrace", String.join("\n", stackTrace)); 122 : } 123 0 : return exceptionInformation; 124 : } 125 : } 126 : }