Reputation: 89
I'm working on creating a custom Log4j plugin for my project using SBT 1.9.9 scalaVersion := "2.13.9"
When I specify packages="com.testserver" in the Log4j XML configuration, everything works correctly. However, this property is deprecated, and I'm trying to configure it without using packages, but I haven't been successful.
The main issue is that Log4j fails to locate the plugin, leading to the following error:
[info] ERROR StatusConsoleListener Appenders contains an invalid element or attribute "MetadataFileAppender"
I've tried several approaches, including following the recommended setup described in the https://logging.apache.org/log4j/2.x/manual/plugins.html
Here is the relevant part of my project configuration:
lazy val core = (project in file("core"))
.settings(
name := "core",
)
lazy val server = (project in file("server"))
.dependsOn(core)
.settings(
Compile / mainClass := Some("com.testserver.Hello"),
libraryDependencies ++= Dependencies.log4j ++ Dependencies.allOthers,
name := "server",
)
lazy val root = (project in file("."))
.dependsOn(server)
.settings(
Compile / run / fork := true,
Compile / mainClass := Some("com.testserver.Hello"),
libraryDependencies ++= Dependencies.log4j,
javaOptions ++= Seq(
"-Dlog4j.configurationFile=server/src/universal/conf/log4j2.xml",
)
)
"org.log4s" %% "log4s" % "1.10.0",
"org.apache.logging.log4j" % "log4j-slf4j-impl" % log4jVersion,
"org.apache.logging.log4j" % "log4j-slf4j2-impl" % log4jVersion,
"org.apache.logging.log4j" % "log4j-core" % log4jVersion ,
"org.apache.logging.log4j" % "log4j-api" % log4jVersion
<?xml version="1.0" encoding="UTF-8"?>
<Configuration strict="true" status="info">
<Properties>
<Property name="logPattern" value="%d{dd-MM-yyyy HH:mm:ss.SSS} %msg%n"/>
<Property name="logLocation" value="/tmp/logs"/>
</Properties>
<Appenders>
<MetadataFileAppender name="MetadataFileAppender" foobar="test" location="${sys:logLocation}" />
<Console name="STDOUT">
<PatternLayout pattern="${logPattern}"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
and finally my Pluging
package com.testserver
import org.apache.logging.log4j.core.LogEvent
import org.apache.logging.log4j.core.appender.AbstractAppender
import org.apache.logging.log4j.core.config.{ Node}
import org.apache.logging.log4j.core.config.plugins.{Plugin, PluginAttribute, PluginFactory}
@Plugin(name = "MetadataFileAppender", category = Node.CATEGORY , printObject = true)
class MetadataFileAppender(name: String, foobar: String, location: String)
extends AbstractAppender(name, null, null, false, Array.empty) {
println(s"MetadataFileAppender created - my logic here ${name} ${foobar} ${location}}")
def append(event: LogEvent): Unit = {}
}
object MetadataFileAppender {
// Factory method to create the appender with file path and custom metadata content
@PluginFactory
def createAppender(
@PluginAttribute("name") name: String,
@PluginAttribute("foobar") foobar: String,
@PluginAttribute("location") location: String
): MetadataFileAppender = {
new MetadataFileAppender(name, foobar, location)
}
}
Problem Summary The MetadataFileAppender plugin works fine if I include the deprecated packages="com.testserver" property in log4j2.xml. However, I need a solution that avoids using this deprecated property. The Log4j documentation provides guidelines for setting up plugin discovery with Gradle and Maven, but nothing specific for SBT, where this should theoretically work without additional setup.
What I've Tried Direct configuration: Followed the "right way" as per the Log4j documentation. Rechecking dependencies and imports: Ensured all Log4j dependencies are correctly specified. I tried a few Refactoring log4j2.xml: Verified XML syntax and attributes. Does anyone know the correct configuration for enabling plugin discovery in SBT without the packages property, or if additional settings are required in SBT to make this work?
I also tried a few workaround hacks, including adjusting the compiler setup and importing the sbt-assembly-log4j2 plugin from GitHub, but nothing has worked so far. more info: https://github.com/mpollmeier/sbt-assembly-log4j2 Any advice or insight would be greatly appreciated!
Upvotes: 1
Views: 68
Reputation: 15090
The relevant log4j documentation states that:
Registering plugins are done by placing a Log4j plugin descriptor (i.e., Log4j2Plugins.dat) into the classpath. This file is generated using the
PluginProcessor
annotation processor at compile-time. You need to configure your build tool as follows to employPluginProcessor
by the Java compiler.
The documentation only gives example for Maven and Gradle but you need to do the same with SBT. There's nothing "magic" in SBT that would do this automatically.
So the question(s) you should be asking are:
From what I can read, you'd be able to run a Java annotation processor over Java code with SBT but not over Scala code because it has to run with the javac
compiler.
Related links:
Upvotes: 0