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