A note: we could use the REST API to change logging levels. The configbaker image could carry scripts with well known / often used parts of Dataverse and accept list of stuff where to enable / disable logs.
I'd rather like to have means to configure the log levels via a documented ENV variable...
How should such an env var look like?
And would you be OK with rebooting the container or should it be possible to alter logging while running?
I would love spring like syntax...https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#appendix.application-properties
Could you sketch an example?
Similar to this [1]. However, I'm not sure if that works with current configuration slf4j-jdk11. It does work with log4j and logback...
I think @Don Sizemore does something like that with a properties file. Not sure.
Yeah, there is domain1/config/logging.properties.
I have it on the agenda: https://ct.gdcc.io
3 minutes! :clock:
Initially, I would be sufficient to configure the input for as-admin set-log-level via env vars. This requires a restart but already eases the container debugging..
@Johannes D have your say during the meeting! We're on now :smile:
Johannes D said:
Initially, I would be sufficient to configure the input for
as-admin set-log-levelvia env vars. This requires a restart but already eases the container debugging..
to my experience, Glassfish and (now) Payara pick up changes to logging.properties on-the-fly, unless you're averse to cat and/or awk/sed?
O rly? On the fly?
If thats the case, we could just update the init_2_configure.sh script to echo an ENV var to the file, right?
We probably put this in the base image, not the app image script. This is useful for more than just the app image.
One thing we need to take care of: we must not "just write in the file". This will write into the overlayfs, which is a baaaaad idea
So here's a thought. We could make a script sit in the background within the container, watch for some logging config to appear somewhere (on K8s that would be a mounted configmap key or similar, autoupdating on change), merge it with the original and replace it. I already put the infrastructure in place to do such things in a safe way with the init system in place. @Johannes D @Don Sizemore what do you think?
@Oliver Bertuch Sound good!
Yesterday, I made PR #9863 that changes log levels (as a workaround for #9806). I used asadmin, like normal.
Should we have an issue or at least a note to track what we want to change? Use the REST API to change logging levels? Is that it?
Issues sounds good :-)
Would you like to do the honors? :big_smile:
Oliver Bertuch said:
So here's a thought. We could make a script sit in the background within the container, watch for some logging config to appear somewhere (on K8s that would be a mounted configmap key or similar, autoupdating on change), merge it with the original and replace it. I already put the infrastructure in place to do such things in a safe way with the init system in place. Johannes D Don Sizemore what do you think?
sounds great to me. in my experience Payara picks up changes to logging.properties on the fly, so your changes could be as granular (numerous) as needed.
We're talking about this again. :grinning: See https://docs.google.com/document/d/1toiFxJKGvrYMy9KrW9GZ4U6FLGhMaCipJ9ggtvZFwgc/edit?usp=sharing
Here's the recording: https://harvard.zoom.us/rec/share/LtMO_BjkgEHvqdgjnCv9V0ko6_I3L-VZ-wZapO6JiZf9aFRSs7tkDP182plACuus.fnTfrsTArCtjKFng
I'm investigating adding a JUL to SLF4J bridge to make use of Logback for the server logs. Logback supports hot-reloading logging config files as well as MDC etc.
It would be neat if we make Dataverse use SLF4J instead of JUL, too.
That way we could make use enabling debugging stream in production more selectively, e.g. for a single user.
(Reason for me looking into this: I want to disable warnings about missing property files for our custom metadata block where we just don't care...)
But JUL is the standard. Shouldn't we use the standard? Fewer dependencies.
A standard with flaws...
We need SLF4J anyway. Best practice for any library, plugin etc is to use a logging facade. Usually that is SLF4J
If we're talking standards and less deps: one should use System.Logger then :wink:
Yesterday I really dug deep into this. OSGi and everything.
It looks like we cannot use the SLF4JBridge handler without getting the application involved.
The logging is initialized very early in the boot process from glassfish/modules/logging.jar, which is an OSGi module. Looking into that one reveals that it has a MANIFEST that declares a certain class path and it seems impossible to make some other lib appear on that path from the outside. (At least I don't know how to do that.)
I even went ahead and forked https://github.com/goodees/goodees/blob/master/payara-logback/README.adoc into a more modern version, but no luck to inject it.
It seems we're stuck with JUL... Glassfish completely rewrote their logging subsystem to use "GlassFish Java Util Logging Extension", see also https://www.youtube.com/watch?v=j2gACdwWyNk
What we can do though is to enable switch between log formats, e.g. from ULF to JSON. JSON logs are much better to handle when using fluentd etc to ship the logs to analysis. We need to set java.util.logging.ConsoleHandler.formatter using env var support. Defaulting to com.sun.enterprise.server.logging.UniformLogFormatter, obviously...
Notes to self:
From that video: "For GlassFish 7 we completely changed the logging system". Interesting. Does that apply to us, though? Since we're on Payara?
I might have been doing it wrong with how I added the packages... Maybe I need to retry with what is written here: https://docs.payara.fish/community/docs/Technical%20Documentation/Application%20Development/Class%20Loaders.html#extension-libraries
Also, I did add a modules.java - maybe I sealed the package by accident, so it could not load any classes from it.
I've been looking into Observability as of late. A part of OpenTelemetry infrastructure like Sentry, Loki etc is sending these tools logs.
It makes a lot of sense to enable such things in containers, as all of these tools are often around in a container production environment, especially when running on K8s
Nice. I think this topic was originally about changing log levels on the fly. I still don't know how to do this. ![]()
So now I'm wondering if I should use the JUl-to-SFL4J bridge to re-route all messages from JUL to Logback
With Logback, you can use JMX to change the logging levels on the fly without app restarts
orly
With Logback, you can use a config file which can be reloaded dynamically
So maybe that gives us leverage to support all of these cases!
So I'd say we could include https://github.com/jiaqi/jmxterm in the image / configbaker or maybe even add REST Admin API endpoints that change the levels using JMX
We definitely need to make use of a proper logging library for the non-standard logs of Dataverse... :grimacing:
Otherwise it's hard to get them out. Or at least make sure the path where they are written is configurable, so one can use a sidecar container to ship them.
Writing these logs to the overlayfs is a baaaaad idea
Sure, should we take this to #dev? Or start with a GitHub issue to log properly?
Let's just keep this here for a moment. This is mostly a brain dump, so I can circle back later.
@Philip Durbin โ๏ธ Do you think we could get a PR into Dataverse that changes all loggers from JUL to SLF4J?
That would spare us some of the hassle (not all, as Payara uses JUL internally)
JUL is the standard but it's no good?
Technically JUL is an implementation.
It's a part of the JDK since 1.4
These days, if you want it in a Jakarta like way, the industry standard is SLF4J.
That's the facade and there are plenty of implementations around to send it to some concrete log system
Are we doing it right in https://github.com/IQSS/dataverse-hub or https://github.com/IQSS/dataverse-marketplace ? /cc @Juan Pablo Tosca Villanueva
Note to self: keep https://github.com/goodees/goodees/tree/master/payara-logback in mind and OpenTelemetry log shipping.
So I've pogged and prodded on this a bit today, trying to use Claude 3.7 to mix together an HK2 model to load SLF4J bridge plus Logback. So far, no success. Might give this tomorrow another shot. If this doesn't work out, I'm wondering if I should just create a patched Payara version that ships with the necessary libs added to the core.
@pdurbin is that overkill, creating such a patch? Not sure if the upstream would accept it... they don't seem very interested in this.
We could of course create an issue for this and vote vote vote vote. :grinning_face_with_smiling_eyes:
whatever you do, it would be nice to get it into upstream
PROGRESS!
[#|2025-05-19T21:34:59.403+0000|SEVERE|Payara 6.2025.3|jakarta.enterprise.logging|_ThreadID=34;_ThreadName=RunLevelControllerThread-1747690499218;_TimeMillis=1747690499403;_LevelValue=1000;_MessageID=NCLS-LOGGING-00002;|
Could not apply the logging configuration changes.
MultiException stack 1 of 2
com.sun.enterprise.module.ResolveError: Failed to start OSGiModuleImpl:: Bundle = [io.gdcc.payara-logback-hk2 [396]], State = [NEW]
[...]
Caused by: org.osgi.framework.BundleException: Unable to resolve io.gdcc.payara-logback-hk2 [396](R 396.0): missing requirement [io.gdcc.payara-logback-hk2 [396](R 396.0)] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j)(version>=2.0.0)(!(version>=3.0.0))) Unresolved requirements: [[io.gdcc.payara-logback-hk2 [396](R 396.0)] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j)(version>=2.0.0)(!(version>=3.0.0)))]
This stuff is hard.
YESSSS
#!## LogManagerService.postConstruct : rootFolder=/opt/payara/appserver/glassfish
#!## LogManagerService.postConstruct : templateDir=/opt/payara/appserver/glassfish/lib/templates
#!## LogManagerService.postConstruct : src=/opt/payara/appserver/glassfish/lib/templates/logging.properties
#!## LogManagerService.postConstruct : dest=/opt/payara/appserver/glassfish/domains/domain1/config/logging.properties
SLF4J Bridge bundle is starting...
Installing SLF4J Bridge Handler
Go go go! ![]()
Note to self: apparently the class loading didn't properly work out. Maybe try again with an Extension Library and add to bootdelegation? https://docs.payara.fish/community/docs/6.2025.7/Technical%20Documentation/Application%20Development/Class%20Loaders.html#installing-libraries
Last updated: Oct 30 2025 at 05:14 UTC