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