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 Route defaultRoute;
50 private final Configuration config;
51 private final ConcurrentMap<String, AppenderControl> appenders = new ConcurrentHashMap<String, AppenderControl>();
52 private final RewritePolicy rewritePolicy;
53
54 private RoutingAppender(final String name, final Filter filter, final boolean handleException, final Routes routes,
55 final RewritePolicy rewritePolicy, final Configuration config) {
56 super(name, filter, null, handleException);
57 this.routes = routes;
58 this.config = config;
59 this.rewritePolicy = rewritePolicy;
60 Route defRoute = null;
61 for (final Route route : routes.getRoutes()) {
62 if (route.getKey() == null) {
63 if (defRoute == null) {
64 defRoute = route;
65 } else {
66 error("Multiple default routes. Route " + route.toString() + " will be ignored");
67 }
68 }
69 }
70 defaultRoute = defRoute;
71 }
72
73 @Override
74 public void start() {
75 final Map<String, Appender<?>> map = config.getAppenders();
76
77 for (final Route route : routes.getRoutes()) {
78 if (route.getAppenderRef() != null) {
79 final Appender appender = map.get(route.getAppenderRef());
80 if (appender != null) {
81 final String key = route == defaultRoute ? DEFAULT_KEY : route.getKey();
82 appenders.put(key, new AppenderControl(appender, null, null));
83 } else {
84 LOGGER.error("Appender " + route.getAppenderRef() + " cannot be located. Route ignored");
85 }
86 }
87 }
88 super.start();
89 }
90
91 @Override
92 public void stop() {
93 super.stop();
94 final Map<String, Appender<?>> map = config.getAppenders();
95 for (final Map.Entry<String, AppenderControl> entry : appenders.entrySet()) {
96 final String name = entry.getValue().getAppender().getName();
97 if (!map.containsKey(name)) {
98 entry.getValue().getAppender().stop();
99 }
100 }
101 }
102
103 public void append(LogEvent event) {
104 if (rewritePolicy != null) {
105 event = rewritePolicy.rewrite(event);
106 }
107 final String key = config.getSubst().replace(event, routes.getPattern());
108 final AppenderControl control = getControl(key, event);
109 if (control != null) {
110 control.callAppender(event);
111 }
112 }
113
114 private synchronized AppenderControl getControl(final String key, final LogEvent event) {
115 AppenderControl control = appenders.get(key);
116 if (control != null) {
117 return control;
118 }
119 Route route = null;
120 for (final Route r : routes.getRoutes()) {
121 if (r.getAppenderRef() == null && key.equals(r.getKey())) {
122 route = r;
123 break;
124 }
125 }
126 if (route == null) {
127 route = defaultRoute;
128 }
129 if (route != null) {
130 final Appender app = createAppender(route, event);
131 if (app == null) {
132 return null;
133 }
134 control = new AppenderControl(app, null, null);
135 appenders.put(key, control);
136 }
137
138 return control;
139 }
140
141 private Appender createAppender(final Route route, final LogEvent event) {
142 final Node routeNode = route.getNode();
143 for (final Node node : routeNode.getChildren()) {
144 if (node.getType().getElementName().equals("appender")) {
145 final Node appNode = new Node(node);
146 config.createConfiguration(appNode, event);
147 if (appNode.getObject() instanceof Appender) {
148 final Appender app = (Appender) appNode.getObject();
149 app.start();
150 return app;
151 }
152 LOGGER.error("Unable to create Appender of type " + node.getName());
153 return null;
154 }
155 }
156 LOGGER.error("No Appender was configured for route " + route.getKey());
157 return null;
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171 @PluginFactory
172 public static RoutingAppender createAppender(@PluginAttr("name") final String name,
173 @PluginAttr("suppressExceptions") final String suppress,
174 @PluginElement("routes") final Routes routes,
175 @PluginConfiguration final Configuration config,
176 @PluginElement("rewritePolicy") final RewritePolicy rewritePolicy,
177 @PluginElement("filters") final Filter filter) {
178
179 final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
180
181 if (name == null) {
182 LOGGER.error("No name provided for RoutingAppender");
183 return null;
184 }
185 if (routes == null) {
186 LOGGER.error("No routes defined for RoutingAppender");
187 return null;
188 }
189 return new RoutingAppender(name, filter, handleExceptions, routes, rewritePolicy, config);
190 }
191 }