1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender.routing;
18
19 import org.apache.logging.log4j.core.Appender;
20 import org.apache.logging.log4j.core.Filter;
21 import org.apache.logging.log4j.core.LogEvent;
22 import org.apache.logging.log4j.core.appender.AbstractAppender;
23 import org.apache.logging.log4j.core.appender.rewrite.RewritePolicy;
24 import org.apache.logging.log4j.core.config.AppenderControl;
25 import org.apache.logging.log4j.core.config.Configuration;
26 import org.apache.logging.log4j.core.config.Node;
27 import org.apache.logging.log4j.core.config.plugins.Plugin;
28 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
29 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
30 import org.apache.logging.log4j.core.config.plugins.PluginElement;
31 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
32
33 import java.util.Map;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.ConcurrentMap;
36
37
38
39
40
41
42
43
44
45 @Plugin(name = "Routing", type = "Core", elementType = "appender", printObject = true)
46 public final class RoutingAppender extends AbstractAppender {
47 private static final String DEFAULT_KEY = "ROUTING_APPENDER_DEFAULT";
48 private final Routes routes;
49 private final Configuration config;
50 private ConcurrentMap<String, AppenderControl> appenders = new ConcurrentHashMap<String, AppenderControl>();
51 private final RewritePolicy rewritePolicy;
52
53 private RoutingAppender(String name, Filter filter, boolean handleException, Routes routes,
54 RewritePolicy rewritePolicy, Configuration config) {
55 super(name, filter, null, handleException);
56 this.routes = routes;
57 this.config = config;
58 this.rewritePolicy = rewritePolicy;
59 }
60
61 @Override
62 public void start() {
63 Map<String, Appender> map = config.getAppenders();
64 for (Route route : routes.getRoutes()) {
65 if (route.getAppenderRef() != null) {
66 Appender appender = map.get(route.getAppenderRef());
67 if (appender != null) {
68 String key = route.getKey() == null ? DEFAULT_KEY : route.getKey();
69 if (appenders.containsKey(key)) {
70 if (DEFAULT_KEY.equals(key)) {
71 LOGGER.error("Multiple default routes. Only the first will be used");
72 } else {
73 LOGGER.error("Duplicate route " + key + " is ignored");
74 }
75 } else {
76 appenders.put(key, new AppenderControl(appender, null, null));
77 }
78 } else {
79 LOGGER.error("Appender " + route.getAppenderRef() + " cannot be located. Route ignored");
80 }
81 }
82 }
83 super.start();
84 }
85
86 @Override
87 public void stop() {
88 super.stop();
89 Map<String, Appender> map = config.getAppenders();
90 for (Map.Entry<String, AppenderControl> entry : appenders.entrySet()) {
91 String name = entry.getValue().getAppender().getName();
92 if (!DEFAULT_KEY.equals(entry.getKey()) && !map.containsKey(name)) {
93 entry.getValue().getAppender().stop();
94 }
95 }
96 }
97
98 public void append(LogEvent event) {
99 if (rewritePolicy != null) {
100 event = rewritePolicy.rewrite(event);
101 }
102 String key = config.getSubst().replace(event, routes.getPattern());
103 AppenderControl control = getControl(key, event);
104 if (control != null) {
105 control.callAppender(event);
106 }
107 }
108
109 private synchronized AppenderControl getControl(String key, LogEvent event) {
110 AppenderControl control = appenders.get(key);
111 boolean defaultRoute = false;
112 if (control != null) {
113 return control;
114 }
115 Route route = null;
116 for (Route r : routes.getRoutes()) {
117 if (r.getAppenderRef() == null && key.equals(r.getKey())) {
118 route = r;
119 break;
120 }
121 }
122 if (route == null) {
123 control = appenders.get(DEFAULT_KEY);
124 if (control != null) {
125 return control;
126 }
127 for (Route r : routes.getRoutes()) {
128 if (r.getAppenderRef() == null && r.getKey() == null) {
129 route = r;
130 defaultRoute = true;
131 break;
132 }
133 }
134 }
135 if (route != null) {
136 Appender app = createAppender(route, event);
137 if (app == null) {
138 return null;
139 }
140 control = new AppenderControl(app, null, null);
141 appenders.put(key, control);
142 if (defaultRoute) {
143 appenders.put(DEFAULT_KEY, control);
144 }
145 }
146
147 return control;
148 }
149
150 private Appender createAppender(Route route, LogEvent event) {
151 Node routeNode = route.getNode();
152 for (Node node : routeNode.getChildren()) {
153 if (node.getType().getElementName().equals("appender")) {
154 config.createConfiguration(node, event);
155 if (node.getObject() instanceof Appender) {
156 Appender app = (Appender) node.getObject();
157 app.start();
158 return (Appender) node.getObject();
159 }
160 LOGGER.error("Unable to create Appender of type " + node.getName());
161 return null;
162 }
163 }
164 LOGGER.error("No Appender was configured for route " + route.getKey());
165 return null;
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179 @PluginFactory
180 public static RoutingAppender createAppender(@PluginAttr("name") String name,
181 @PluginAttr("suppressExceptions") String suppress,
182 @PluginElement("routes") Routes routes,
183 @PluginConfiguration Configuration config,
184 @PluginElement("rewritePolicy") RewritePolicy rewritePolicy,
185 @PluginElement("filters") Filter filter) {
186
187 boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
188
189 if (name == null) {
190 LOGGER.error("No name provided for RoutingAppender");
191 return null;
192 }
193 if (routes == null) {
194 LOGGER.error("No routes defined for RoutingAppender");
195 return null;
196 }
197 return new RoutingAppender(name, filter, handleExceptions, routes, rewritePolicy, config);
198 }
199 }