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