Re: Log4j configuration in a Groovy Script

Jochen Theodorou <[email protected]> Wed, 20 Aug 2025 15:31:27 +0200
Newsgroups gmane.comp.lang.groovy.user
Message-ID <[email protected]>

On 20.08.25 10:22, Per Nyfelt wrote:
> Interesting! I did some more testing. most combinations does work

good

> but i  found two that yield surprising results:
>=20
> 1. Instantiate=C2=A0logger without specifier gives log name as IndyInter=
face
>=20
> #!/usr/bin/env groovy
> @Grab(group=3D'org.apache.logging.log4j', module=3D'log4j-api', version=
=3D'2.20.0')
> @Grab(group=3D'org.apache.logging.log4j', module=3D'log4j-core', version=
=3D'2.20.0')
> @Grab(group=3D'org.apache.logging.log4j', module=3D'log4j-slf4j-impl', v=
ersion=3D'2.20.0')
>=20
> import org.apache.logging.log4j.Logger
> import org.apache.logging.log4j.LogManager
> import org.apache.logging.log4j.Level
>=20
> final Logger log =3DLogManager.getLogger()
> log.setLevel(Level.INFO)
> println"Running script $this.class"
> log.info('Hello world')
> // will print:
> // Running script class noSpecifierInstanceConfig
> // 10:12:18.256 [main] INFO=20
> org.codehaus.groovy.vmplugin.v8.IndyInterface - Hello world

What Log4j does is getting a stack trace in the getLogger method to then=
=20
go back by a bit and take that as class:=20
https://github.com/apache/logging-log4j2/blob/44ab0131718fc8d1fcb45604b0f1=
a8187765910d/log4j-api/src/main/java/org/apache/logging/log4j/LogManager.j=
ava#L584=20
leading to
https://github.com/apache/logging-log4j2/blob/44ab0131718fc8d1fcb45604b0f1=
a8187765910d/log4j-api-java9/src/main/java/org/apache/logging/log4j/util/S=
tackLocator.java#L81:

return WALKER.walk(s ->=20
s.skip(depth).findFirst()).map(StackWalker.StackFrame::getDeclaringClass).=
orElse(null);

Now this will just go back in the trace and use whatever it finds=20
ignoring frames from reflection. This here

getLogger(StackLocatorUtil.getCallerClass(3))

maybe this here also works:

getLogger((Class) null)

would probably work for you too. both not so nice of course

> 2. Setting the root level and give the logger the script class yields no=
=20
> output:
>=20
> #!/usr/bin/env groovy
> @Grab(group=3D'org.apache.logging.log4j', module=3D'log4j-api', version=
=3D'2.20.0')
> @Grab(group=3D'org.apache.logging.log4j', module=3D'log4j-core', version=
=3D'2.20.0')
> @Grab(group=3D'org.apache.logging.log4j', module=3D'log4j-slf4j-impl', v=
ersion=3D'2.20.0')
>=20
> import groovy.transform.Field
> import org.apache.logging.log4j.Logger
> import org.apache.logging.log4j.LogManager
> import org.apache.logging.log4j.Level
> import org.apache.logging.log4j.core.config.Configurator
>=20
> Configurator.setRootLevel(Level.INFO)
>=20
> @Field
> final Loggerlog =3DLogManager.getLogger(this.class)
> println"Running script $this.class"
>=20
> // This will NOT work, no log output is generated
> // note that LogManager.getLogger() DOES work and so does=20
> LogManager.getLogger(this.class.name <http://this.class.name>)
>=20
> log.info('Hello world')
>=20
> This will not log anything, only the println will be shown.

With "this.class" normally works for me.

> The variant with LogManager.getLogger(this.class.name)=C2=A0does work ho=
wever


strange. I mean it is doing class loading then, ok... but that should be=
=20
no other class.


> The variations i tried are here in case anyone want to verify: https://=
=20
> github.com/perNyfelt/groovy-issues/tree/main/logging/src <https://=20
> github.com/perNyfelt/groovy-issues/tree/main/logging/src>

bye Jochen