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 public AppenderControl(final Appender appender, final Level level, final Filter filter) {
48 super(filter);
49 this.appender = appender;
50 this.appenderName = appender.getName();
51 this.level = level;
52 this.intLevel = level == null ? Level.ALL.intLevel() : level.intLevel();
53 start();
54 }
55
56
57
58
59
60 public String getAppenderName() {
61 return appenderName;
62 }
63
64
65
66
67
68 public Appender getAppender() {
69 return appender;
70 }
71
72
73
74
75
76 public void callAppender(final LogEvent event) {
77 if (shouldSkip(event)) {
78 return;
79 }
80 callAppenderPreventRecursion(event);
81 }
82
83 private boolean shouldSkip(final LogEvent event) {
84 return isFilteredByAppenderControl(event) || isFilteredByLevel(event) || isRecursiveCall();
85 }
86
87 private boolean isFilteredByAppenderControl(final LogEvent event) {
88 return getFilter() != null && Filter.Result.DENY == getFilter().filter(event);
89 }
90
91 private boolean isFilteredByLevel(final LogEvent event) {
92 return level != null && intLevel < event.getLevel().intLevel();
93 }
94
95 private boolean isRecursiveCall() {
96 if (recursive.get() != null) {
97 appenderErrorHandlerMessage("Recursive call to appender ");
98 return true;
99 }
100 return false;
101 }
102
103 private String appenderErrorHandlerMessage(final String prefix) {
104 String result = createErrorMsg(prefix);
105 appender.getHandler().error(result);
106 return result;
107 }
108
109 private void callAppenderPreventRecursion(final LogEvent event) {
110 try {
111 recursive.set(this);
112 callAppender0(event);
113 } finally {
114 recursive.set(null);
115 }
116 }
117
118 private void callAppender0(final LogEvent event) {
119 ensureAppenderStarted();
120 if (!isFilteredByAppender(event)) {
121 tryCallAppender(event);
122 }
123 }
124
125 private void ensureAppenderStarted() {
126 if (!appender.isStarted()) {
127 handleError("Attempted to append to non-started appender ");
128 }
129 }
130
131 private void handleError(final String prefix) {
132 final String msg = appenderErrorHandlerMessage(prefix);
133 if (!appender.ignoreExceptions()) {
134 throw new AppenderLoggingException(msg);
135 }
136 }
137
138 private String createErrorMsg(final String prefix) {
139 return prefix + appender.getName();
140 }
141
142 private boolean isFilteredByAppender(final LogEvent event) {
143 return appender instanceof Filterable && ((Filterable) appender).isFiltered(event);
144 }
145
146 private void tryCallAppender(final LogEvent event) {
147 try {
148 appender.append(event);
149 } catch (final RuntimeException ex) {
150 handleAppenderError(ex);
151 } catch (final Exception ex) {
152 handleAppenderError(new AppenderLoggingException(ex));
153 }
154 }
155
156 private void handleAppenderError(final RuntimeException ex) {
157 appender.getHandler().error(createErrorMsg("An exception occurred processing Appender "), ex);
158 if (!appender.ignoreExceptions()) {
159 throw ex;
160 }
161 }
162
163
164
165
166
167
168 @Override
169 public boolean equals(final Object obj) {
170 if (obj == this) {
171 return true;
172 }
173 if (!(obj instanceof AppenderControl)) {
174 return false;
175 }
176 final AppenderControl other = (AppenderControl) obj;
177 return Objects.equals(appenderName, other.appenderName);
178 }
179
180 @Override
181 public int hashCode() {
182 return appenderName.hashCode();
183 }
184 }