customize log file name from code in springboot - spring-boot

I have a simple springboot application with rest end points. Every time I call the rest end point, it performs a certain activity. Right now, all the logging information goes to server.log file in wildfly. I would like to have a scenario where i can customize the name of the log file everytime my rest end points are invoked. For e.g.
All logging information from point A to Point B shall goto a file called First.log and all the logging information from point B to Point C shall goto Second.log
Is such an implementation possible either by using logback or log4j2. can i customize the name of the log file from code where in I specify every logging information from this point on should go to a specific file.

If you are using Log4j2, you can reconfigure it at runtime with Configurator#reconfigure.
The standard log4j2.xml file used by Spring Boot (cf. Github) uses the Java system property LOG_FILE to store the location of the log file. Therefore you just need to:
configure Spring Boot to log to a file (cf. documentation). For example you can add:
logging.file.name = initial.log
to your `application.properties,
whenever you want to change the name of the log file call
System.setProperty("LOG_FILE", "first.log");
Configurator.reconfigure();
Log4j2 guarantees you that no message will be lost during reconfiguration (the old file is closed after the new one has been created).
There is certainly a similar solution for Logback, but Logback can lose messages during reconfiguration.

Related

Can I move Spring Boot logging settings out of application.properties file and into an untracked file?

I am working on building a SpringBoot app with my workmates. We all have different preferred logging levels for the app. We have been battling back and forth with each other's logging changed to application.properties. Is there a way to move all of the logging.level.* stuff out of that application.properties file and into a ~logging.properties file or something? That way we can add that file to the .gitignore and not track that file so we can each leave our logging alone. We are using Java annotations and not xml btw.
I've tried adding #PropertySource("classpath:logging.properties") to the application file, but I read somewhere that the logging gets setup early on in the init process and this won't work. I tried it anyway and it doesn't work (so confirmed I guess).
I can't believe there's isn't more info on this out there.. I'd imagine the members of a dev team each want their own custom level of logging and don't want to keep stepping on each other's toes/commits.
You can just override it using a command line property. The fallback strategy will take command line -D args as the highest overriding priority.
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
I would recommend to have logback.xml file inside resources/ with some defaults that works for everyone (more likely to the application in question) and then you can provide --logging.config=/path/to/your/very/custom/logback.xml file whenever you start the application locally.
That should work for everyone.

How to specify Log4j2 configuration file in spring boot application

I am using log4j2 in my spring boot application. This works in all respects re: excluding slf4j, including log4j2, etc.
But when the application deploys I need to customize the file for each target host. I have created an ansible role that does this. Ultimately I end up with a log4j2.xml file deployed in another directory e.g. /prod/produsrX/data/log4j2.xml.
I am using the spring-boot-maven-plugin "repackage" goal to generate an executable jar file. It doesn't seem like that should matter but it is a data point in the problem.
This was supposed to be the easiest part of the project. Always before I have just been able to set -Dlog4j.configurationFile - advice which is echoed on about 3,000 web pages and DOES NOT WORK in Spring Boot 2.1.3.
The most useful info I've found is this question. It talks about using -Dlogging.config because logging must be initialized before other properties are read. Unfortunately that didn't help either.
I did find one example that suggested specifying the above directory in a -classpath parameter to java. But that didn't help either.
Does anyone know how to get a spring boot application to read the log4j2.xml file?
The property actually has to be put into the application context (e.g. application.yml). Using a -D property does not work!
logging:
config: /prod/produsrX/data/log4j2.xml #fully qualified name to your log4j.xml

Logback with Spring Boot - programatically change configuration at runtime to add Syslog Appender

I am building an application (Spring Boot 1.4.2) where i would like to offer an administrator the option to enable syslog but i want to avoid him/her having to manually edit any config files - in this case logstash-spring.xml.
Therefore i am trying to understand how i can achieve using a logback-spring.xml file as a baseline (e.g. define file based log options, levels etc. - settings i dont want the administrator to change) and on top of that provide a functionality at runtime where an administrator can add or change a syslog appender.
I have listed what i see as requirements:
The changes made to the Logger should be persisted after the Spring Boot application is restarted.
Ideally the syslog server info (name, port) are kept in my persistence layer (H2, hibernate) but i am not sure if that is possible as i guess the logging framework is being injected prior to my persistence layer?
The syslog appender that i want to add should be referenced by root logger so that all the packages i have configured logging for would go to syslog (not sure if this is just "how it works per default")
Also i dont know if i could simply treat logback-spring.xml as a regular XML object and use for example JAXB to manipulate that file and use the autoscan feature of Logback to simply read in the new changes?
I have played around with defining a Logger #Bean:
#Bean
public Logger logger() {
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
// excluded implementation
}
This is being picked up by Spring Boot but that brings me to the 2 items i have listed above that i dont know how or where i would store the syslog server information the administrator would provide.
UPDATE:
I wrote the following which meets the 3 requirements above however i would appreciate any feedback on the actual implementation as i am very new to Spring and Java.
GitHub repository with implementation - spring-boot-logback-syslog
I managed to use the example i posted in my Github repo in my designated application and with that i am answering my own questions based on the implementation in that repo.
Please refer to the README for full details on how it was implemented.
UPDATE: As part of Spring Boot 1.5.1 there is an actuator that can set the logging level during runtime: Production Ready Loggers
Not necessarily 100% related to this topic but this was one of the requirements i had for the implementation as well as changing syslog related settings.

Actuator - custom logfile endpoint possible?

I have set up my log configuration using logback.
The configuration sets up my logs in a rolling manner in a custom location. This means that I'm not using either:
"logging.file" or "logging.path" in my application.yml configuration, and as a consequence, the logfile endpoint no longer works.
Does anybody know of a way to customize this endpoint, so that I can point to the location/file specified in my logback.xml configuration?
Reading the two sections on Logging 26 & 74. It looks like it recommends using the logback-spring.xml config file with the base.xml configuration. With that you can still use the logging.file or logging.path application properties within the configuration. That way the /logfile endpoint is still valid for the current log file (probably won't look into the rolling files if that is what you setup).
You can specify the log file source from which the actuator will read.
To do that, try to use this property in your application.properties
endpoints.logfile.external-file=/var/log/app.log
or (based on your springboot version):
management.endpoint.logfile.external-file=/var/log/app.log

How does my spring web app capture errors that I didn't catch and log? Is this a result of apache commons?

I'm confused as to how the errors are logged without me implicitly catching them and logging out the error. All that I've done is put a log4j.xml file in my project defining appenders and now the logs catch and log everything from the frameworks.
If I say, try to query in Hibernate and the query fails, or I try to open a file that doesn't exist, or I get a null pointer exception, if the log4j.xml file defines a log file, and the error level is set correctly, then the error will be captured there?
How does my spring web app capture errors that I didn't catch and log? Is this a result of apache commons logging?
Or is this some magic that log4j knows how to deal with - catch stream to the console etc?
Any info appreciated.
From spring official documentation:
The nice thing about commons-logging is that you don't need anything else to make your application work. It has a runtime discovery algorithm that looks for other logging frameworks in well known places on the classpath and uses one that it thinks is appropriate (or you can tell it which one if you need to). If nothing else is available you get pretty nice looking logs just from the JDK (java.util.logging or JUL for short). You should find that your Spring application works and logs happily to the console out of the box in most situations, and that's important.
To make Log4j work with the default JCL dependency (commons-logging)
all you need to do is put Log4j on the classpath, and provide it with
a configuration file (log4j.properties or log4j.xml in the root of the
classpath).
Take a look for a complete explanation: http://static.springsource.org/spring/docs/3.0.x/reference/overview.html#d0e743

Resources