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