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