1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.pattern;
18
19 import org.apache.logging.log4j.util.PerformanceSensitive;
20 import org.apache.logging.log4j.util.ReadOnlyStringMap;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.config.plugins.Plugin;
23 import org.apache.logging.log4j.core.util.Constants;
24 import org.apache.logging.log4j.util.TriConsumer;
25 import org.apache.logging.log4j.util.StringBuilders;
26
27
28
29
30
31
32
33
34 @Plugin(name = "MdcPatternConverter", category = PatternConverter.CATEGORY)
35 @ConverterKeys({ "X", "mdc", "MDC" })
36 @PerformanceSensitive("allocation")
37 public final class MdcPatternConverter extends LogEventPatternConverter {
38
39 private static final ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();
40 private static final int DEFAULT_STRING_BUILDER_SIZE = 64;
41
42
43
44
45 private final String key;
46 private final String[] keys;
47 private final boolean full;
48
49
50
51
52
53
54 private MdcPatternConverter(final String[] options) {
55 super(options != null && options.length > 0 ? "MDC{" + options[0] + '}' : "MDC", "mdc");
56 if (options != null && options.length > 0) {
57 full = false;
58 if (options[0].indexOf(',') > 0) {
59 keys = options[0].split(",");
60 for (int i = 0; i < keys.length; i++) {
61 keys[i] = keys[i].trim();
62 }
63 key = null;
64 } else {
65 keys = null;
66 key = options[0];
67 }
68 } else {
69 full = true;
70 key = null;
71 keys = null;
72 }
73 }
74
75
76
77
78
79
80
81 public static MdcPatternConverter newInstance(final String[] options) {
82 return new MdcPatternConverter(options);
83 }
84
85 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = new TriConsumer<String, Object, StringBuilder>() {
86 @Override
87 public void accept(final String key, final Object value, final StringBuilder sb) {
88 if (sb.length() > 1) {
89 sb.append(", ");
90 }
91 sb.append(key).append('=');
92 StringBuilders.appendValue(sb, value);
93 }
94 };
95
96
97
98
99 @Override
100 public void format(final LogEvent event, final StringBuilder toAppendTo) {
101 final ReadOnlyStringMap contextData = event.getContextData();
102
103
104 if (full) {
105 if (contextData == null || contextData.size() == 0) {
106 toAppendTo.append("{}");
107 return;
108 }
109 appendFully(contextData, toAppendTo);
110 } else {
111 if (keys != null) {
112 if (contextData == null || contextData.size() == 0) {
113 toAppendTo.append("{}");
114 return;
115 }
116 appendSelectedKeys(keys, contextData, toAppendTo);
117 } else if (contextData != null){
118
119 final Object value = contextData.getValue(key);
120 if (value != null) {
121 StringBuilders.appendValue(toAppendTo, value);
122 }
123 }
124 }
125 }
126
127 private static void appendFully(final ReadOnlyStringMap contextData, final StringBuilder toAppendTo) {
128 final StringBuilder sb = getStringBuilder();
129 sb.append("{");
130 contextData.forEach(WRITE_KEY_VALUES_INTO, sb);
131 sb.append('}');
132 toAppendTo.append(sb);
133 trimToMaxSize(sb);
134 }
135
136 private static void appendSelectedKeys(final String[] keys, final ReadOnlyStringMap contextData, final StringBuilder toAppendTo) {
137
138 final StringBuilder sb = getStringBuilder();
139 sb.append("{");
140 for (int i = 0; i < keys.length; i++) {
141 final String theKey = keys[i];
142 final Object value = contextData.getValue(theKey);
143 if (value != null) {
144 if (sb.length() > 1) {
145 sb.append(", ");
146 }
147 sb.append(theKey).append('=');
148 StringBuilders.appendValue(sb, value);
149 }
150 }
151 sb.append('}');
152 toAppendTo.append(sb);
153 trimToMaxSize(sb);
154 }
155
156 private static StringBuilder getStringBuilder() {
157 StringBuilder result = threadLocal.get();
158 if (result == null) {
159 result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
160 threadLocal.set(result);
161 }
162 result.setLength(0);
163 return result;
164 }
165
166 private static void trimToMaxSize(final StringBuilder stringBuilder) {
167 StringBuilders.trimToMaxSize(stringBuilder, Constants.MAX_REUSABLE_MESSAGE_SIZE);
168 }
169 }