1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.filter;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.apache.logging.log4j.Level;
26 import org.apache.logging.log4j.Marker;
27 import org.apache.logging.log4j.ThreadContext;
28 import org.apache.logging.log4j.core.Filter;
29 import org.apache.logging.log4j.core.LogEvent;
30 import org.apache.logging.log4j.core.Logger;
31 import org.apache.logging.log4j.core.config.Node;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
34 import org.apache.logging.log4j.core.config.plugins.PluginElement;
35 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
36 import org.apache.logging.log4j.core.util.KeyValuePair;
37 import org.apache.logging.log4j.message.Message;
38
39
40
41
42 @Plugin(name = "ThreadContextMapFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
43 public class ThreadContextMapFilter extends MapFilter {
44
45 private final String key;
46 private final String value;
47
48 private final boolean useMap;
49
50 public ThreadContextMapFilter(final Map<String, List<String>> pairs, final boolean oper, final Result onMatch,
51 final Result onMismatch) {
52 super(pairs, oper, onMatch, onMismatch);
53 if (pairs.size() == 1) {
54 final Iterator<Map.Entry<String, List<String>>> iter = pairs.entrySet().iterator();
55 final Map.Entry<String, List<String>> entry = iter.next();
56 if (entry.getValue().size() == 1) {
57 this.key = entry.getKey();
58 this.value = entry.getValue().get(0);
59 this.useMap = false;
60 } else {
61 this.key = null;
62 this.value = null;
63 this.useMap = true;
64 }
65 } else {
66 this.key = null;
67 this.value = null;
68 this.useMap = true;
69 }
70 }
71
72 @Override
73 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
74 final Object... params) {
75 return filter();
76 }
77
78 @Override
79 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
80 final Throwable t) {
81 return filter();
82 }
83
84 @Override
85 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
86 final Throwable t) {
87 return filter();
88 }
89
90 private Result filter() {
91 boolean match = false;
92 if (useMap) {
93 for (final Map.Entry<String, List<String>> entry : getMap().entrySet()) {
94 final String toMatch = ThreadContext.get(entry.getKey());
95 if (toMatch != null) {
96 match = entry.getValue().contains(toMatch);
97 } else {
98 match = false;
99 }
100 if ((!isAnd() && match) || (isAnd() && !match)) {
101 break;
102 }
103 }
104 } else {
105 match = value.equals(ThreadContext.get(key));
106 }
107 return match ? onMatch : onMismatch;
108 }
109
110 @Override
111 public Result filter(final LogEvent event) {
112 return super.filter(event.getContextMap()) ? onMatch : onMismatch;
113 }
114
115 @PluginFactory
116 public static ThreadContextMapFilter createFilter(
117 @PluginElement("Pairs") final KeyValuePair[] pairs,
118 @PluginAttribute("operator") final String oper,
119 @PluginAttribute("onMatch") final Result match,
120 @PluginAttribute("onMismatch") final Result mismatch) {
121 if (pairs == null || pairs.length == 0) {
122 LOGGER.error("key and value pairs must be specified for the ThreadContextMapFilter");
123 return null;
124 }
125 final Map<String, List<String>> map = new HashMap<>();
126 for (final KeyValuePair pair : pairs) {
127 final String key = pair.getKey();
128 if (key == null) {
129 LOGGER.error("A null key is not valid in MapFilter");
130 continue;
131 }
132 final String value = pair.getValue();
133 if (value == null) {
134 LOGGER.error("A null value for key " + key + " is not allowed in MapFilter");
135 continue;
136 }
137 List<String> list = map.get(pair.getKey());
138 if (list != null) {
139 list.add(value);
140 } else {
141 list = new ArrayList<>();
142 list.add(value);
143 map.put(pair.getKey(), list);
144 }
145 }
146 if (map.isEmpty()) {
147 LOGGER.error("ThreadContextMapFilter is not configured with any valid key value pairs");
148 return null;
149 }
150 final boolean isAnd = oper == null || !oper.equalsIgnoreCase("or");
151 return new ThreadContextMapFilter(map, isAnd, match, mismatch);
152 }
153 }