You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Conor Griffin (Jira)" <ji...@apache.org> on 2022/01/07 15:12:00 UTC

[jira] [Updated] (LOG4J2-3327) scala: add support for creating custom PatternConverter plugins

     [ https://issues.apache.org/jira/browse/LOG4J2-3327?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Conor Griffin updated LOG4J2-3327:
----------------------------------
    Description: 
I tried to add a custom pattern converter using Scala but the plugin does not seem to get picked up or the pattern conversion does not work.  Here's my sample scala implementation where I am trying to use {{%W}} as the pattern to substitute a correlation ID
{code:java}
package com.mycompany.log4jext

import org.apache.logging.log4j.core.LogEvent
import org.apache.logging.log4j.core.config.plugins.{Plugin, PluginFactory}
import org.apache.logging.log4j.core.pattern.{ConverterKeys, LogEventPatternConverter, PatternConverter}

import java.lang

import java.util.UUID


@Plugin(name = "CustomPatternConverter", category = PatternConverter.CATEGORY)
@ConverterKeys(Array("W"))
class CustomPatternConverter(name: String, style: String) extends LogEventPatternConverter(name: String, style: String) {

  def this(options:Array[String]) {
    this("CustomPatternConverter", "none")
  }

  override def format(obj: Any, output: lang.StringBuilder): Unit = {
    obj match {
      case l:LogEvent => format(l, output)
    }
  }

  override def format(event: LogEvent, toAppendTo: lang.StringBuilder): Unit = {
    Option(CorrelationId.getCorrelationId) match {
      case Some(value) => toAppendTo.append(s"[commonId=$value]")
    }
  }
}

object CustomPatternConverter {
  @PluginFactory
  def newInstance(options:Array[String]): CustomPatternConverter = {
    new CustomPatternConverter(options)
  }
}

object CorrelationId {

  private val ID = new ThreadLocal[String]()

  def clearCorrelationId(): Unit = {
    ID.remove()
  }

  def setCorrelationId(id: String): Unit = setCorrelationId(Option(id))

  def setCorrelationId(maybeId: Option[String]): Unit = {
    maybeId foreach { ID.set }
  }

  def getCorrelationId: String = ID.get()

  def generateCorrelationId: String = s"MyApp|${UUID.randomUUID().toString}"

}{code}

I have enabled debug with {{log4j2.debug=true}} and see debug logs but don't see evidence that the pattern converter is loaded.  I also don't see the correlation ID logged however this used to be logged under log4j1.

Is there special configuration needed to get log4j2 to load plugins written in scala?  Or is there an error in how I've written the code above?

I also tried without the {{@PluginFactory}} annotation without success.

  was:
I tried to add a custom appender using Scala but the pattern of having a class with an Plugin annotation and a static method on that class with a PluginFactory or PluginBuilderFactory annotation doesn't seem to work in Scala.
In Scala, you can create a companion object to a class where you can implement the equivalent of static methods but these are not the same class under the hood. The Scala compiler builds 2 or more classes, the companion object gets a class name with a $ appended to it. I think this is affecting the lookup for the method with the Factory annotation.


> scala: add support for creating custom PatternConverter plugins
> ---------------------------------------------------------------
>
>                 Key: LOG4J2-3327
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3327
>             Project: Log4j 2
>          Issue Type: Improvement
>          Components: Plugins
>            Reporter: Conor Griffin
>            Assignee: Mikael Ståldal
>            Priority: Major
>              Labels: scala
>
> I tried to add a custom pattern converter using Scala but the plugin does not seem to get picked up or the pattern conversion does not work.  Here's my sample scala implementation where I am trying to use {{%W}} as the pattern to substitute a correlation ID
> {code:java}
> package com.mycompany.log4jext
> import org.apache.logging.log4j.core.LogEvent
> import org.apache.logging.log4j.core.config.plugins.{Plugin, PluginFactory}
> import org.apache.logging.log4j.core.pattern.{ConverterKeys, LogEventPatternConverter, PatternConverter}
> import java.lang
> import java.util.UUID
> @Plugin(name = "CustomPatternConverter", category = PatternConverter.CATEGORY)
> @ConverterKeys(Array("W"))
> class CustomPatternConverter(name: String, style: String) extends LogEventPatternConverter(name: String, style: String) {
>   def this(options:Array[String]) {
>     this("CustomPatternConverter", "none")
>   }
>   override def format(obj: Any, output: lang.StringBuilder): Unit = {
>     obj match {
>       case l:LogEvent => format(l, output)
>     }
>   }
>   override def format(event: LogEvent, toAppendTo: lang.StringBuilder): Unit = {
>     Option(CorrelationId.getCorrelationId) match {
>       case Some(value) => toAppendTo.append(s"[commonId=$value]")
>     }
>   }
> }
> object CustomPatternConverter {
>   @PluginFactory
>   def newInstance(options:Array[String]): CustomPatternConverter = {
>     new CustomPatternConverter(options)
>   }
> }
> object CorrelationId {
>   private val ID = new ThreadLocal[String]()
>   def clearCorrelationId(): Unit = {
>     ID.remove()
>   }
>   def setCorrelationId(id: String): Unit = setCorrelationId(Option(id))
>   def setCorrelationId(maybeId: Option[String]): Unit = {
>     maybeId foreach { ID.set }
>   }
>   def getCorrelationId: String = ID.get()
>   def generateCorrelationId: String = s"MyApp|${UUID.randomUUID().toString}"
> }{code}
> I have enabled debug with {{log4j2.debug=true}} and see debug logs but don't see evidence that the pattern converter is loaded.  I also don't see the correlation ID logged however this used to be logged under log4j1.
> Is there special configuration needed to get log4j2 to load plugins written in scala?  Or is there an error in how I've written the code above?
> I also tried without the {{@PluginFactory}} annotation without success.



--
This message was sent by Atlassian Jira
(v8.20.1#820001)