Hi Chris,

On 30.05.2025 20:23, Christopher Schultz wrote:
> For my purposes, I need to be able to:
> 
> 1. Attach custom headers to SMTP messages.
> 
> I did this by creating a custom subclass[1] of SMTPAppender that
> overrides activateOptions and sets whatever headers I need on the SMTP
> message.
> 
> In log4j2, SmtpAppender is final, so this is no longer possible.
> 
> Are there any suggestions for how to add custom headers to messages sent
> via SmtpAppender?


Since the HTTP appender[1] already supports the configuration of custom
headers using nested <Property> elements, it would make sense to add
similar support to the SMTP appender as well. I've gone ahead and
created Issue #3704[2] to track this enhancement. Feel free to submit a
PR if you're interested in implementing it.

As for extending the `SmtpAppender`, most Log4j Core 2 appenders follow
a similar architectural pattern:

- The `Appender` itself is fairly minimal and mainly responsible for
exposing a builder that handles configuration options. This part
typically doesn't require extensibility.

- The actual work is done by a `Manager`, which is reference-counted to
allow reuse across multiple `Configuration`s and even `LoggerContext`s.
This ensures that shared resources like a Java Mail session aren’t
closed during reconfiguration.

For SMTP, Log4j uses an abstract `MailManager` to support both Java EE
and Jakarta EE environments. Each implementation handles the protocol
specifics while sharing common logic through the abstract base.

[1]
https://logging.apache.org/log4j/2.x/manual/appenders/network.html#HttpAppender
[2] https://github.com/apache/logging-log4j2/issues/3704

> 2. Don't send log messages as individual SMTP messages, send all at once.
> 
> I did this by creating a custom[2] TriggeringEventEvaluator that simply
> delays triggering until it gets to some high threshold.
> 
> There doesn't seem to be anything at all like that in log4j2.
> 
> Are there any suggestions for how to get multiple log events per SMTP
> message?

This functionality is actually already supported in Log4j Core, although
the behavior may not be immediately intuitive.

Like most Log4j Core appenders, the `SmtpAppender` accepts a nested
filter element[2]. However, unlike other appenders, the SmtpAppender
does not use the filter to drop log events. Instead, it uses the filter
to determine how events are handled:

- Events that do not pass the filter (i.e., the filter returns DENY) are
still captured and stored in a cyclic buffer. These events provide
context and will be included in the body of the email if an email is
triggered later.

- Events that do pass the filter (i.e., the filter returns ACCEPT or
NEUTRAL) trigger the sending of an email. When this happens, the content
of the email includes not just the triggering event but also the
buffered context events that were previously collected.

For more details, see the documentation on the SMTP appender here[4].

[3] https://logging.apache.org/log4j/2.x/manual/filters.html
[4]
https://logging.apache.org/log4j/2.x/manual/appenders/network.html#SmtpAppender

> 3. Re-configure the logging system to enable TRACE logging (or really
> anything kinda like this).
> 
> The idea is that there is an on-disk file with the typical configuration
> (e.g. production-style low-message-output config) but then I'd like to
> pick out a specific logger or appender, change its threshold, and have
> that configuration become effective across the whole logging system, at
> runtime, without re-starting the JVM or anything like that.

This is actually one of the core strengths of Log4j Core 2. Unlike Log4j
1.x or Logback, Log4j Core 2 supports seamless, lossless
reconfiguration—even during high-throughput logging. No log events are
lost in the process.

To enable this feature, simply set the `monitorInterval`[5] attribute on
the `<Configuration>` element to a positive integer. This tells Log4j to
poll the configuration source (such as a `file:` or `https:` URI) every
n seconds, automatically reloading the configuration if it detects any
changes.

Behind the scenes, Log4j's Manager mechanism (as mentioned earlier)
ensures that shared resources, such as file handles or SMTP sessions,
remain open and consistent across reconfigurations. For the SMTP
appender it means that the internal cyclic buffer holding context log
events is preserved across configuration reloads—meaning you won’t lose
the context of an `ERROR` event just because the config was updated.

Looking ahead, starting with version 2.25.0, we’re introducing a new
`MonitorResources` mechanism inspired by the `WatchedResources` you have
in Tomcat. This will allow you to monitor additional resources (e.g.,
keystores, certificate files) for changes and trigger a reconfiguration
if they are modified—even if the main config file itself remains untouched.

Piotr

[5]
https://logging.apache.org/log4j/2.x/manual/configuration.html#configuration-attribute-monitorInterval
[6] https://github.com/apache/logging-log4j2/issues/3074

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-user-h...@logging.apache.org

Reply via email to