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.HashMap;
20 import java.util.Map;
21 import java.util.Objects;
22
23 import org.apache.logging.log4j.Level;
24 import org.apache.logging.log4j.Marker;
25 import org.apache.logging.log4j.ThreadContext;
26 import org.apache.logging.log4j.core.Filter;
27 import org.apache.logging.log4j.core.LogEvent;
28 import org.apache.logging.log4j.core.Logger;
29 import org.apache.logging.log4j.core.config.Node;
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.ContextDataInjector;
35 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
36 import org.apache.logging.log4j.core.util.KeyValuePair;
37 import org.apache.logging.log4j.message.Message;
38 import org.apache.logging.log4j.util.ReadOnlyStringMap;
39
40
41
42
43
44
45 @Plugin(name = "DynamicThresholdFilter", category = Node.CATEGORY, elementType = Filter.ELEMENT_TYPE, printObject = true)
46 public final class DynamicThresholdFilter extends AbstractFilter {
47
48
49
50
51
52
53
54
55
56
57 @PluginFactory
58 public static DynamicThresholdFilter createFilter(
59 @PluginAttribute("key") final String key,
60 @PluginElement("Pairs") final KeyValuePair[] pairs,
61 @PluginAttribute("defaultThreshold") final Level defaultThreshold,
62 @PluginAttribute("onMatch") final Result onMatch,
63 @PluginAttribute("onMismatch") final Result onMismatch) {
64 final Map<String, Level> map = new HashMap<>();
65 for (final KeyValuePair pair : pairs) {
66 map.put(pair.getKey(), Level.toLevel(pair.getValue()));
67 }
68 final Level level = defaultThreshold == null ? Level.ERROR : defaultThreshold;
69 return new DynamicThresholdFilter(key, map, level, onMatch, onMismatch);
70 }
71
72 private Level defaultThreshold = Level.ERROR;
73 private final String key;
74 private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
75 private Map<String, Level> levelMap = new HashMap<>();
76
77 private DynamicThresholdFilter(final String key, final Map<String, Level> pairs, final Level defaultLevel,
78 final Result onMatch, final Result onMismatch) {
79 super(onMatch, onMismatch);
80 Objects.requireNonNull(key, "key cannot be null");
81 this.key = key;
82 this.levelMap = pairs;
83 this.defaultThreshold = defaultLevel;
84 }
85
86 @Override
87 public boolean equals(final Object obj) {
88 if (this == obj) {
89 return true;
90 }
91 if (!super.equalsImpl(obj)) {
92 return false;
93 }
94 if (getClass() != obj.getClass()) {
95 return false;
96 }
97 final DynamicThresholdFilter other = (DynamicThresholdFilter) obj;
98 if (defaultThreshold == null) {
99 if (other.defaultThreshold != null) {
100 return false;
101 }
102 } else if (!defaultThreshold.equals(other.defaultThreshold)) {
103 return false;
104 }
105 if (key == null) {
106 if (other.key != null) {
107 return false;
108 }
109 } else if (!key.equals(other.key)) {
110 return false;
111 }
112 if (levelMap == null) {
113 if (other.levelMap != null) {
114 return false;
115 }
116 } else if (!levelMap.equals(other.levelMap)) {
117 return false;
118 }
119 return true;
120 }
121
122 private Result filter(final Level level, final ReadOnlyStringMap contextMap) {
123 final String value = contextMap.getValue(key);
124 if (value != null) {
125 Level ctxLevel = levelMap.get(value);
126 if (ctxLevel == null) {
127 ctxLevel = defaultThreshold;
128 }
129 return level.isMoreSpecificThan(ctxLevel) ? onMatch : onMismatch;
130 }
131 return Result.NEUTRAL;
132
133 }
134
135 @Override
136 public Result filter(final LogEvent event) {
137 return filter(event.getLevel(), event.getContextData());
138 }
139
140 @Override
141 public Result filter(final Logger logger, final Level level, final Marker marker, final Message msg,
142 final Throwable t) {
143 return filter(level, currentContextData());
144 }
145
146 @Override
147 public Result filter(final Logger logger, final Level level, final Marker marker, final Object msg,
148 final Throwable t) {
149 return filter(level, currentContextData());
150 }
151
152 @Override
153 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
154 final Object... params) {
155 return filter(level, currentContextData());
156 }
157
158 private ReadOnlyStringMap currentContextData() {
159 return injector.rawContextData();
160 }
161
162 @Override
163 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
164 final Object p0) {
165 return filter(level, currentContextData());
166
167 }
168
169 @Override
170 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
171 final Object p0, final Object p1) {
172 return filter(level, currentContextData());
173
174 }
175
176 @Override
177 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
178 final Object p0, final Object p1, final Object p2) {
179 return filter(level, currentContextData());
180
181 }
182
183 @Override
184 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
185 final Object p0, final Object p1, final Object p2, final Object p3) {
186 return filter(level, currentContextData());
187
188 }
189
190 @Override
191 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
192 final Object p0, final Object p1, final Object p2, final Object p3,
193 final Object p4) {
194 return filter(level, currentContextData());
195
196 }
197
198 @Override
199 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
200 final Object p0, final Object p1, final Object p2, final Object p3,
201 final Object p4, final Object p5) {
202 return filter(level, currentContextData());
203
204 }
205
206 @Override
207 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
208 final Object p0, final Object p1, final Object p2, final Object p3,
209 final Object p4, final Object p5, final Object p6) {
210 return filter(level, currentContextData());
211
212 }
213
214 @Override
215 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
216 final Object p0, final Object p1, final Object p2, final Object p3,
217 final Object p4, final Object p5, final Object p6,
218 final Object p7) {
219 return filter(level, currentContextData());
220
221 }
222
223 @Override
224 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
225 final Object p0, final Object p1, final Object p2, final Object p3,
226 final Object p4, final Object p5, final Object p6,
227 final Object p7, final Object p8) {
228 return filter(level, currentContextData());
229
230 }
231
232 @Override
233 public Result filter(final Logger logger, final Level level, final Marker marker, final String msg,
234 final Object p0, final Object p1, final Object p2, final Object p3,
235 final Object p4, final Object p5, final Object p6,
236 final Object p7, final Object p8, final Object p9) {
237 return filter(level, currentContextData());
238
239 }
240
241 public String getKey() {
242 return this.key;
243 }
244
245 public Map<String, Level> getLevelMap() {
246 return levelMap;
247 }
248
249 @Override
250 public int hashCode() {
251 final int prime = 31;
252 int result = super.hashCodeImpl();
253 result = prime * result + ((defaultThreshold == null) ? 0 : defaultThreshold.hashCode());
254 result = prime * result + ((key == null) ? 0 : key.hashCode());
255 result = prime * result + ((levelMap == null) ? 0 : levelMap.hashCode());
256 return result;
257 }
258
259 @Override
260 public String toString() {
261 final StringBuilder sb = new StringBuilder();
262 sb.append("key=").append(key);
263 sb.append(", default=").append(defaultThreshold);
264 if (levelMap.size() > 0) {
265 sb.append('{');
266 boolean first = true;
267 for (final Map.Entry<String, Level> entry : levelMap.entrySet()) {
268 if (!first) {
269 sb.append(", ");
270 first = false;
271 }
272 sb.append(entry.getKey()).append('=').append(entry.getValue());
273 }
274 sb.append('}');
275 }
276 return sb.toString();
277 }
278 }