001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 package org.apache.logging.log4j.core.pattern; 018 019 import org.apache.logging.log4j.core.LogEvent; 020 import org.apache.logging.log4j.core.config.plugins.Plugin; 021 022 import java.io.PrintWriter; 023 import java.io.StringWriter; 024 025 026 /** 027 * Outputs the Throwable portion of the LoggingEvent as a full stacktrace 028 * unless this converter's option is 'short', where it just outputs the first line of the trace, or if 029 * the number of lines to print is explicitly specified. 030 */ 031 @Plugin(name = "ThrowablePatternConverter", type = "Converter") 032 @ConverterKeys({"ex", "throwable", "exception" }) 033 public class ThrowablePatternConverter extends LogEventPatternConverter { 034 035 /** 036 * Format the whole stack trace. 037 */ 038 protected static final String FULL = "full"; 039 /** 040 * Format only the first line of the throwable. 041 */ 042 protected static final String SHORT = "short"; 043 /** 044 * If "short", only first line of throwable report will be formatted.<br> 045 * If "full", the whole stack trace will be formatted.<br> 046 * If "numeric" the output will be limited to the specified number of lines. 047 */ 048 protected final String option; 049 050 /** 051 * The number of lines to write. 052 */ 053 protected final int lines; 054 055 /** 056 * Constructor. 057 * @param name Name of converter. 058 * @param style CSS style for output. 059 * @param options options, may be null. 060 */ 061 protected ThrowablePatternConverter(String name, String style, final String[] options) { 062 super(name, style); 063 int count = 0; 064 if ((options != null) && (options.length > 0)) { 065 option = options[0]; 066 if (option == null) { 067 } else if (option.equalsIgnoreCase(SHORT)) { 068 count = 2; 069 } else if (!option.equalsIgnoreCase(FULL)) { 070 count = Integer.parseInt(option); 071 } 072 073 } else { 074 option = null; 075 } 076 lines = count; 077 } 078 079 /** 080 * Gets an instance of the class. 081 * 082 * @param options pattern options, may be null. If first element is "short", 083 * only the first line of the throwable will be formatted. 084 * @return instance of class. 085 */ 086 public static ThrowablePatternConverter newInstance(final String[] options) { 087 return new ThrowablePatternConverter("Throwable", "throwable", options); 088 } 089 090 /** 091 * {@inheritDoc} 092 */ 093 @Override 094 public void format(final LogEvent event, final StringBuilder toAppendTo) { 095 Throwable t = event.getThrown(); 096 097 if (t != null) { 098 StringWriter w = new StringWriter(); 099 t.printStackTrace(new PrintWriter(w)); 100 int len = toAppendTo.length(); 101 if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) { 102 toAppendTo.append(" "); 103 } 104 if (lines > 0) { 105 StringBuilder sb = new StringBuilder(); 106 String[] array = w.toString().split("\n"); 107 for (int i = 0; i < lines; ++i) { 108 sb.append(array[i]).append("\n"); 109 } 110 toAppendTo.append(sb.toString()); 111 112 } else { 113 toAppendTo.append(w.toString()); 114 } 115 } 116 } 117 118 /** 119 * This converter obviously handles throwables. 120 * 121 * @return true. 122 */ 123 @Override 124 public boolean handlesThrowable() { 125 return true; 126 } 127 }