1

Our application is deployed as a servlet war to multiple tomcat servers under multiple customer contexts:

customer#application.war

We're using log4j2 as our logging and alert email mechanism. So far, everything is working great and our fatal errors are being sent. However, as we deploy to new contexts, it's becoming less clear which customer is generating the error.

So far, it appears that the subject value is static and set in the config file and the system variables are loaded when the logger is built:

subject="[${applicationname}] Fatal Error ${hostname}:${sys:pwd}"

While it appears that there is a way to ascertain the name of our deployed context via the servlet API, we have yet to determine how to introduce this value in the email subject programmatically and dynamically at run time.

This would greatly reduce the time it takes to research an error. Any tips?

So far we've considered the following:

  1. Custom war file with custom log4j2 config for each customer context (very hackish)
  2. Update all log.fatal calls to include the context info from the servlet (horrid)
  3. Custom SmtpAppender (final and protected so that's out)
  4. Custom SmtpManager and override the subject in the MimeMessage object (seems workable but the documentation does not show how to implement)

TIA!!

Piko

Piko
  • 4,132
  • 2
  • 21
  • 13
  • "programmatically and dynamically" - From what I can see, you actually just need it to be set when each WAR starts, not updated on each log message? – ThrawnCA Nov 07 '17 at 22:26
  • Yes, but how can I set it when the servlet is loaded? – Piko Nov 07 '17 at 22:42
  • I updated my answer. This may already work. – Remko Popma Nov 08 '17 at 12:25
  • 1
    @Piko I’ve updated my answer. Please try a dynamic lookup (double $$) and use the lookup prefix (`$${sys:...}` for system properties, `$${env:...` for environment variables etc) – Remko Popma Nov 08 '17 at 22:44

1 Answers1

2

This is actually a known issue in Log4j2 as of 2.9.1. The problem is that a MimeMessage is cached and the subject becomes a fixed value. A simple solution would be to stop caching.

There is an open ticket to address this: Log4j2-1450. (Related: Log4j2-1192, which implemented pattern lookups but didn’t fix that MimeMessages are cached.)

If you can provide a patch or a pull request it would greatly increase the chances of this being addressed speedily.


Update: looking my old comment in that ticket:

Looks like subject already supports $$ runtime lookups. The following attributes are used for each email that is sent, and it should be possible to support runtime lookups for these attributes: * from * replyto * to * cc * bcc * subject (already a runtime lookup)

It should be possible to configure the subject to be a system properties lookup like this:

subject = "$${sys:email.subject}"

Then you set system property email.subject to a different subject and send an email with a different subject. Can you try this?


Update 2:

If system properties are not suitable, you can also create a custom lookup, this is only a few lines of code.

Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • Thanks for the heads up. What release of log4j2 is this available in? We're stuck at 2.8.2 as there is a bug in 2.9.x that breaks our logging... ;) – Piko Nov 09 '17 at 00:18
  • Looks like 2.6. Have you reported the bug in 2.9? We’d like to fix it. – Remko Popma Nov 09 '17 at 02:43
  • Thanks @Remko. We'll test out the dynamic lookup feature and will also see about reporting the bug we encountered at 2.9. – Piko Nov 09 '17 at 20:47
  • So far, we're running in to a limitation of this idea in that, any system property we might set would be the same for all contexts within the application server container. One of our team stumbled across web:contextPath from the log4j-web api that seems closer to our solution. So far, that value is not being substituted. Does that require a certain version of tomcat? – Piko Nov 09 '17 at 22:11
  • I updated my answer. You may want to create a custom lookup for this, should be only a few lines of code. – Remko Popma Nov 09 '17 at 22:57
  • Finally got it working using the custom lookup plugin feature. Unfortunately, we had to apply the log4j2.xml custom configuration before it would see our plugin. Not sure how it's supposed to automatically find it in the class path otherwise... :) – Piko Nov 13 '17 at 20:11
  • Glad to hear that. Well done! The Log4j2 jar includes an annotation processor that is supposed to work even without the `packages` configuration attribute. But anyway, glad you got it to work. – Remko Popma Nov 14 '17 at 04:44