I want to change the log level of a Spring Boot application that is running.
Is it possible to change the log level at runtime? Right now I have the logger configuration in my jar itself.
Changing the log level while the application is running is part of the underlying logger implementation.
You did not specify the logger implementation you are using so I will assume you are using the default logback provided via the spring-boot-starter-logging or spring-boot-starter-web dependencies.
Comment out any logger related configurations from application.properties
e.g.
#logging.path=logs
#logging.level.org.springframework.web= INFO
#logging.level.=INFO
Add logback.xml in the root of your classpath with tag
See http://logback.qos.ch/manual/jmxConfig.html
Start the application and open JConsole and go to MBeans tab.
Select the package ch.qos.logback.classic.JMxConfigurator.Under default locate the setLoggerLevel operation
e.g. org.springframework.web, DEBUG
The change will be effective immediately.
For other logger libraries see the spring boot user guide
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html
And library specific information e.g. for log4j
http://www.sureshpw.com/2012/04/dynamic-logging-with-log4j.html
A different approach is to repeat the about steps without JMX and use configuration watcher
Logback Automatically reloading configuration file upon modification
Log4j configureAndWatch(java.lang.String, long)
If you want to change the logging level of an already running Spring Boot application you can take a look at spring-cloud-config. Refer to:
http://cloud.spring.io/spring-cloud-config/:
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server you have a central place to manage external properties for applications across all environments.
You can centrally manage the properties in config server and in your current application - applications.properties file (check bootstrap.properties) create an entry for
spring.application.name=application name
Using #RefreshScope annotation in your client application you will be able to refresh your application runtime and see the updated logging level property.
With the release of Spring Boot 1.5, if you have actuator in your Boot application you can do this through an out of the box REST API.
1.5 actuator provides an endpoint called 'loggers' which you can GET to view the configuration, and POST to make runtime changes.
Ex.
curl -i -X POST -H 'Content-Type: application/json' -d '{"configuredLevel": "DEBUG"}' http://localhost:8080/loggers/org.springframwork
Related
I have a Camel Spring Boot application where I am printing the value of a property which is set using Spring Cloud Config Server (via Git commit id plugin). The issue is that the value of the property in Camel application is not updated once the value is committed to Git. I have to restart the Camel application which fails the purpose of Spring Cloud Config server. Please note that we are using Git file system in our local machine.
The name of the properties file is CamelSpringBootSample-dev.properties.
As soon as I commit, the config server publishes the updated value at the endpoint on refresh:
http://localhost:8888/CamelSpringBootSample/dev
I have also made the Camel application end point available at:
http://localhost:8181/actuator/env
Here the value of the property is not updated on refresh. However, if I restart the Camel application, the value is reflecting.
The source code for all the three projects are uploaded in github.com.
The config server: https://github.com/sreejeshraj/config-server
The Camel client project (which uses the config server to configure itself): https://github.com/sreejeshraj/camel-config-server
Please do not get misled by the repository name camel-config-server. This is the client of config server, but I accidentally named it incorrectly, apologies.
The local git repository where the configuration properties are stored: https://github.com/sreejeshraj/Git-Config
Please note that I have used the annotation #RefreshScope in my Spring bean component class.
Can you please help me with this? Thanks in advance.
You have to set:
management.endpoints.web.exposure.include=refresh
in bootstrap.properties or bootstrap.yml.
and trigger the /actuator/refresh endpoint.
See #RefreshScope and /refresh not working
Note that as said in the comments, Camel does not update its values when a Spring beans is refreshed and there is no plan to implement this feature. (https://issues.apache.org/jira/browse/CAMEL-13892). You probably could find a solution through Spring Cloud Bus.
As #ortomala-lokni already pointed out, you need to refresh your configuration consumers after an update happened.
If you want a centralized solution for this task (for refreshing many components automatically), take a look at Spring Cloud Bus.
This page gives a quite good overview about the subject.
I had a situation where I had both application.properties and bootstrap.properties file in my client. I that case you should specify spring.application.name and spring.cloud.config.server.git.uri inside bootstrap.yml. I didn't refresh properties having spring.application.name inside applicaiton.properties.
I have a setup where I am using the following:
Spring Boot 1.5.13 with Spring Cloud Version Edgware.S3
I have Spring Cloud Config Server and my Spring Boot apps are its clients
Each app carries a bootstrap.yml with the config server uri and some other properties.
Running containers on a Docker Swarm
I am currently passing Swarm secrets to the clients via a custom script which reads the files put into /run/secrets/ and creating a /config/bootstrap.properties file. It ends up looking like this:
spring.cloud.config.username=user
spring.cloud.config.password=password
My Docker image's default command is then this:
java -Djava.security.egd=file:/dev/./urandom -jar /${appName}.jar --spring.cloud.bootstrap.location=file:/config/bootstrap.properties"
Great. This is working without a problem. The app, seemingly, reads:
The external bootstrap.properties to read in the config server's credentials
The classpath bootstrap.yml to read in the rest of the config client props
Fetches and reads in the config server's application-appName.yml
Then reads the bundled application.yml from the classpath
Now. I'm moving the apps to Spring Boot 2.0.3 with Finchley.RELEASE and well, this breaks.
What is happening now is:
The external bootstrap.properties is read in to get the config server's credentials
The classpath bootstrap.yml is SKIPPED entirely (UNEXPECTED!)
Fetches and reads in the config server's application-appName.yml
Then reads the bundled application.yml from the classpath
The problem is that the properties that were set in the internal bootstrap.yml are now missing for the app so it blows up on start. I've been able to reproduce it outside the container environment by doing the same thing; point the app to an external bootstrap.properties. If I copy over the bootstrap.yml properties into the bootstrap.properties, then it works just fine. Also, if I don't provide an external properties file, then the internal bootstrap.yml kicks in without a problem. So it's either one or the other!
I'v also tried modifying the bootstrap location to include the default locations but no luck:
-- spring.cloud.bootstrap.location=file:/config/bootstrap.properties,classpath:,classpath:/config,file:,file:config/
Any ideas where to look next? Maybe there is a new spring.cloud.config property I'm missing? Or can anyone confirm which behavior is the correct behavior? Assuming they fixed a potential loophole in Finchley then I can just put this to rest and look for another solution. If it's 'broken' in Finchley, I guess an issue report is in order?
Well, some more digging showed that it looks like this is the new behavior:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide
The behavior of the spring.config.location configuration has been fixed; it previously added a location to the list of default ones, now it replaces the default locations. If you were relying on the way it was handled previously, you should now use spring.config.additional-location instead.
It didn't look to be Spring Cloud specific but I had nothing to lose.
Changing my java command to use this new property did the trick:
--spring.config.additional-location=file:/config/bootstrap.properties
Thanks.
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.
I have a Spring boot application which use logback.xml for logging configurations.I am looking for options to dynamically change log level.
For instance if I have deployed an app with loglevel as ERROR,Let say I want to change this to INFO but I don't want to redeploy/restart my JVM.
Is there any possibility we can configure logback.xml like config server to achieve this
You can configure Logback to Automatically reloading configuration file upon modification
Yes, this is quite possible. Expose a rest endpoint where you supply the className and log level. With slf4j you can get the LoggerContext and change the level.
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
context.getLogger(className).setLevel(Level.valueOf(level));
Apache Commons logging and others have similar features.
If you are using spring cloud then you can have this in your yml file
logging:
level:
root: INFO
Then you can change it and refresh the configuration using actuator refresh to fetch new configuration changes no need to restart the service.
Also if you need some sort of UI to do this stuff you can explore the Spring-cloud-dashboard It is pretty cool and uses the features from the actuator to do and show you a lot of stuff not only changing log levels.
Spring boot currently support the following Spring Environment to System properties for logging:
Spring Environment System Property
logging.file <-----> LOG_FILE
logging.path <----> LOG_PATH
PID <-----> PID
I want to add additional custom Spring Environment properties , to be read in logback.xml, to be specific i want to add LOG_KAFKA_BROKERS <------> LOG_KAFKA_BROKERS to the KAFKA log appender
and in logback.xml has the following
<producerConfig>bootstrap.servers= ${LOG_KAFKA_BROKERS}</producerConfig>
What should I do to achieve this?
It's currently not supported by spring boot but there is an open request to have it in the next release (see https://github.com/spring-projects/spring-boot/issues/1788).
To get around it, I created a small library (https://github.com/lukashinsch/spring-boot-extended-logging-properties) that allows you to add arbitrary configuration properties to logback.xml via application.properties/yml.