001/* 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2026, 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 v2.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.classic; 015 016import java.util.HashMap; 017import java.util.Map; 018import java.util.function.Supplier; 019 020import ch.qos.logback.classic.pattern.*; 021import ch.qos.logback.classic.pattern.color.HighlightingCompositeConverter; 022import ch.qos.logback.classic.spi.ILoggingEvent; 023import ch.qos.logback.core.CoreConstants; 024import ch.qos.logback.core.pattern.DynamicConverter; 025import ch.qos.logback.core.pattern.PatternLayoutBase; 026import ch.qos.logback.core.pattern.color.*; 027import ch.qos.logback.core.pattern.parser.Parser; 028 029/** 030 * <p> 031 * A flexible layout configurable with pattern string. The main method in this class is 032 * to {@link #doLayout(ILoggingEvent)}. It returns the results as a 033 * {#link String}. The format and contents of the result depends on the <em>conversion 034 * pattern</em>. 035 * <p> 036 * For more information about this layout, please refer to the online manual at 037 * <a href="http://logback.qos.ch/manual/layouts.html#PatternLayout">layouts.html#PatternLayout</a> 038 * 039 */ 040 041public class PatternLayout extends PatternLayoutBase<ILoggingEvent> { 042 043 public static final Map<String, Supplier<DynamicConverter>> DEFAULT_CONVERTER_SUPPLIER_MAP = new HashMap<>(); 044 045 public static final Map<String, String> CONVERTER_CLASS_TO_KEY_MAP = new HashMap<String, String>(); 046 047 public static final String HEADER_PREFIX = "#logback.classic pattern: "; 048 049 static { 050 DEFAULT_CONVERTER_SUPPLIER_MAP.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); 051 052 DEFAULT_CONVERTER_SUPPLIER_MAP.put("d", DateConverter::new); 053 DEFAULT_CONVERTER_SUPPLIER_MAP.put("date", DateConverter::new); 054 // used by PrefixComposite converter 055 CONVERTER_CLASS_TO_KEY_MAP.put(DateConverter.class.getName(), "date"); 056 057 DEFAULT_CONVERTER_SUPPLIER_MAP.put("ms", MicrosecondConverter::new); 058 DEFAULT_CONVERTER_SUPPLIER_MAP.put("micros", MicrosecondConverter::new); 059 CONVERTER_CLASS_TO_KEY_MAP.put(MicrosecondConverter.class.getName(), "micros"); 060 061 DEFAULT_CONVERTER_SUPPLIER_MAP.put("ep", EpochConverter::new); 062 DEFAULT_CONVERTER_SUPPLIER_MAP.put("epoch", EpochConverter::new); 063 CONVERTER_CLASS_TO_KEY_MAP.put(EpochConverter.class.getName(), "epoch"); 064 065 DEFAULT_CONVERTER_SUPPLIER_MAP.put("r", RelativeTimeConverter::new); 066 DEFAULT_CONVERTER_SUPPLIER_MAP.put("relative", RelativeTimeConverter::new); 067 CONVERTER_CLASS_TO_KEY_MAP.put(RelativeTimeConverter.class.getName(), "relative"); 068 069 DEFAULT_CONVERTER_SUPPLIER_MAP.put("level", LevelConverter::new); 070 DEFAULT_CONVERTER_SUPPLIER_MAP.put("le", LevelConverter::new); 071 DEFAULT_CONVERTER_SUPPLIER_MAP.put("p", LevelConverter::new); 072 CONVERTER_CLASS_TO_KEY_MAP.put(LevelConverter.class.getName(), "level"); 073 074 DEFAULT_CONVERTER_SUPPLIER_MAP.put("t", ThreadConverter::new); 075 DEFAULT_CONVERTER_SUPPLIER_MAP.put("thread", ThreadConverter::new); 076 CONVERTER_CLASS_TO_KEY_MAP.put(ThreadConverter.class.getName(), "thread"); 077 078 DEFAULT_CONVERTER_SUPPLIER_MAP.put("lo", LoggerConverter::new); 079 DEFAULT_CONVERTER_SUPPLIER_MAP.put("logger", LoggerConverter::new); 080 DEFAULT_CONVERTER_SUPPLIER_MAP.put("c", LoggerConverter::new); 081 CONVERTER_CLASS_TO_KEY_MAP.put(LoggerConverter.class.getName(), "logger"); 082 083 DEFAULT_CONVERTER_SUPPLIER_MAP.put("m", MessageConverter::new); 084 DEFAULT_CONVERTER_SUPPLIER_MAP.put("msg", MessageConverter::new); 085 DEFAULT_CONVERTER_SUPPLIER_MAP.put("message", MessageConverter::new); 086 CONVERTER_CLASS_TO_KEY_MAP.put(MessageConverter.class.getName(), "message"); 087 088 DEFAULT_CONVERTER_SUPPLIER_MAP.put("C", ClassOfCallerConverter::new); 089 DEFAULT_CONVERTER_SUPPLIER_MAP.put("class", ClassOfCallerConverter::new); 090 CONVERTER_CLASS_TO_KEY_MAP.put(ClassOfCallerConverter.class.getName(), "class"); 091 092 DEFAULT_CONVERTER_SUPPLIER_MAP.put("M", MethodOfCallerConverter::new); 093 DEFAULT_CONVERTER_SUPPLIER_MAP.put("method", MethodOfCallerConverter::new); 094 CONVERTER_CLASS_TO_KEY_MAP.put(MethodOfCallerConverter.class.getName(), "method"); 095 096 DEFAULT_CONVERTER_SUPPLIER_MAP.put("L", LineOfCallerConverter::new); 097 DEFAULT_CONVERTER_SUPPLIER_MAP.put("line", LineOfCallerConverter::new); 098 CONVERTER_CLASS_TO_KEY_MAP.put(LineOfCallerConverter.class.getName(), "line"); 099 100 DEFAULT_CONVERTER_SUPPLIER_MAP.put("F", FileOfCallerConverter::new); 101 DEFAULT_CONVERTER_SUPPLIER_MAP.put("file", FileOfCallerConverter::new); 102 CONVERTER_CLASS_TO_KEY_MAP.put(FileOfCallerConverter.class.getName(), "file"); 103 104 DEFAULT_CONVERTER_SUPPLIER_MAP.put("X", MDCConverter::new); 105 DEFAULT_CONVERTER_SUPPLIER_MAP.put("mdc", MDCConverter::new); 106 107 DEFAULT_CONVERTER_SUPPLIER_MAP.put("ex", ThrowableProxyConverter::new); 108 DEFAULT_CONVERTER_SUPPLIER_MAP.put("exception", ThrowableProxyConverter::new); 109 DEFAULT_CONVERTER_SUPPLIER_MAP.put("rEx", RootCauseFirstThrowableProxyConverter::new); 110 DEFAULT_CONVERTER_SUPPLIER_MAP.put("rootException", RootCauseFirstThrowableProxyConverter::new); 111 DEFAULT_CONVERTER_SUPPLIER_MAP.put("throwable", ThrowableProxyConverter::new); 112 113 DEFAULT_CONVERTER_SUPPLIER_MAP.put("xEx", ExtendedThrowableProxyConverter::new); 114 DEFAULT_CONVERTER_SUPPLIER_MAP.put("xException", ExtendedThrowableProxyConverter::new); 115 DEFAULT_CONVERTER_SUPPLIER_MAP.put("xThrowable", ExtendedThrowableProxyConverter::new); 116 117 DEFAULT_CONVERTER_SUPPLIER_MAP.put("nopex", NopThrowableInformationConverter::new); 118 DEFAULT_CONVERTER_SUPPLIER_MAP.put("nopexception", NopThrowableInformationConverter::new); 119 120 DEFAULT_CONVERTER_SUPPLIER_MAP.put("cn", ContextNameConverter::new); 121 DEFAULT_CONVERTER_SUPPLIER_MAP.put("contextName", ContextNameConverter::new); 122 CONVERTER_CLASS_TO_KEY_MAP.put(ContextNameConverter.class.getName(), "contextName"); 123 124 DEFAULT_CONVERTER_SUPPLIER_MAP.put("caller", CallerDataConverter::new); 125 CONVERTER_CLASS_TO_KEY_MAP.put(CallerDataConverter.class.getName(), "caller"); 126 127 DEFAULT_CONVERTER_SUPPLIER_MAP.put("marker", MarkerConverter::new); 128 CONVERTER_CLASS_TO_KEY_MAP.put(MarkerConverter.class.getName(), "marker"); 129 130 DEFAULT_CONVERTER_SUPPLIER_MAP.put("kvp", KeyValuePairConverter::new); 131 CONVERTER_CLASS_TO_KEY_MAP.put(KeyValuePairConverter.class.getName(), "kvp"); 132 133 DEFAULT_CONVERTER_SUPPLIER_MAP.put("maskedKvp", MaskedKeyValuePairConverter::new); 134 CONVERTER_CLASS_TO_KEY_MAP.put(MaskedKeyValuePairConverter.class.getName(), "maskedKvp"); 135 136 DEFAULT_CONVERTER_SUPPLIER_MAP.put("property", PropertyConverter::new); 137 138 DEFAULT_CONVERTER_SUPPLIER_MAP.put("n", LineSeparatorConverter::new); 139 140 DEFAULT_CONVERTER_SUPPLIER_MAP.put("black", BlackCompositeConverter::new); 141 DEFAULT_CONVERTER_SUPPLIER_MAP.put("red", RedCompositeConverter::new); 142 DEFAULT_CONVERTER_SUPPLIER_MAP.put("green", GreenCompositeConverter::new); 143 DEFAULT_CONVERTER_SUPPLIER_MAP.put("yellow", YellowCompositeConverter::new); 144 DEFAULT_CONVERTER_SUPPLIER_MAP.put("blue", BlueCompositeConverter::new); 145 DEFAULT_CONVERTER_SUPPLIER_MAP.put("magenta", MagentaCompositeConverter::new); 146 DEFAULT_CONVERTER_SUPPLIER_MAP.put("cyan", CyanCompositeConverter::new); 147 DEFAULT_CONVERTER_SUPPLIER_MAP.put("white", WhiteCompositeConverter::new); 148 DEFAULT_CONVERTER_SUPPLIER_MAP.put("gray", GrayCompositeConverter::new); 149 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldRed", BoldRedCompositeConverter::new); 150 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldGreen", BoldGreenCompositeConverter::new); 151 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldYellow", BoldYellowCompositeConverter::new); 152 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldBlue", BoldBlueCompositeConverter::new); 153 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldMagenta", BoldMagentaCompositeConverter::new); 154 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldCyan", BoldCyanCompositeConverter::new); 155 DEFAULT_CONVERTER_SUPPLIER_MAP.put("boldWhite", BoldWhiteCompositeConverter::new); 156 DEFAULT_CONVERTER_SUPPLIER_MAP.put("highlight", HighlightingCompositeConverter::new); 157 158 DEFAULT_CONVERTER_SUPPLIER_MAP.put("lsn", LocalSequenceNumberConverter::new); 159 CONVERTER_CLASS_TO_KEY_MAP.put(LocalSequenceNumberConverter.class.getName(), "lsn"); 160 161 DEFAULT_CONVERTER_SUPPLIER_MAP.put("sn", SequenceNumberConverter::new); 162 DEFAULT_CONVERTER_SUPPLIER_MAP.put("sequenceNumber", SequenceNumberConverter::new); 163 CONVERTER_CLASS_TO_KEY_MAP.put(SequenceNumberConverter.class.getName(), "sequenceNumber"); 164 165 DEFAULT_CONVERTER_SUPPLIER_MAP.put("prefix", PrefixCompositeConverter::new); 166 167 } 168 169 public PatternLayout() { 170 this.postCompileProcessor = new EnsureExceptionHandling(); 171 } 172 173 public Map<String, Supplier<DynamicConverter>> getDefaultConverterSupplierMap() { 174 return DEFAULT_CONVERTER_SUPPLIER_MAP; 175 } 176 177 public String doLayout(ILoggingEvent event) { 178 if (!isStarted()) { 179 return CoreConstants.EMPTY_STRING; 180 } 181 return writeLoopOnConverters(event); 182 } 183 184 @Override 185 protected String getPresentationHeaderPrefix() { 186 return HEADER_PREFIX; 187 } 188}