1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.util;
17
18 import java.io.PrintWriter;
19 import java.io.Serializable;
20 import java.io.StringWriter;
21 import java.util.Set;
22
23 import org.apache.logging.log4j.Level;
24 import org.apache.logging.log4j.core.Appender;
25 import org.apache.logging.log4j.core.Core;
26 import org.apache.logging.log4j.core.Filter;
27 import org.apache.logging.log4j.core.Layout;
28 import org.apache.logging.log4j.core.LogEvent;
29 import org.apache.logging.log4j.core.appender.AbstractAppender;
30 import org.apache.logging.log4j.core.config.Property;
31 import org.apache.logging.log4j.core.config.plugins.Plugin;
32 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
33 import org.apache.logging.log4j.core.config.plugins.PluginElement;
34 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
35 import org.codelibs.fess.helper.LogNotificationHelper;
36 import org.codelibs.fess.helper.LogNotificationHelper.LogNotificationEvent;
37
38
39
40
41 @Plugin(name = "LogNotificationAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
42 public class LogNotificationAppender extends AbstractAppender {
43
44 private static final int MAX_THROWABLE_LENGTH = 500;
45
46 private static final Set<String> EXCLUDED_LOGGERS = Set.of(
47 "org.codelibs.fess.helper.NotificationHelper",
48 "org.codelibs.fess.util.LogNotificationAppender",
49 "org.codelibs.fess.job.LogNotificationJob",
50 "org.codelibs.fess.timer.LogNotificationTarget",
51 "org.codelibs.fess.helper.LogNotificationHelper",
52 "org.codelibs.curl"
53 );
54
55 private final Level minLevel;
56
57
58
59
60
61
62
63
64
65
66
67 protected LogNotificationAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
68 final boolean ignoreExceptions, final Property[] properties, final Level minLevel) {
69 super(name, filter, layout, ignoreExceptions, properties);
70 this.minLevel = minLevel;
71 }
72
73 @Override
74 public void append(final LogEvent event) {
75 final String loggerName = event.getLoggerName();
76 if (loggerName != null) {
77 for (final String excluded : EXCLUDED_LOGGERS) {
78 if (loggerName.startsWith(excluded)) {
79 return;
80 }
81 }
82 }
83
84 if (!event.getLevel().isMoreSpecificThan(getEffectiveMinLevel())) {
85 return;
86 }
87
88 try {
89 if (!ComponentUtil.getFessConfig().isLogNotificationEnabled()) {
90 return;
91 }
92 } catch (final Exception e) {
93 return;
94 }
95
96 final LogNotificationHelper helper;
97 try {
98 helper = ComponentUtil.getLogNotificationHelper();
99 } catch (final Exception e) {
100 return;
101 }
102
103 String throwableStr = null;
104 final Throwable thrown = event.getThrown();
105 if (thrown != null) {
106 final StringWriter sw = new StringWriter();
107 thrown.printStackTrace(new PrintWriter(sw));
108 throwableStr = sw.toString();
109 if (throwableStr.length() > MAX_THROWABLE_LENGTH) {
110 throwableStr = throwableStr.substring(0, MAX_THROWABLE_LENGTH);
111 }
112 }
113
114 final LogNotificationEvent notificationEvent = new LogNotificationEvent(
115 event.getTimeMillis(),
116 event.getLevel().name(),
117 loggerName,
118 event.getMessage().getFormattedMessage(),
119 throwableStr
120 );
121 helper.offer(notificationEvent);
122 }
123
124 private Level getEffectiveMinLevel() {
125 try {
126 final String levelStr = ComponentUtil.getSystemProperties().getProperty("fess.log.notification.level");
127 if (levelStr != null) {
128 return Level.toLevel(levelStr, minLevel);
129 }
130 } catch (final Exception e) {
131
132 }
133 return minLevel;
134 }
135
136
137
138
139
140
141
142
143
144
145 @PluginFactory
146 public static LogNotificationAppender createAppender(
147 @PluginAttribute("name") final String name,
148 @PluginAttribute(value = "minLevel", defaultString = "ERROR") final String minLevel,
149 @PluginElement("Filter") final Filter filter,
150 @PluginElement("Layout") final Layout<? extends Serializable> layout) {
151 if (name == null) {
152 LOGGER.error("No name provided for LogNotificationAppender");
153 return null;
154 }
155 final Level level = Level.toLevel(minLevel, Level.ERROR);
156 return new LogNotificationAppender(name, filter, layout, true, Property.EMPTY_ARRAY, level);
157 }
158 }