You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Ron Grabowski (Jira)" <ji...@apache.org> on 2022/01/30 16:55:00 UTC
[jira] [Commented] (LOG4J2-1039) SmtpAppender needs the ability to filter out logging events that contain a specific Marker
[ https://issues.apache.org/jira/browse/LOG4J2-1039?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17484385#comment-17484385 ]
Ron Grabowski commented on LOG4J2-1039:
---------------------------------------
Seems like the problem is a typo in SmtpAppender:
{code:java}
// WRONG - SmtpAppender
public boolean isFiltered(final LogEvent event) {
final boolean filtered = super.isFiltered(event);
if (filtered) {
manager.add(event);
}
return filtered;
} {code}
{code:java}
// CORRECT - LoggerConfig
protected void log(final LogEvent event, final LoggerConfigPredicate predicate) {
if (!isFiltered(event)) {
processLogEvent(event, predicate);
}
} {code}
_isFiltered_ checks if the filter matched with DENY. SmtpAppender should add the event to the buffer only if {_}isFiltered==false{_}:
{code:java}
// CORRECT - SmtpAppender
public boolean isFiltered(final LogEvent event) {
final boolean filtered = super.isFiltered(event);
if (!filtered) { // add if not DENY
manager.add(event);
}
return filtered;
}{code}
The FilteredSmtpAppender example on this ticket came to the same conclusion. Other things like CompositeFilter is working correctly.
SmtpAppender didn't have a test case for isFiltered, looks like this has been broke since 2013.
> SmtpAppender needs the ability to filter out logging events that contain a specific Marker
> ------------------------------------------------------------------------------------------
>
> Key: LOG4J2-1039
> URL: https://issues.apache.org/jira/browse/LOG4J2-1039
> Project: Log4j 2
> Issue Type: Improvement
> Components: Appenders, Filters
> Affects Versions: 2.3
> Reporter: Tony DeFusco
> Priority: Major
> Labels: easyfix, features, patch
> Attachments: FilteredSmtpAppender.java, SmtpAppender.patch
>
>
> I have a use case where some of my logged events have been marked with a custom _Marker_ (e.g. "PRIVATE"). When the _SMTP Appender_ sends out an e-mail with the triggering event and its cyclic buffer of collected log events, I do not want the log events that have been set with a custom _Marker_ to be included in the e-mail.
> What follows is the source code for a custom SMTP appender plugin that I created to support the above use case:
> {code:title=org.apache.logging.log4j.core.appender.FilteredSmtpAppender.java}package org.apache.logging.log4j.core.appender;
> import org.apache.logging.log4j.core.Filter;
> import org.apache.logging.log4j.core.Layout;
> import org.apache.logging.log4j.core.LogEvent;
> import org.apache.logging.log4j.core.appender.AbstractAppender;
> import org.apache.logging.log4j.core.config.plugins.Plugin;
> import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
> import org.apache.logging.log4j.core.config.plugins.PluginElement;
> import org.apache.logging.log4j.core.config.plugins.PluginFactory;
> import org.apache.logging.log4j.core.filter.CompositeFilter;
> import org.apache.logging.log4j.core.filter.MarkerFilter;
> import org.apache.logging.log4j.core.filter.ThresholdFilter;
> import org.apache.logging.log4j.core.layout.HtmlLayout;
> import org.apache.logging.log4j.core.net.SmtpManager;
> import org.apache.logging.log4j.core.util.Booleans;
> import java.io.Serializable;
> import java.util.List;
> /**
> * Send an e-mail when a specific logging event occurs, typically on errors or
> * fatal errors. Unlike the vanilla SmtpAppender, this variation allows for
> * using a MarkerFilter to filter out certain logging events from appearing in
> * the e-mail.
> * <p/>
> * <Filters>
> * <MarkerFilter marker="PRIVATE" onMatch="DENY" onMismatch="NEUTRAL"/>
> * <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
> * </Filters>
> * <p/>
> * The number of logging events delivered in this e-mail depend on the value of
> * <b>BufferSize</b> option. The <code>SmtpAppender</code> keeps only the last
> * <code>BufferSize</code> logging events in its cyclic buffer. This keeps
> * memory requirements at a reasonable level while still delivering useful
> * application context.
> * <p/>
> * By default, an email message will be formatted as HTML. This can be modified
> * by setting a layout for the appender.
> * <p/>
> * By default, an email message will be sent when an ERROR or higher severity
> * message is appended. This can be modified by setting a filter for the
> * appender.
> */
> @Plugin(name = "FilteredSMTP", category = "Core", elementType = "appender", printObject = true)
> public class FilteredSmtpAppender extends AbstractAppender {
> private static final long serialVersionUID = 1L;
> private static final int DEFAULT_BUFFER_SIZE = 512;
> /**
> * The SMTP Manager
> */
> private final SmtpManager manager;
> /**
> * Constructor.
> *
> * @param name The Appender name.
> * @param filter The Filter to associate with the Appender.
> * @param layout The layout to use to format the event.
> * @param manager The SmtpManager to use to format and send the e-mail.
> * @param ignoreExceptions If true, exceptions will be logged and suppressed. If false errors will be propagated.
> */
> protected FilteredSmtpAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout, final SmtpManager manager, final boolean ignoreExceptions) {
> super(name, filter, layout, ignoreExceptions);
> this.manager = manager;
> }
> /**
> * Create a FilteredSmtpAppender.
> *
> * @param name The name of the Appender.
> * @param to The comma-separated list of recipient email addresses.
> * @param cc The comma-separated list of CC email addresses.
> * @param bcc The comma-separated list of BCC email addresses.
> * @param from The email address of the sender.
> * @param replyTo The comma-separated list of reply-to email addresses.
> * @param subject The subject of the email message.
> * @param smtpProtocol The SMTP transport protocol (such as "smtps", defaults to "smtp").
> * @param smtpHost The SMTP hostname to send to.
> * @param smtpPortStr The SMTP port to send to.
> * @param smtpUsername The username required to authenticate against the SMTP server.
> * @param smtpPassword The password required to authenticate against the SMTP server.
> * @param smtpDebug Enable mail session debuging on STDOUT.
> * @param bufferSizeStr How many log events should be buffered for inclusion in the
> * message?
> * @param layout The layout to use (defaults to HtmlLayout).
> * @param filter The Filter or null (defaults to ThresholdFilter, level of
> * ERROR).
> * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
> * they are propagated to the caller.
> *
> * @return The FilteredSmtpAppender.
> */
> @PluginFactory
> public static FilteredSmtpAppender createAppender(
> @PluginAttribute("name") final String name,
> @PluginAttribute("to") final String to,
> @PluginAttribute("cc") final String cc,
> @PluginAttribute("bcc") final String bcc,
> @PluginAttribute("from") final String from,
> @PluginAttribute("replyTo") final String replyTo,
> @PluginAttribute("subject") final String subject,
> @PluginAttribute("smtpProtocol") final String smtpProtocol,
> @PluginAttribute("smtpHost") final String smtpHost,
> @PluginAttribute("smtpPort") final String smtpPortStr,
> @PluginAttribute("smtpUsername") final String smtpUsername,
> @PluginAttribute("smtpPassword") final String smtpPassword,
> @PluginAttribute("smtpDebug") final String smtpDebug,
> @PluginAttribute("bufferSize") final String bufferSizeStr,
> @PluginElement("Layout") Layout<? extends Serializable> layout,
> @PluginElement("Filter") Filter filter,
> @PluginAttribute("ignoreExceptions") final String ignore) {
> if (name == null) {
> LOGGER.error("No name provided for FilteredSmtpAppender");
> return null;
> }
> final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
> final int smtpPort = AbstractAppender.parseInt(smtpPortStr, 0);
> final boolean isSmtpDebug = Boolean.parseBoolean(smtpDebug);
> final int bufferSize = bufferSizeStr == null ? DEFAULT_BUFFER_SIZE : Integer.parseInt(bufferSizeStr);
> if (layout == null) {
> layout = HtmlLayout.createDefaultLayout();
> }
> if (filter == null) {
> filter = ThresholdFilter.createFilter(null, null, null);
> }
> final SmtpManager manager = SmtpManager.getSMTPManager(to, cc, bcc, from, replyTo, subject, smtpProtocol,
> smtpHost, smtpPort, smtpUsername, smtpPassword, isSmtpDebug, filter.toString(), bufferSize);
> if (manager == null) {
> return null;
> }
> return new FilteredSmtpAppender(name, filter, layout, manager, ignoreExceptions);
> }
> /**
> * Capture all events in CyclicBuffer. Ignore events that are denied by a
> * MarkerFilter.
> *
> * @param event The Log event.
> *
> * @return true if the event should be filtered.
> */
> @Override
> public boolean isFiltered(final LogEvent event) {
> boolean filtered = false;
> final Filter filter = this.getFilter();
> if (filter instanceof CompositeFilter) {
> final List<Filter> filters = ((CompositeFilter)filter).getFilters();
> for (final Filter aFilter : filters) {
> final Filter.Result filterResult = (aFilter != null) ? aFilter.filter(event) : Filter.Result.NEUTRAL;
> if (!Filter.Result.NEUTRAL.equals(filterResult)) {
> filtered = (Filter.Result.DENY.equals(filterResult));
> if (filtered) {
> final boolean isMarkerFilter = aFilter instanceof MarkerFilter;
> // Ignore events that are denied by a MarkerFilter.
> if (!isMarkerFilter) {
> manager.add(event);
> }
> }
> break;
> }
> }
> }
> else {
> filtered = super.isFiltered(event);
> if (filtered) {
> final boolean isMarkerFilter = filter instanceof MarkerFilter;
> if (!isMarkerFilter) {
> manager.add(event);
> }
> }
> }
> return filtered;
> }
> /**
> * Perform FilterableSmtpAppender specific appending actions, mainly adding
> * the event to a cyclic buffer and checking if the event triggers an e-mail
> * to be sent.
> *
> * @param event The Log event.
> */
> @Override
> public void append(final LogEvent event) {
> manager.sendEvents(getLayout(), event);
> }
> }{code}
> Such a use case could be configured as follows for the custom _Filtered SMTP Appender_ plugin. Here it is configured to accept only logging events of *WARN* level or greater:
> {code:xml}<?xml version="1.0" encoding="UTF-8"?>
> ...
> <Appender type="FilteredSMTP" name="filteredSmtp"
> bufferSize="5"
> smtpHost="${smtpHost}" smtpPort="${smtpPort}" smtpProtocol="${smtpProtocol}"
> smtpUsername="${smtpUsername}" smtpPassword="${smtpPassword}"
> subject="${emailSubject}"
> from="${emailFrom}"
> to="${emailTo}"
> replyTo="${emailReplyTo}"
> cc="${emailCc}"
> bcc="${emailBcc}"
> >
> <Layout type="PatternLayout">
> <Pattern>%m</Pattern>
> </Layout>
> <Filters>
> <MarkerFilter marker="PRIVATE" onMatch="DENY" onMismatch="NEUTRAL"/>
> <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
> </Filters>
> </Appender>
> ...{code}
--
This message was sent by Atlassian Jira
(v8.20.1#820001)