Spring Boot version : 2.3.5
log4jdbc version : 2.0.0
Hibernate version : 5.4.22 (pulled in by the Spring Boot Starter pack)
I am trying to capture SQL query execution related data from our Spring Boot Java application. Following are the changes I have made in our application:
pom.xml -->
<dependency>
<groupId>com.integralblue</groupId>
<artifactId>log4jdbc-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
application.properties -->
log4jdbc.drivers=oracle.jdbc.OracleDriver
log4jdbc.auto.load.popular.drivers=false
log4jdbc.debug.stack.prefix=^com\.myapp\.subpackage.*
log4jdbc.sqltiming.warn.threshold=25
log4jdbc.jdbc.sqltiming.level=DEBUG
log4jdbc.jdbc.sqltiming.logging.file=${application.logging.path}/log4jdbc.log
logback-spring.xml -->
<springProperty name="LOG4JDBC_SQLTIMING_LOGGING_FILE_NAME" source="log4jdbc.jdbc.sqltiming.logging.file"/>
<springProperty name="LOG4JDBC_SQLTIMING_LOG_LEVEL" source="log4jdbc.jdbc.sqltiming.level"/>
<logger name="jdbc.sqlonly" level="${LOG4JDBC_SQLTIMING_LOG_LEVEL}">
<appender class="ch.qos.logback.core.FileAppender">
<file>${LOG4JDBC_SQLTIMING_LOGGING_FILE_NAME}</file>
<encoder>
<pattern>${FILE_LOGGING_PATTERN}</pattern>
</encoder>
</appender>
</logger>
<!--
<logger name="jdbc.sqltiming" level="${LOG4JDBC_SQLTIMING_LOG_LEVEL}">
<appender class="ch.qos.logback.core.FileAppender">
<file>${LOG4JDBC_SQLTIMING_LOGGING_FILE_NAME}</file>
<encoder>
<pattern>${FILE_LOGGING_PATTERN}</pattern>
</encoder>
</appender>
</logger>
-->
The reason I'd commented out the last logger definition is because it did not work. So I tried to capture the 'sqlonly' logger output. When I run my application, it does generate an empty log file named "log4jdbc.log". However, the other log file capturing the generic application logs is getting generated just the same. Is there some minor mistake that is preventing this configuration setup from working as I expect it to?
Related
I have configured logback xml for a spring boot project.
I want to configure another appender based on the property configured. We want to create an appender either for JSON logs or for text log, this will be decided either by property file or by environment variable.
So I am thinking about the best approach to do this.
Using filters to print logs to 1 of the file (either to JSON or to Txt). But this will create both of the appenders. I want to create only 1 appender.
Use "If else" blocks in logback XML file. To put if else around appenders, loggers seems untidy and error prone. So will try to avoid as much as possible.
So now exploring options where I can add appender at runtime.
So I want to know if it is possible to add appender at runtime. And will it be added before spring boots up or it could be done anytime in the project.
What could be the best approach to include this scenario.
As you're already using Spring, I suggest using Spring Profiles, lot cleaner than trying to do the same programmatically. This approach is also outlined in Spring Boot docs.
You can set an active profile from either property file:
spring.profiles.active=jsonlogs
or from environment value:
spring_profiles_active=jsonlogs
of from startup parameter:
-Dspring.profiles.active=jsonlogs
Then have separate configurations per profile:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="stdout-classic" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} %magenta([%thread]) %highlight(%-5level) %logger{36}.%M - %msg%n</pattern>
</encoder>
</appender>
<appender name="stdout-json" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
<timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
</layout>
</encoder>
</appender>
<!-- begin profile-specific stuff -->
<springProfile name="jsonlogs">
<root level="info">
<appender-ref ref="stdout-json" />
</root>
</springProfile>
<springProfile name="classiclogs">
<root level="info">
<appender-ref ref="stdout-classic" />
</root>
</springProfile>
</configuration>
As the previous answer states, you can set different appenders based on Spring Profiles.
However, if you do not want to rely on that feature, you can use environments variables as described in the Logback manual. I.e.:
<appender name="json" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>true</prettyPrint>
</jsonFormatter>
<appendLineSeparator>true</appendLineSeparator>
</layout>
</encoder>
</appender>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n
</pattern>
</encoder>
</appender>
<root level="info">
<!--
! Use the content of the LOGBACK_APPENDER environment variable falling back
! to 'json' if it is not defined
-->
<appender-ref ref="${LOGBACK_APPENDER:-json}"/>
</root>
I have a Java standalone app. with a main method, with these 2 imports:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
and
private static final Logger log = LoggerFactory.getLogger(PecadorDeLaPradera.class);
In the same folder I also have a logback.xml but I don't know how to tell the program that uses the logback.xml to config the log
I couldn't find any class similar to org.apache.log4j.PropertyConfigurator
I have this logback.xml in the same folder of the Java class I am running:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- trace, debug, info, warn, error, fatal -->
<timestamp key="myTimestamp" datePattern="yyyy-MM-dd'_'HH-mm-ss.SSS"/>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- To enable JMX Management -->
<jmxConfigurator/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{"yyyy-MM-dd HH:mm"} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>pecador.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>handler.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>1MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d{"yyyy-MM-dd HH:mm"} [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!-- <logger name="org.springframework.orm.jpa" level="debug" /> -->
<logger name="com.calzada.pecador" level="debug" />
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
I also run the appl. with Program arguments:
-Dlogback.configurationFile=/Users/calzada/Dev/J2EE/eclipseWSJ2EE/myApp/src/com/calzada/pecador/logback.xml
and I got this error:
java.util.MissingResourceException: Can't find bundle for base name -Dlogback.configurationFile=/Users/nullpointer/Development/J2EE/eclipseWSJ2EE/myApp/src/com/calzada/pecador/logback.xml, locale en_ES
The library used is logback-classic-1.2.3.jar
Here's how logback configures itself:
Logback tries to find a file called logback-test.xml in the classpath.
If no such file is found, logback tries to find a file called logback.groovy in the classpath.
If no such file is found, it checks for the file logback.xml in the classpath.
If no such file is found, service-provider loading facility (introduced in JDK 1.6) is used to resolve the implementation of com.qos.logback.classic.spi.Configurator interface by looking up the file META-INF\services\ch.qos.logback.classic.spi.Configurator in the class path. Its contents should specify the fully qualified class name of the desired Configurator implementation.
If none of the above succeeds, logback configures itself automatically using the BasicConfigurator which will cause logging output to be directed to the console.
You can also point Logback at a specific configuration file using the system parameter logback.configurationFile. From the docs:
You may specify the location of the default configuration file with a system property named "logback.configurationFile". The value of this property can be a URL, a resource on the class path or a path to a file external to the application.
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1
All the above taken from the docs.
According to your question you have a logback.xml but this file is in the "same folder" as your class. Unless your class is in the root package this means that logback.xml is not in the root of the classpath so Logback will not discover it. In order for Logback to configure itself from this file you can do one of the following:
Place your logback.xml in the root of your classpath (for a Maven project this is as simple as copying logback.xml to src/main/resources)
Run your Java program with -Dlogback.configurationFile=/path/to/logback.xml
In my weblogic server I have two independent application. App1 is old web application with web services using log4j:
# Console logger
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout.ConversionPattern=%-4r %-5p %c %x - %m%n
log4j.appender.CONSOLE.Threshold=ERROR
# APP logger
log4j.appender.APP=org.apache.log4j.DailyRollingFileAppender
log4j.appender.APP.DatePattern=.yyyy-MM-dd-HH
log4j.appender.APP.File=${logfile.app}
log4j.appender.APP.encoding=UTF-8
log4j.appender.APP.layout=org.apache.log4j.PatternLayout
log4j.appender.APP.layout.ConversionPattern=%d{DATE} %-5p [%t] %-15c : %m%n
log4j.rootLogger=ERROR, CONSOLE
log4j.logger.cz.isvs=INFO, APP
log4j.logger.org.springframework=WARN, APP
${logfile.app} is replaced during build to target/log/app1.log
When there is just this application deployed everything is working OK.
Second app2 is spring boot with also web services application using logback:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProfile name="default">
<property name="LOGS_HOME" value="/app/app_logs/app2" />
<appender name="appfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS_HOME}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOGS_HOME}.log.%d{yyyy-MM-dd-HH}</fileNamePattern>
</rollingPolicy>
</appender>
<root level="error">
<appender-ref ref="appfile" />
</root>
<logger name="cz.isvs" additivity="false">
<level value="debug" />
<appender-ref ref="appfile" />
</logger>
</springProfile>
</configuration>
When I deployed second application to my weblogic server then both application is logging into app2.log. I am really confused why and how can this happened
Recently I was facing a similar issue with spring boot deployed in weblogic 12c. After investigation found that spring boot is using spring boot logger starter which has some dependency jar i.e. sl4fj, logback, jcl-over-sl4j, jul-to-slf4j, log4j-over-slf4j.jar etc.
From slf4j manual found this:
The implementation of JCL over SLF4J, i.e jcl-over-slf4j.jar, will
allow your project to migrate to SLF4J piecemeal, without breaking
compatibility with existing software using JCL. Similarly,
log4j-over-slf4j.jar and jul-to-slf4j modules will allow you to
redirect log4j and respectively java.util.logging calls to SLF4J.
The bridging jars are responsible to redirect log4j logs, java util logs, commons logging logs to logback via slf4j. After excluding the bridging jar dependencies got the expected result.
I have two applications in the same maven project and have given each of them their own configuration file by setting the spring.config.name property for each before invoking SpringApplication.run().
Thus, in the first application, I set spring.config.name to server1 so it looks for server1 instead of application.yml. In the second I have set spring.config.name to server2.
However I would like them to share the same logging configuration. Unfortunately, logging configuration cannot be imported via #PropertySource since logging is already configured before property-sources are read - see Logging section of Spring Boot manual.
Is there any way I can do this?
Spring Boot uses as default Logback. You can put a logback.xml file in src/main/resources to configure the log. And both applications will automatically use this file to configure their logging engine.
You can learn how to configure Logback here: http://logback.qos.ch/manual/configuration.html
A simple example. It will set the log level to INFO and log to the Console:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>
I'm working on a project where I thought I would try using logback-classic for debugging and log rotation. I'm using this in a Maven context for building and creating a .war file to be deployed in JBoss 7.1 Application Server.
I've placed a logback.xml file in the resources folder in the code and a logback-test.xml in test/resources.
The active jar I'm using is the SLF4J to print the actual debugging.
public class MyClass extends MultiActionController {
private Logger logger = LoggerFactory.getLogger(MyClass.class);
public MyClass() {
logger.debug("hello");
}
}
When I run a JUnit test on the code in Maven itself it works, but after building a .war file i don't get any debugging in STDOUT nor can I find a file created.
I know that I've removed the actual logging from STDOUT in the config file, but where is the logging going...
the logback.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>logs/myproject.%d{yyyy-MM-dd}.log</FileNamePattern>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyMMdd HH:mm:ss.SSS} [%-5.5level] [%-25.25logger] %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
The folder "logs" do I need to explicit create it in the JBoss instance or need to refer relative to it for this to work? Or is there something I missed? Do I need to put the logback.xml file in the JBoss instance?
best,
Henrik
Firstly you should ensure that the logback.xml is at the classpath, e.g. WEB-INF/classes/logback.xml as the mentioning at Chapter 3: Logback configuration.
The Chapter 4: Appenders mentions about FileAppender and RollingFileAppender properties as
file *String* The name of the file to write to. If the file does not exist, it is created. On the MS Windows platform users frequently forget to escape back slashes. For example, the value c:\temp\test.log is not likely to be interpreted properly as '\t' is an escape sequence interpreted as a single tab character (\u0009). Correct values can be specified as c:/temp/test.log or alternatively as c:\temp\test.log. The File option has no default value.
If the parent directory of the file does not exist, FileAppender will automatically create it, including any necessary but nonexistent parent directories.
The example is for logback.xml is as the following:-
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="FILE" />
</root>
</configuration>
I hope this may help.
You need to define the file-tag (as the previous answers already said). But you also need to know how it's interpreted. Logback sees it as relative to the application it's used in. So if you only use
<file>logs/<myfile>.log</file>
logback should create a "logs"-folder in the root of your JBoss (more specific: the folder where the .sh-script you start it with is located). Check from the root of your JBoss to see if you can find your logs-folder and file from there.