Spring logging priority - spring-boot

The Spring logging documentation is available here and describes the different logging possibilities. However, something I have not been able to find is the priority of the different configurations. More concretely, in application.properties I enabled logging for showing basic authentication failures by doing:
logging.level.org.springframework.security.web.authentication.www=DEBUG
This works fines and enabled the logs I expect to see. Then I checked if I could override the configuration above via log4j2.xml by including:
<Logger name="org.springframework.security.web.authentication.www" level="ERROR" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
The change in log4j2.xml did not cause any effect. So my impression is that the logging configuration included in applications.properties takes priority over log4j2.xml (or it is read after). The only note I can see in the documentation that may be related is:
Since logging is initialized before the ApplicationContext is created,
it is not possible to control logging from #PropertySources in Spring
#Configuration files. The only way to change the logging system or
disable it entirely is through System properties.
So my assumption is that the following will happen:
Logging is configured according to log4j2.xml.
Spring loads the Application context and then the logging configuration in application.properties is taken and "wins".
So my question is, if someone knows how this is supposed to work without guessing (a link will be appreciated). NOTE: I am interested because I want to be sure that no log4j2.xml will disable the spring-security logging.
Thanks in advance!

application.properties/application.yaml take precedence over log4j2.xml - search for precedence here
Environment variables take precedence over application.properties/application.yaml
A fuller precedence list is here

Related

Can Ktor have different log levels per package/file

In spring boot, it's possible to specify a different log level at the package or even file level.
logging.level.com.company.project.monitors=DEBUG
logging.level.com.company.project.controllers=INFO
logging.level.com.company.project.controllers.utils=WARN
Is there anything similar in Ktor where we can set different logging for individual areas of the app (without writing a bunch of code)?
What you describe isn't Spring Boot specific feature as such, but of the underlying logging library both Spring Boot and Ktor use by default.
In order to achieve the same behaviour in Ktor, add the following lines to your logback.xml file:
<logger name="com.company.project.monitors" level="DEBUG" />
<logger name="com.company.project.controllers" level="INFO" />
<logger name="com.company.project.controllers.utils" level="WARN" />
The logback.xml should be located in your src/main/resources directory, if you're using Gradle as your build tool.
You can read more about Logback support in Ktor here: https://ktor.io/docs/logging.html#add_dependencies

spring boot logback refresh

I know that with config server and refresh endpoint, it is possible to dynamically change the logging level in spring boot application. To get control over the log rotation policy and json encoding for file, I decided to use logback. But this will stop me from dynamically changing the logging level.
<root level="info">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</root>
This means that only info will be written to console/file. But what if I want to change it to debug/trace during runtime?
EDIT
I still dont understand the root level tag. But the logback seems to be taking the log level from application.properties, which basically answers my question.
You can change loggig levle using spring-boot-acutuator endpiont.
To check loging level call this GET method endpoint:
http://host:port/contextpath/actuator/loggers
To check root level loggers call this GET method:
http://host:port/contextpath/actuator/loggers/root
To change root log level call this POST method endpoint:
http://host:port/contextpath/actuator/loggers/root
header: content-type: application-json
body:
{"configuredLevel": "TRACE"}
By calling this endpoint u can change root log level.

How to disable logs of Exposed Framework?

I have a kotlin desktop application with gradle builder.
I added Exposed ORM framework for my sqlite DB.
Then I noticed this framework generates a lot of logs that I don't want to see in console (I want to see only my logs generated io.github.microutils:kotlin-logging).
Is there any way to disable logs from Exposed using gradle properties?
To disable (or change logging level) you have to check your logger framework implementation documentation. Both kotlin-logging and slf4j (which used by kotlin-logging) just provide facades for logging.
For example, if you use logback you could update your configuration to show only warns and errors from an Exposed:
<configuration>
// another code here
<logger name="Exposed" level="warn" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>
</configuration>

How to use Spring environment values from config server in Logstash Encoder of Logback

I would like to use Spring environment values as custom fields in the Logstash encoder of a Logback appender.
There is a general configuration tag to use properties
<property resource="logstash.properties" />
And there is a special configuration tag from Spring for this purpose
<springProperty name="appEnv" source="environment"/>
The properties of both tags can then be used in the custom fields of the Logstash encoder
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<customFields>{"application.environment":"${appEnv}"</customFields>
</encoder>
Problem is, as far as I understand, that this only works under certain circumstances. The problem is probably that Logback has already finished configuring when the Spring environment is built.
It seems to work when
The property is local and static (available on configuration time)
The property is in bootstrap.properties
It seems NOT to work when
The property is dynamic as when retrieved from Spring config server
My property values delivered from config server are null when Logback is configured and therefore the log shows them as appEnv_IS_UNDEFINED for a property called appEnv.
Because most examples just use the spring.application.name this seems to be mostly unnoticed.
To solve the timing problem, I searched for a way to reload the Logback configuration onApplicationEvent. I found this answer that confirms my problem and offers a skeleton solution.
I found other solutions where the Logback appender that uses the Logstash encoder is completely programmatically built and added to the LoggerContext.
However, I wonder if there is also a way to stick with the XML configuration of the appender and "just reload" the config programmatically when the Spring environment is ready. How would I do this?
I found this answer to do the reload, but it does not work for my case. The appEnv_IS_UNDEFINED continue to appear in the log file.
I was able to solve my problem by implementing a Spring ApplicationContextInitializer.
In the called initialize method I can access my Logback Appender and Encoder via RootLogger.
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
RollingFileAppender jsonFileAppender = (RollingFileAppender) rootLogger.getAppender(LOGSTASH_APPENDER_NAME);
LogstashEncoder encoder = (LogstashEncoder) jsonFileAppender.getEncoder();
From the LogstashEncoder, I can get the customFields
String customFields = encoder.getCustomFields();
And there I found the unresolved properties in the JSON String as expected
{"application.environment":"appEnv_IS_UNDEFINED"}
Since I can get the built Spring Environment from the passed ApplicationContext
springEnvironment = applicationContext.getEnvironment();
I can match unresolved properties with the Regex (\w+)_IS_UNDEFINED and replace them with the real value from the Spring Environment.
Surprisingly, I do not need to reload or restart anything. It is sufficent to just set the fixed customFields on the Encoder. Immediately after, the Log messages contain the correct values.
encoder.setCustomFields(fixedCustomFields);
With this Initializer in place, I can fully configure my appender and the LogstashEncoder in logback-spring.xml or an included file.

How do I turn debug logging off, in log4j, for docx4j

I receive the following message when I deploy my maven/spring application on jboss as7 and attempt to upload a docx file. The message is displayed within the body of the uploaded file when I view it in the app's WYSIWIG editor. The message does not display when I run the app locally on jetty. I included the log4j and docx4j property files. I'm not sure what property would allow me to toggle the debug logging for the docx4j class mentioned in the error and so far I've come up empty on web searches. BTW, my app is not using a log4j/docx4j xml file and from what I've read it's an either or setup. If I should switch to xml, then please let me know and please inform me of which property needs to be adjusted so I can clear this message.
TY
TO HIDE THESE MESSAGES, TURN OFF log4j debug level logging for org.docx4j.convert.out.html.HtmlExporterNG2
log4j.properties
log4j.rootLogger=ERROR,stdout
#Console Appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%5p] [%t %d{hh:mm:ss}] (%F:%M:%L) %m%n
#Custom assignments
log4j.logger.Controllers=DEBUG,stdout
log4j.logger.Entities=DEBUG,stdout
log4j.logger.Models=DEBUG,stdout
#Disable additivity
log4j.additivity.Controllers=false
log4j.additivity.Entities=false
log4j.additivity.Models=false
docx4j.properties
# Page size: use a value from org.docx4j.model.structure.PageSizePaper enum
# eg A4, LETTER
docx4j.PageSize=LETTER
# Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum
docx4j.PageMargins=NORMAL
docx4j.PageOrientationLandscape=false
# Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum
# eg A4, LETTER
pptx4j.PageSize=LETTER
pptx4j.PageOrientationLandscape=false
# These will be injected into docProps/app.xml
# if App.Write=true
docx4j.App.write=true
docx4j.Application=docx4j
docx4j.AppVersion=2.7
# of the form XX.YYYY where X and Y represent numerical values
# These will be injected into docProps/core.xml
docx4j.dc.write=true
docx4j.dc.creator.value=docx4j
docx4j.dc.lastModifiedBy.value=docx4j
#
#docx4j.McPreprocessor=true
# If you haven't configured log4j yourself
# docx4j will autoconfigure it. Set this to true to disable that
docx4j.Log4j.Configurator.disabled=true
We had a similar issue while using docx4j with Spring Boot.
Since spring-boot-starter-logging auto-configures logback-classic which is used as implementation for loggers, it comes to just setting correct level for package. In our case we didn't need any logging from docx4j therefore adding below line to application.properties disabled whole output from 'docx4j':
logging.level.org.docx4j=OFF
If you specifically need to disable console print of document, then you need to set turn off log level on this particular file:
logging.level.org.docx4j.model.datastorage.migration.VariablePrepare=OFF
EDIT: I know this topic is old but there are very limited sources targeting this topic while using spring boot. I hope this helps someone in future.
I'm not sure how docx4j configures log4j, but you could try changing the docx4j.Log4j.Configurator.disabled=true to false instead.
If that doesn't work you might want to try excluding the servers log4j implementation. You can add a jboss-deployment-structure.xml that excludes log4j.
change the rootCategory Level from DEBUG to OFF in your log4j.properties or log4j.xml file
log4j.rootCategory=OFF, SymbolicNameForAppender
I was able to disable the logging output with the following (using docx4j 2.8.1):
Docx4jProperties.getProperties().setProperty(
"docx4j.Log4j.Configurator.disabled", "true");
Log4jConfigurator.configure();
Note that without the second statement, the logging was not suppressed.
Use following code:
Docx4jProperties.getProperties().setProperty("docx4j.Log4j.Configurator.disabled", "true");
Log4jConfigurator.configure();
org.docx4j.convert.out.pdf.viaXSLFO.Conversion.log.setLevel(Level.OFF);
Use this:
LogManager.getLogger("org.docx4j").setLevel(Level.OFF);

Resources