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 import org.apache.logging.log4j.util.PerformanceSensitive;
29
30
31
32
33 public class AppenderControl extends AbstractFilterable {
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 @PerformanceSensitive
92 private boolean isFilteredByAppenderControl(final LogEvent event) {
93 final Filter filter = getFilter();
94 return filter != null && Filter.Result.DENY == filter.filter(event);
95 }
96
97 @PerformanceSensitive
98 private boolean isFilteredByLevel(final LogEvent event) {
99 return level != null && intLevel < event.getLevel().intLevel();
100 }
101
102 @PerformanceSensitive
103 private boolean isRecursiveCall() {
104 if (recursive.get() != null) {
105 appenderErrorHandlerMessage("Recursive call to appender ");
106 return true;
107 }
108 return false;
109 }
110
111 private String appenderErrorHandlerMessage(final String prefix) {
112 final String result = createErrorMsg(prefix);
113 appender.getHandler().error(result);
114 return result;
115 }
116
117 private void callAppenderPreventRecursion(final LogEvent event) {
118 try {
119 recursive.set(this);
120 callAppender0(event);
121 } finally {
122 recursive.set(null);
123 }
124 }
125
126 private void callAppender0(final LogEvent event) {
127 ensureAppenderStarted();
128 if (!isFilteredByAppender(event)) {
129 tryCallAppender(event);
130 }
131 }
132
133 private void ensureAppenderStarted() {
134 if (!appender.isStarted()) {
135 handleError("Attempted to append to non-started appender ");
136 }
137 }
138
139 private void handleError(final String prefix) {
140 final String msg = appenderErrorHandlerMessage(prefix);
141 if (!appender.ignoreExceptions()) {
142 throw new AppenderLoggingException(msg);
143 }
144 }
145
146 private String createErrorMsg(final String prefix) {
147 return prefix + appender.getName();
148 }
149
150 private boolean isFilteredByAppender(final LogEvent event) {
151 return appender instanceof Filterable && ((Filterable) appender).isFiltered(event);
152 }
153
154 private void tryCallAppender(final LogEvent event) {
155 try {
156 appender.append(event);
157 } catch (final RuntimeException ex) {
158 handleAppenderError(event, ex);
159 } catch (final Throwable t) {
160 handleAppenderError(event, new AppenderLoggingException(t));
161 }
162 }
163
164 private void handleAppenderError(final LogEvent event, final RuntimeException ex) {
165 appender.getHandler().error(createErrorMsg("An exception occurred processing Appender "), event, ex);
166 if (!appender.ignoreExceptions()) {
167 throw ex;
168 }
169 }
170
171
172
173
174
175
176 @Override
177 public boolean equals(final Object obj) {
178 if (obj == this) {
179 return true;
180 }
181 if (!(obj instanceof AppenderControl)) {
182 return false;
183 }
184 final AppenderControl other = (AppenderControl) obj;
185 return Objects.equals(appenderName, other.appenderName);
186 }
187
188 @Override
189 public int hashCode() {
190 return appenderName.hashCode();
191 }
192
193 @Override
194 public String toString() {
195 return super.toString() + "[appender=" + appender + ", appenderName=" + appenderName + ", level=" + level
196 + ", intLevel=" + intLevel + ", recursive=" + recursive + ", filter=" + getFilter() + "]";
197 }
198 }