1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender;
18
19 import org.apache.logging.log4j.LoggingException;
20 import org.apache.logging.log4j.core.Appender;
21 import org.apache.logging.log4j.core.Filter;
22 import org.apache.logging.log4j.core.LogEvent;
23 import org.apache.logging.log4j.core.config.AppenderControl;
24 import org.apache.logging.log4j.core.config.Configuration;
25 import org.apache.logging.log4j.core.config.plugins.Plugin;
26 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
27 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
28 import org.apache.logging.log4j.core.config.plugins.PluginElement;
29 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
30
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Map;
34
35
36
37
38
39
40 @Plugin(name = "Failover", type = "Core", elementType = "appender", printObject = true)
41 public final class FailoverAppender extends AbstractAppender {
42
43 private final String primaryRef;
44
45 private final String[] failovers;
46
47 private final Configuration config;
48
49 private AppenderControl primary;
50
51 private final List<AppenderControl> failoverAppenders = new ArrayList<AppenderControl>();
52
53 private FailoverAppender(String name, Filter filter, String primary, String[] failovers,
54 Configuration config, boolean handleExceptions) {
55 super(name, filter, null, handleExceptions);
56 this.primaryRef = primary;
57 this.failovers = failovers;
58 this.config = config;
59 }
60
61
62 @Override
63 public void start() {
64 Map<String, Appender> map = config.getAppenders();
65 int errors = 0;
66 if (map.containsKey(primaryRef)) {
67 primary = new AppenderControl(map.get(primaryRef), null, null);
68 } else {
69 LOGGER.error("Unable to locate primary Appender " + primaryRef);
70 ++errors;
71 }
72 for (String name : failovers) {
73 if (map.containsKey(name)) {
74 failoverAppenders.add(new AppenderControl(map.get(name), null, null));
75 } else {
76 LOGGER.error("Failover appender " + name + " is not configured");
77 }
78 }
79 if (failoverAppenders.size() == 0) {
80 LOGGER.error("No failover appenders are available");
81 ++errors;
82 }
83 if (errors == 0) {
84 super.start();
85 }
86 }
87
88
89
90
91
92 public void append(LogEvent event) {
93 RuntimeException re = null;
94 if (!isStarted()) {
95 error("FailoverAppender " + getName() + " did not start successfully");
96 return;
97 }
98 try {
99 primary.callAppender(event);
100 } catch (Exception ex) {
101 re = new LoggingException(ex);
102 boolean written = false;
103 for (AppenderControl control : failoverAppenders) {
104 try {
105 control.callAppender(event);
106 written = true;
107 break;
108 } catch (Exception fex) {
109 continue;
110 }
111 }
112 if (!written && !isExceptionSuppressed()) {
113 throw re;
114 }
115 }
116 }
117
118 @Override
119 public String toString() {
120 StringBuilder sb = new StringBuilder(getName());
121 sb.append(" primary=").append(primary).append(", failover={");
122 boolean first = true;
123 for (String str : failovers) {
124 if (!first) {
125 sb.append(", ");
126 }
127 sb.append(str);
128 first = false;
129 }
130 sb.append("}");
131 return sb.toString();
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145 @PluginFactory
146 public static FailoverAppender createAppender(@PluginAttr("name") String name,
147 @PluginAttr("primary") String primary,
148 @PluginElement("failovers") String[] failovers,
149 @PluginConfiguration Configuration config,
150 @PluginElement("filters") Filter filter,
151 @PluginAttr("suppressExceptions") String suppress) {
152 if (name == null) {
153 LOGGER.error("A name for the Appender must be specified");
154 return null;
155 }
156 if (primary == null) {
157 LOGGER.error("A primary Appender must be specified");
158 return null;
159 }
160 if (failovers == null || failovers.length == 0) {
161 LOGGER.error("At least one failover Appender must be specified");
162 return null;
163 }
164
165 boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
166
167 return new FailoverAppender(name, filter, primary, failovers, config, handleExceptions);
168 }
169 }