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.util.TriConsumer;
24 import org.apache.logging.log4j.util.StringBuilders;
25
26
27
28
29
30
31
32
33 @Plugin(name = "MdcPatternConverter", category = PatternConverter.CATEGORY)
34 @ConverterKeys({ "X", "mdc", "MDC" })
35 @PerformanceSensitive("allocation")
36 public final class MdcPatternConverter extends LogEventPatternConverter {
37
38
39
40
41 private final String key;
42 private final String[] keys;
43 private final boolean full;
44
45
46
47
48
49
50 private MdcPatternConverter(final String[] options) {
51 super(options != null && options.length > 0 ? "MDC{" + options[0] + '}' : "MDC", "mdc");
52 if (options != null && options.length > 0) {
53 full = false;
54 if (options[0].indexOf(',') > 0) {
55 keys = options[0].split(",");
56 for (int i = 0; i < keys.length; i++) {
57 keys[i] = keys[i].trim();
58 }
59 key = null;
60 } else {
61 keys = null;
62 key = options[0];
63 }
64 } else {
65 full = true;
66 key = null;
67 keys = null;
68 }
69 }
70
71
72
73
74
75
76
77 public static MdcPatternConverter newInstance(final String[] options) {
78 return new MdcPatternConverter(options);
79 }
80
81 private static final TriConsumer<String, Object, StringBuilder> WRITE_KEY_VALUES_INTO = new TriConsumer<String, Object, StringBuilder>() {
82 @Override
83 public void accept(final String key, final Object value, final StringBuilder sb) {
84 sb.append(key).append('=');
85 StringBuilders.appendValue(sb, value);
86 sb.append(", ");
87 }
88 };
89
90
91
92
93 @Override
94 public void format(final LogEvent event, final StringBuilder toAppendTo) {
95 final ReadOnlyStringMap contextData = event.getContextData();
96
97
98 if (full) {
99 if (contextData == null || contextData.size() == 0) {
100 toAppendTo.append("{}");
101 return;
102 }
103 appendFully(contextData, toAppendTo);
104 } else {
105 if (keys != null) {
106 if (contextData == null || contextData.size() == 0) {
107 toAppendTo.append("{}");
108 return;
109 }
110 appendSelectedKeys(keys, contextData, toAppendTo);
111 } else if (contextData != null){
112
113 final Object value = contextData.getValue(key);
114 if (value != null) {
115 StringBuilders.appendValue(toAppendTo, value);
116 }
117 }
118 }
119 }
120
121 private static void appendFully(final ReadOnlyStringMap contextData, final StringBuilder toAppendTo) {
122 toAppendTo.append("{");
123 final int start = toAppendTo.length();
124 contextData.forEach(WRITE_KEY_VALUES_INTO, toAppendTo);
125 final int end = toAppendTo.length();
126 if (end > start) {
127 toAppendTo.setCharAt(end - 2, '}');
128 toAppendTo.deleteCharAt(end - 1);
129 } else {
130 toAppendTo.append('}');
131 }
132 }
133
134 private static void appendSelectedKeys(final String[] keys, final ReadOnlyStringMap contextData, final StringBuilder sb) {
135
136 final int start = sb.length();
137 sb.append('{');
138 for (int i = 0; i < keys.length; i++) {
139 final String theKey = keys[i];
140 final Object value = contextData.getValue(theKey);
141 if (value != null) {
142 if (sb.length() - start > 1) {
143 sb.append(", ");
144 }
145 sb.append(theKey).append('=');
146 StringBuilders.appendValue(sb, value);
147 }
148 }
149 sb.append('}');
150 }
151 }