001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.access.common; 015 016import ch.qos.logback.access.common.pattern.ContentLengthConverter; 017import ch.qos.logback.access.common.pattern.DateConverter; 018import ch.qos.logback.access.common.pattern.ElapsedSecondsConverter; 019import ch.qos.logback.access.common.pattern.ElapsedTimeConverter; 020import ch.qos.logback.access.common.pattern.EnsureLineSeparation; 021import ch.qos.logback.access.common.pattern.FullRequestConverter; 022import ch.qos.logback.access.common.pattern.FullResponseConverter; 023import ch.qos.logback.access.common.pattern.LineSeparatorConverter; 024import ch.qos.logback.access.common.pattern.LocalIPAddressConverter; 025import ch.qos.logback.access.common.pattern.LocalPortConverter; 026import ch.qos.logback.access.common.pattern.NAConverter; 027import ch.qos.logback.access.common.pattern.QueryStringConverter; 028import ch.qos.logback.access.common.pattern.RemoteHostConverter; 029import ch.qos.logback.access.common.pattern.RemoteIPAddressConverter; 030import ch.qos.logback.access.common.pattern.RemoteUserConverter; 031import ch.qos.logback.access.common.pattern.RequestAttributeConverter; 032import ch.qos.logback.access.common.pattern.RequestContentConverter; 033import ch.qos.logback.access.common.pattern.RequestCookieConverter; 034import ch.qos.logback.access.common.pattern.RequestHeaderConverter; 035import ch.qos.logback.access.common.pattern.RequestMethodConverter; 036import ch.qos.logback.access.common.pattern.RequestParameterConverter; 037import ch.qos.logback.access.common.pattern.RequestProtocolConverter; 038import ch.qos.logback.access.common.pattern.RequestURIConverter; 039import ch.qos.logback.access.common.pattern.RequestURLConverter; 040import ch.qos.logback.access.common.pattern.ResponseContentConverter; 041import ch.qos.logback.access.common.pattern.ResponseHeaderConverter; 042import ch.qos.logback.access.common.pattern.ServerNameConverter; 043import ch.qos.logback.access.common.pattern.SessionIDConverter; 044import ch.qos.logback.access.common.pattern.StatusCodeConverter; 045import ch.qos.logback.access.common.pattern.ThreadNameConverter; 046import ch.qos.logback.access.common.spi.IAccessEvent; 047import ch.qos.logback.core.pattern.DynamicConverter; 048import ch.qos.logback.core.pattern.PatternLayoutBase; 049import ch.qos.logback.core.pattern.color.*; 050import ch.qos.logback.core.pattern.parser.Parser; 051 052import java.util.HashMap; 053import java.util.Map; 054import java.util.function.Supplier; 055 056/** 057 * <p> 058 * This class is a module-specific implementation of 059 * {@link PatternLayout} to allow http-specific patterns 060 * to be used. The <code>ch.qos.logback.access.PatternLayout</code> provides a 061 * way to format the logging output that is just as easy and flexible as the 062 * usual <code>PatternLayout</code>. 063 * </p> 064 * <p/> 065 * For more information about this layout, please refer to the online manual at 066 * http://logback.qos.ch/manual/layouts.html#AccessPatternLayout 067 * 068 * @author Ceki Gülcü 069 * @author Sébastien Pennec 070 */ 071public class PatternLayout extends PatternLayoutBase<IAccessEvent> { 072 073 public static final Map<String, Supplier<DynamicConverter>> ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP = new HashMap<>(); 074 public static final String HEADER_PREFIX = "#logback.access pattern: "; 075 076 public static final String CLF_PATTERN = "%h %l %u [%t] \"%r\" %s %b"; 077 public static final String CLF_PATTERN_NAME = "common"; 078 public static final String CLF_PATTERN_NAME_2 = "clf"; 079 public static final String COMBINED_PATTERN = "%h %l %u [%t] \"%r\" %s %b \"%i{Referer}\" \"%i{User-Agent}\""; 080 public static final String COMBINED_PATTERN_NAME = "combined"; 081 082 static { 083 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); 084 085 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("a", RemoteIPAddressConverter::new); 086 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("remoteIP", RemoteIPAddressConverter::new); 087 088 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("A", LocalIPAddressConverter::new); 089 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("localIP", LocalIPAddressConverter::new); 090 091 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("b", ContentLengthConverter::new); 092 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("B", ContentLengthConverter::new); 093 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("bytesSent", ContentLengthConverter::new); 094 095 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("h", RemoteHostConverter::new); 096 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("clientHost", RemoteHostConverter::new); 097 098 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("H", RequestProtocolConverter::new); 099 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("protocol", RequestProtocolConverter::new); 100 101 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("i", RequestHeaderConverter::new); 102 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("header", RequestHeaderConverter::new); 103 104 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("I", ThreadNameConverter::new); 105 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("threadName", ThreadNameConverter::new); 106 107 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("l", NAConverter::new); 108 109 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("m", RequestMethodConverter::new); 110 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestMethod", RequestMethodConverter::new); 111 112 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("q", QueryStringConverter::new); 113 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("queryString", QueryStringConverter::new); 114 115 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("r", RequestURLConverter::new); 116 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestURL", RequestURLConverter::new); 117 118 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("s", StatusCodeConverter::new); 119 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("statusCode", StatusCodeConverter::new); 120 121 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("S", SessionIDConverter::new); 122 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("sessionID", SessionIDConverter::new); 123 124 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("t", DateConverter::new); 125 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("date", DateConverter::new); 126 127 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("u", RemoteUserConverter::new); 128 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("user", RemoteUserConverter::new); 129 130 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("U", RequestURIConverter::new); 131 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestURI", RequestURIConverter::new); 132 133 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("v", ServerNameConverter::new); 134 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("server", ServerNameConverter::new); 135 136 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("localPort", LocalPortConverter::new); 137 138 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestAttribute", RequestAttributeConverter::new); 139 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("reqAttribute", RequestAttributeConverter::new); 140 141 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("reqCookie", RequestCookieConverter::new); 142 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestCookie", RequestCookieConverter::new); 143 144 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("responseHeader", ResponseHeaderConverter::new); 145 146 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestParameter", RequestParameterConverter::new); 147 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("reqParameter", RequestParameterConverter::new); 148 149 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("requestContent", RequestContentConverter::new); 150 151 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("responseContent", ResponseContentConverter::new); 152 153 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("fullRequest", FullRequestConverter::new); 154 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("fullResponse", FullResponseConverter::new); 155 156 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("elapsedTime", ElapsedTimeConverter::new); 157 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("D", ElapsedTimeConverter::new); 158 159 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("elapsedSeconds", ElapsedSecondsConverter::new); 160 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("T", ElapsedSecondsConverter::new); 161 162 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("n", LineSeparatorConverter::new); 163 164 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("black", BlackCompositeConverter::new); 165 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("red", RedCompositeConverter::new); 166 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("green", GreenCompositeConverter::new); 167 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("yellow", YellowCompositeConverter::new); 168 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("blue", BlueCompositeConverter::new); 169 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("magenta", MagentaCompositeConverter::new); 170 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("cyan", CyanCompositeConverter::new); 171 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("white", WhiteCompositeConverter::new); 172 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("gray", GrayCompositeConverter::new); 173 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldRed", BoldRedCompositeConverter::new); 174 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldGreen", BoldGreenCompositeConverter::new); 175 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldYellow", BoldYellowCompositeConverter::new); 176 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldBlue", BoldBlueCompositeConverter::new); 177 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldMagenta", BoldMagentaCompositeConverter::new); 178 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldCyan", BoldCyanCompositeConverter::new); 179 ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldWhite", BoldWhiteCompositeConverter::new); 180 } 181 182 public PatternLayout() { 183 // set a default value for pattern 184 setPattern(CLF_PATTERN); 185 // by default postCompileProcessor is an EnsureLineSeparation instance 186 this.postCompileProcessor = new EnsureLineSeparation(); 187 } 188 189 /** 190 * Returns the default converter map for this instance. 191 */ 192 @Override 193 public Map<String, Supplier<DynamicConverter>> getDefaultConverterSupplierMap() { 194 return ACCESS_DEFAULT_CONVERTER_SUPPLIER_MAP; 195 } 196 197 @Override 198 public Map<String, String> getDefaultConverterMap() { 199 return Map.of(); 200 } 201 202 @Override 203 public String doLayout(IAccessEvent event) { 204 if (!isStarted()) { 205 return null; 206 } 207 return writeLoopOnConverters(event); 208 } 209 210 @Override 211 public void start() { 212 if (getPattern().equalsIgnoreCase(CLF_PATTERN_NAME) || getPattern().equalsIgnoreCase(CLF_PATTERN_NAME_2)) { 213 setPattern(CLF_PATTERN); 214 } else if (getPattern().equalsIgnoreCase(COMBINED_PATTERN_NAME)) { 215 setPattern(COMBINED_PATTERN); 216 } 217 super.start(); 218 } 219 220 @Override 221 protected String getPresentationHeaderPrefix() { 222 return HEADER_PREFIX; 223 } 224}