I have the following logback configuration and I am using it in a very simple Java application that does nothing except logging one line. When I uncomment the Splunk appender line it doesn't let the application exit, even though the application is finished.
Is there a way to terminate all the logging threads so that the main application exits?
logback.xml
<appender name="SPLUNK" class="com.splunk.logging.HttpEventCollectorLogbackAppender">
<url>${splunkUrl}</url>
<token>${splunkToken}</token>
<source>${projectName}</source>
<host>${COMPUTERNAME}</host>
<sourcetype>batch_application_log:json</sourcetype>
<disableCertificateValidation>true</disableCertificateValidation>
<!--<messageFormat>json</messageFormat>-->
<!--<retries_on_error>1</retries_on_error>-->
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>"%msg"</pattern>
</layout>
</appender>
<root level="INFO">
<!--<appender-ref ref="SPLUNK"/>--> if I uncomment this line application never exits
</root>
Java code
public class Main {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("******");
}
}
You could add a Logback shutdown hook, this will close all appenders and stop any active threads related to Logback.
For example:
<configuration debug="true">
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook">
<!--
the default value is 0 millis, I have included a non default
value here just to show you how it can be supplied
-->
<delay>10</delay>
</shutdownHook>
...
<configuration>
With the shutdown hook in place and debug="true" Logback will emit its own log events like so ...
08:57:19,410 |-INFO in ch.qos.logback.core.hook.DelayingShutdownHook#2bafec4c - Sleeping for 10 milliseconds
08:57:19,421 |-INFO in ch.qos.logback.core.hook.DelayingShutdownHook#2bafec4c - Logback context being closed via shutdown hook
Note: there is no requirement to use debug="true", I have only o
included that to show you how to verify that the shutdown hook has been executed.
Related
I'm trying to configure a Spring Boot project to use net.logstash.logback.encoder.LogstashEncoder to format log output in JSON and provide the ability to use the keyValue method for adding custom fields to the output. I know there are other ways of doing it, but many of our current applications using an older version of Spring use this technique and it works well. In order to update those applications, we'd like to be able to use the same configuration.
The problem I'm having is that with the following logstash.xml file:
<configuration>
<appender name="json" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
<root level="INFO">
<appender-ref ref="json" />
</root>
</configuration>
I'm getting the following error when starting the app:
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: java.lang.IllegalStateException: java.lang.IllegalStateException: Logback configuration error detected:
ERROR in net.logstash.logback.encoder.LogstashEncoder#4f659288 - Error occurred while dynamically loading jackson modules java.util.ServiceConfigurationError: com.fasterxml.jackson.databind.Module: com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module Unable to get public no-arg constructor
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:328)
at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:282)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:240)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:216)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:344)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
at com.lowes.oms.eor.services.order.Application.main(Application.java:33)
... 5 more
Caused by: java.lang.IllegalStateException: Logback configuration error detected:
ERROR in net.logstash.logback.encoder.LogstashEncoder#4f659288 - Error occurred while dynamically loading jackson modules java.util.ServiceConfigurationError: com.fasterxml.jackson.databind.Module: com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module Unable to get public no-arg constructor
at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:179)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.reinitialize(LogbackLoggingSystem.java:232)
at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:73)
at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:132)
at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:313)
... 23 more
If I look in com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module, there is a public no-arg constructor.
Relevant dependency versions:
Spring Boot*: 2.7.2
Jackson*: 2.13.3 (managed by Spring Boot)
Logback*: 1.2.11 (managed by Spring Boot)
Any thoughts on what I could be doing wrong?
Turns out this was an incompatibility between logstash-logback-encoder and jackson-datatype-hibernate5. Whenever I try to use the logstash encoder with jackson-datatype-hibernate5 on the classpath, the error occurs. I've raised an issue in the logstash github repo here: https://github.com/logfellow/logstash-logback-encoder/issues/878
We have been migrating from Log4j 1 to Logback and we have few custom appenders like below:
public class CustomAppender extends AppenderBase<ILoggingEvent> implements Runnable {}
Those attach to ch.qos.logback.classic.Logger using addAppender method when application start. All these programmatically created appenders are removed when Logback configuration file (logback.xml) changed. How can we re attach those appenders back to Logger without application restart?
Thanks
I followed the following configuration for wildfly10:
https://developer.jboss.org/thread/237094
So to be able to use slf4j and logback in my application I disabled the logging subsystem:
<jboss-deployment-structure>
<deployment>
<!-- exclude-subsystem prevents a subsystems deployment unit processors running on a deployment -->
<!-- which gives basically the same effect as removing the subsystem, but it only affects single deployment -->
<exclude-subsystems>
<subsystem name="logging" />
</exclude-subsystems>
</jboss-deployment-structure>
With this configuration my application uses correctly my logback configuration: the problem is that the server does not use anymore its own logging, so the general information are not written anymore to server.log, but they are written to my application appender.
This sounds very strange to me: I tried a lot of other configurations like excluding directly the modules (i.e. org.slf4j and org.slf4j.impl) on my jboss-deployment-structure.xml file but with no effect.
I am using the MariaDb4j library for my integration tests and it registers a shutdown hook, this way:
protected void cleanupOnExit() {
String threadName = "Shutdown Hook Deletion Thread for Temporary DB " + dataDir.toString();
final DB db = this;
Runtime.getRuntime().addShutdownHook(new Thread(threadName) {
#Override
public void run() {
// ManagedProcess DestroyOnShutdown ProcessDestroyer does
// something similar, but it shouldn't hurt to better be save
// than sorry and do it again ourselves here as well.
try {
// Shut up and don't log if it was already stop() before
if (mysqldProcess != null && mysqldProcess.isAlive()) {
logger.info("cleanupOnExit() ShutdownHook now stopping database");
db.stop();
}
} catch (ManagedProcessException e) {
logger.warn("cleanupOnExit() ShutdownHook: An error occurred while stopping the database", e);
}
if (dataDir.exists() && Util.isTemporaryDirectory(dataDir.getAbsolutePath())) {
logger.info("cleanupOnExit() ShutdownHook quietly deleting temporary DB data directory: " + dataDir);
FileUtils.deleteQuietly(dataDir);
}
if (baseDir.exists() && Util.isTemporaryDirectory(baseDir.getAbsolutePath())) {
logger.info("cleanupOnExit() ShutdownHook quietly deleting temporary DB base directory: " + baseDir);
FileUtils.deleteQuietly(baseDir);
}
}
});
}
This was working fine.
But then I added Logback and created a Console appender.
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>${defaultPattern}</Pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
If I set the Logging level to WARN or ERROR it is still working fine, but when I set it to INFO or lower then I get this exception:
Exception: java.lang.IllegalStateException thrown from the UncaughtExceptionHandler in thread "Shutdown Hook Deletion Thread for Temporary DB /var/folders/t5/lr8ytf257hb9_649cjp9hkn40000gn/T/MariaDB4j/data/3306"
"Shutdown Hook Deletion Thread for Temporary DB... " is the name of the thread registered in the first piece of code above.
The result is that I am left with a mysqld process running. And that prevents the tests to run again as MariaDB4j complains about it and won't start a new database.
Once I kill the mysqld process than I can run my tests again, but then same thing happens.
I assume this is a JVM problem. I don't see how the logging level can prevent a shutdown hook to work properly.
I use MariaDB4j in my integration tests. When I run them with IntelliJ or Eclipse it do not get this error. I only get it when I run them with gradle (as part of the build task).
What could be causing that and how to get around it?
I had similar problem. It was caused by Gradle issue which is described there.
It can be solved by downgrading Gradle to version 3.2 or upgrading to version 3.5.
I have an application that is deployed on OpenShift. I have the below configuration on log back.xml.
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<prudent>true</prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}myLogFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>5</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} %p %t %c{1}.%M - %m%n</pattern>
</encoder>
I can read on the server $logPath is properly substituted and logback file has no problems in terms of setting properties. However it doesn't write the log file at the specified place. I tried this with specifying a file property and setting prudent to "false" as well, still no luck. I checked the permissions on the file system there are no problems, creating and writing a file at the specified location. I'm using log back 1.1.2.
Note: I checked this question and it's answer. Setup for a Logback RollingFileAppender with prudent flag and a file location
Does anybody have an idea what could be wrong here? I hope there isn't a bug with TimeBasedRollingPolicy
Updating ticket to clarify variable substitution (per logback documentation http://logback.qos.ch/manual/configuration.html#variableSubstitution )
${logPath} variable is substituted during build time (in jenkins) and the war file generated bears the correct path to the log file. Then this war file is deployed to Tomcat.