1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.config;
18
19 import java.util.Objects;
20
21 import org.apache.logging.log4j.Level;
22 import org.apache.logging.log4j.core.Appender;
23 import org.apache.logging.log4j.core.Filter;
24 import org.apache.logging.log4j.core.LogEvent;
25 import org.apache.logging.log4j.core.appender.AppenderLoggingException;
26 import org.apache.logging.log4j.core.filter.AbstractFilterable;
27 import org.apache.logging.log4j.core.filter.Filterable;
28
29
30
31
32 public class AppenderControl extends AbstractFilterable {
33 private static final long serialVersionUID = 1L;
34
35 private final ThreadLocal<AppenderControl> recursive = new ThreadLocal<>();
36 private final Appender appender;
37 private final Level level;
38 private final int intLevel;
39 private final String appenderName;
40
41
42
43
44
45
46
47
48 public AppenderControl(final Appender appender, final Level level, final Filter filter) {
49 super(filter);
50 this.appender = appender;
51 this.appenderName = appender.getName();
52 this.level = level;
53 this.intLevel = level == null ? Level.ALL.intLevel() : level.intLevel();
54 start();
55 }
56
57
58
59
60
61
62 public String getAppenderName() {
63 return appenderName;
64 }
65
66
67
68
69
70
71 public Appender getAppender() {
72 return appender;
73 }
74
75
76
77
78
79
80 public void callAppender(final LogEvent event) {
81 if (shouldSkip(event)) {
82 return;
83 }
84 callAppenderPreventRecursion(event);
85 }
86
87 private boolean shouldSkip(final LogEvent event) {
88 return isFilteredByAppenderControl(event) || isFilteredByLevel(event) || isRecursiveCall();
89 }
90
91 private boolean isFilteredByAppenderControl(final LogEvent event) {
92 return getFilter() != null && Filter.Result.DENY == getFilter().filter(event);
93 }
94
95 private boolean isFilteredByLevel(final LogEvent event) {
96 return level != null && intLevel < event.getLevel().intLevel();
97 }
98
99 private boolean isRecursiveCall() {
100 if (recursive.get() != null) {
101 appenderErrorHandlerMessage("Recursive call to appender ");
102 return true;
103 }
104 return false;
105 }
106
107 private String appenderErrorHandlerMessage(final String prefix) {
108 String result = createErrorMsg(prefix);
109 appender.getHandler().error(result);
110 return result;
111 }
112
113 private void callAppenderPreventRecursion(final LogEvent event) {
114 try {
115 recursive.set(this);
116 callAppender0(event);
117 } finally {
118 recursive.set(null);
119 }
120 }
121
122 private void callAppender0(final LogEvent event) {
123 ensureAppenderStarted();
124 if (!isFilteredByAppender(event)) {
125 tryCallAppender(event);
126 }
127 }
128
129 private void ensureAppenderStarted() {
130 if (!appender.isStarted()) {
131 handleError("Attempted to append to non-started appender ");
132 }
133 }
134
135 private void handleError(final String prefix) {
136 final String msg = appenderErrorHandlerMessage(prefix);
137 if (!appender.ignoreExceptions()) {
138 throw new AppenderLoggingException(msg);
139 }
140 }
141
142 private String createErrorMsg(final String prefix) {
143 return prefix + appender.getName();
144 }
145
146 private boolean isFilteredByAppender(final LogEvent event) {
147 return appender instanceof Filterable && ((Filterable) appender).isFiltered(event);
148 }
149
150 private void tryCallAppender(final LogEvent event) {
151 try {
152 appender.append(event);
153 } catch (final RuntimeException ex) {
154 handleAppenderError(ex);
155 } catch (final Exception ex) {
156 handleAppenderError(new AppenderLoggingException(ex));
157 }
158 }
159
160 private void handleAppenderError(final RuntimeException ex) {
161 appender.getHandler().error(createErrorMsg("An exception occurred processing Appender "), ex);
162 if (!appender.ignoreExceptions()) {
163 throw ex;
164 }
165 }
166
167
168
169
170
171
172 @Override
173 public boolean equals(final Object obj) {
174 if (obj == this) {
175 return true;
176 }
177 if (!(obj instanceof AppenderControl)) {
178 return false;
179 }
180 final AppenderControl other = (AppenderControl) obj;
181 return Objects.equals(appenderName, other.appenderName);
182 }
183
184 @Override
185 public int hashCode() {
186 return appenderName.hashCode();
187 }
188
189 @Override
190 public String toString() {
191 return super.toString() + "[appender=" + appender + ", appenderName=" + appenderName + ", level=" + level
192 + ", intLevel=" + intLevel + ", recursive=" + recursive + ", filter=" + getFilter() + "]";
193 }
194 }