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