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