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 018package org.apache.logging.log4j.core.pattern; 019 020import java.util.List; 021 022import org.apache.logging.log4j.core.LogEvent; 023import org.apache.logging.log4j.core.appender.AbstractAppender; 024import org.apache.logging.log4j.core.config.Configuration; 025import org.apache.logging.log4j.core.config.plugins.Plugin; 026import org.apache.logging.log4j.core.layout.PatternLayout; 027 028/** 029 * Max length pattern converter. Limit contained text to a maximum length. 030 * On invalid length the default value 100 is used (and an error message is logged). 031 * If max length is greater than 20, an abbreviated text will get ellipsis ("...") appended. 032 * Example usage (for email subject): 033 * {@code "%maxLen{[AppName, ${hostName}, ${web:contextPath}] %p: %c{1} - %m%notEmpty{ =>%ex{short}}}{160}"} 034 * 035 * @author Thies Wellpott 036 */ 037@Plugin(name = "maxLength", category = PatternConverter.CATEGORY) 038@ConverterKeys({"maxLength", "maxLen"}) 039public final class MaxLengthConverter extends LogEventPatternConverter { 040 041 /** 042 * Gets an instance of the class. 043 * 044 * @param config The current Configuration. 045 * @param options pattern options, an array of two elements: pattern, max length (defaults to 100 on invalid value). 046 * @return instance of class. 047 */ 048 public static MaxLengthConverter newInstance(final Configuration config, final String[] options) { 049 if (options.length != 2) { 050 LOGGER.error("Incorrect number of options on maxLength: expected 2 received {}: {}", options.length, 051 options); 052 return null; 053 } 054 if (options[0] == null) { 055 LOGGER.error("No pattern supplied on maxLength"); 056 return null; 057 } 058 if (options[1] == null) { 059 LOGGER.error("No length supplied on maxLength"); 060 return null; 061 } 062 final PatternParser parser = PatternLayout.createPatternParser(config); 063 final List<PatternFormatter> formatters = parser.parse(options[0]); 064 return new MaxLengthConverter(formatters, AbstractAppender.parseInt(options[1], 100)); 065 } 066 067 068 private final List<PatternFormatter> formatters; 069 private final int maxLength; 070 071 /** 072 * Construct the converter. 073 * 074 * @param formatters The PatternFormatters to generate the text to manipulate. 075 * @param maxLength The max. length of the resulting string. Ellipsis ("...") is appended on shorted string, if greater than 20. 076 */ 077 private MaxLengthConverter(final List<PatternFormatter> formatters, final int maxLength) { 078 super("MaxLength", "maxLength"); 079 this.maxLength = maxLength; 080 this.formatters = formatters; 081 LOGGER.trace("new MaxLengthConverter with {}", maxLength); 082 } 083 084 085 @Override 086 public void format(final LogEvent event, final StringBuilder toAppendTo) { 087 final StringBuilder buf = new StringBuilder(); 088 for (final PatternFormatter formatter : formatters) { 089 formatter.format(event, buf); 090 if (buf.length() > maxLength) { // stop early 091 break; 092 } 093 } 094 if (buf.length() > maxLength) { 095 buf.setLength(maxLength); 096 if (maxLength > 20) { // only append ellipses if length is not very short 097 buf.append("..."); 098 } 099 } 100 toAppendTo.append(buf); 101 } 102 103}