Giter Club home page Giter Club logo

logback's Introduction

About logback

Thank you for your interest in logback, the reliable, generic, fast and flexible logging library for Java.

The Logback documentation can be found on the project web-site as well as under the docs/ folder of the logback distribution.

Java EE and Jakarta EE versions

Given that downstream users are likely to depend on either Java EE (in the javax namespace) or on Jakarta EE (in the jakarta namespace) in their projects, it was deemed important for logback to support both EE alternatives.

Version 1.3.x supports Java EE, while version 1.4.x supports Jakarta EE. The two versions are feature identical.

Both 1.3.x and 1.4.x series require SLF4J 2.0.x or later.

The 1.3.x series requires Java 8 at runtime. If you wish to build logback from source, you will need Java 9.

The 1.4.x series requires Java 11 at build time and at runtime.

Building logback

Version 1.3.x requires Java 9 to compile and build.

More details on building logback is documented at:

https://logback.qos.ch/setup.html#ide

In case of problems

In case of problems please do not hesitate to post an e-mail message on the [email protected] mailing list. However, please do not directly e-mail logback developers. The answer to your question might be useful to other users. Moreover, there are many knowledgeable users on the logback-user mailing lists who can quickly answer your questions.

Urgent issues

For urgent issues do not hesitate to champion a release. In principle, most championed issues are solved within 3 business days followed up by a release.

Pull requests

If you are interested in improving logback, great! The logback community looks forward to your contribution. Please follow this process:

  1. Please file a bug report before filing a pull requests. Note that pull requests wit an associated JIRA issue will get more attention. Moreover, your pull request is unlikely to be merged without an associated jira issue.

    Optional: Start a discussion on the logback-dev mailing list about your proposed change.

  2. Fork qos-ch/logback. Ideally, create a new branch from your fork for your contribution to make it easier to merge your changes back.

  3. Make your changes on the branch you hopefully created in Step 2. Be sure that your code passes existing unit tests.

  4. Please add unit tests for your work if appropriate. It usually is.

  5. Push your changes to your fork/branch in GitHub. Don't push it to your master! If you do it will make it harder to submit new changes later.

  6. Submit a pull request to logback from your commit page on GitHub.

Continuous integration build status

Branch Last results
master CI master
1.3 branch CI 1.3 branch

logback's People

Contributors

ash2k avatar brenuart avatar ceharris avatar ceki avatar chrisdolan avatar dave-r12 avatar diroussel avatar dwijnand avatar ericdahl avatar hanneswell avatar hazendaz avatar hkupty avatar huxi avatar ingebrigt avatar jkuipers avatar johngmyers avatar jon-ruckwood avatar kalgon avatar kovacevicm avatar motlin avatar nurkiewicz avatar panchenko avatar reinhapa avatar richardfearn avatar rkapsi avatar sierragolf avatar solidjb avatar timclemons avatar tony19 avatar wuwen5 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

logback's Issues

Appender class substitution is not implemented - is there a reason?

A short snippet

    <appender name="STDOUT" class="${APPENDER_CLASS:-ch.qos.logback.core.ConsoleAppender}">
        <layout class="${LAYOUT_CLASS:-some.custom.Layout}">
            <hostName>${HOSTNAME}</hostName>
        </layout>

In this example, the layout class may be specified via env variable, which is useful to switch between different receivers.
However, the APPENDER_CLASS will not be substituted, throwing an error:

Caused by: java.lang.ClassNotFoundException: ${APPENDER_CLASS:-ch.qos.logback.core.ConsoleAppender}

Is there any particular reason for this behaviour?
It is tempting to "fix" it by changing line #23 to

appenderModel.setClassName(interpretationContext(attributes.getValue(CLASS_ATTRIBUTE)));

However, it doesn't seem to be a correct fix, as SaxEventInterpretationContext interpretationContext seems to not be used at all

no-janino conditions

Feature request:
pls make possible to write conditions without janino.
it should allow to use conditions with native image for example.

I suggest something like a predicate-like interface that user would implement and use like so:

<if predicateClass="org.example.MyCondition">

or it could be a static method

Observability of async logging queue

Hello. Is there any way to gather metrics on the internal queue used by async logger? Things like current capacity, nb of info logs dropped, nb of logs dropped when full, etc.

If not available would that be an interesting contribution?

Thanks.

DoS Vulnerability was discovered in logback-core

Summary

Denial of service vulnerability in logback-core was discovered by CIFuzz. Method new CyclicBuffer(int) and CyclicBuffer.resize(int) can receive a too big number which can lead to OOM.

POC

pom

<dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-core</artifactId>
       <version>1.4.11</version>
</dependency>

code1

CyclicBuffer cyc = new CyclicBuffer(1611270666);

image

code2

CyclicBuffer cyc = new CyclicBuffer(123);
cyc.resize(1611270666);

image

logfile midnight error

I have started the same JAR file on the same server using two different ports, and I'm writing logs to the same log file. The log file should be split by day and when it reaches 30MB, a new log file should be created. However, I'm facing the following issue: after midnight, one of the services is still writing logs to the file from the previous day and not creating a new one, while the other service is working correctly. What could be the reason for this?

lQLPJxXl-T6EVczNAYPNA9iwtquJMuI65psFGlEibtN3AA_984_387

`

<springProperty scope="context" name="logfile.home" source="server.logfile.home"/>
<springProperty scope="context" name="logLevel" source="server.loglevel"/>
<springProperty scope="context" name="profiles.active" source="spring.profiles.active"/>



<appender name="ERRORFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${logfile.home}/error/error.log</file>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>WARN</level>
    </filter>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <FileNamePattern>${logfile.home}/error/error.%d{yyyy-MM-dd}-%i.log</FileNamePattern>
        <MaxHistory>60</MaxHistory>
        <totalSizeCap>2GB</totalSizeCap>
        <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <MaxFileSize>30MB</MaxFileSize>
        </TimeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>
    <encoder>
        <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%p] [%t] [%class{35}] [%X{supplierId}-%X{userId}][%X{deviceSn}][%X{traceId}] [%m]%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

<appender name="DEBUGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${logfile.home}/debug/debug.log</file>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>DEBUG</level>
    </filter>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <FileNamePattern>${logfile.home}/debug/debug.%d{yyyy-MM-dd}-%i.log</FileNamePattern>
        <MaxHistory>1095</MaxHistory>
        <totalSizeCap>30GB</totalSizeCap>
        <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <MaxFileSize>30MB</MaxFileSize>
        </TimeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>
    <encoder>
        <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%p] [%t] [%class{35}] [%X{supplierId}-%X{userId}][%X{deviceSn}][%X{traceId}] [%m]%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <neverBlock>true</neverBlock>
    <queueSize>512</queueSize>
    <appender-ref ref="DEBUGFILE" />
</appender>

<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG"/>
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG"/>
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG"/>

<root level="${logLevel}">
    <appender-ref ref="DEBUGFILE"/>
    <appender-ref ref="ERRORFILE"/>
</root>

`

Make logback access logging work with Jetty 12

Jetty 12 has been released July 20, 2023 and it is the latest stable release of Jetty: https://projects.eclipse.org/projects/rt.jetty/releases/12.0 . There has been quite many changes in Jetty 12 compared to earlier versions. One of the biggest change is probably "The Servlet-Api has been removed from the internals of Jetty allowing for non-servlet-based application creation."

These changes in Jetty 12 seems to make logback access logging not to work at all when using Jetty 12. At least I don't get any errors or stacktraces in logs but it just silently does not work. I am assuming that the problem might be in the log method of logback's RequestLogImpl:

public void log(Request jettyRequest, Response jettyResponse) {
        JettyServerAdapter adapter = makeJettyServerAdapter(jettyRequest, jettyResponse);
        IAccessEvent accessEvent = new AccessEvent(this, jettyRequest, jettyResponse, adapter);
        if (getFilterChainDecision(accessEvent) == FilterReply.DENY) {
            return;
        }
        aai.appendLoopOnAppenders(accessEvent);
    }

So in the log method parameters it takes org.eclipse.jetty.server.Request and passes that to the constructor of AccessEvent which assumes that the request should implement jakarta.servlet.http.HttpServletRequest. This has worked just fine with Jetty 10 and 11. But the case in Jetty 12 is that due to the big change mentioned above, org.eclipse.jetty.server.Request no longer implements jakarta.servlet.http.HttpServletRequest.

In Jetty 10 and 11, Request class is defined as public class Request implements HttpServletRequest: https://github.com/jetty/jetty.project/blob/jetty-10.0.x/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java#L145

In Jetty 12, Request class is defined as public interface Request extends Attributes, Content.Source: https://github.com/jetty/jetty.project/blob/jetty-12.0.x/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java#L122

So my guess is that the access logging most likely silently breaks due to this problem and should somehow be able to change org.eclipse.jetty.server.Request -> jakarta.servlet.http.HttpServletRequest or make AccessEvent to accept org.eclipse.jetty.server.Request or some other better solution. Same problem is of course with the jettyResponse object.

Also package structure has changed in Jetty 12 a bit: https://webtide.com/new-jetty-12-maven-coordinates/ but not sure if this package structure change has any impact on logback since logback does not seem to reference classes in org.eclipse.jetty.eeX packages but only org.eclipse.jetty.server.*.

There is org.eclipse.jetty.ee9.nested.Request in Jetty 12 which implements HttpServletRequest but using that is probably not an option to use since it seems to be Jetty internal class and would then depend on the org.eclipse.jetty.eeX packages.

There has been some plans that Jetty 10 and 11 will probably reach end of life in couple of years, possibly in 2025, so would be good time to start preparing logback to also work with Jetty 12.

Incorrect tag for release 1.4.12

Thanks for maintaining this great software! Just dropping by to share the observation that the most recent release was tagged as 4.1.12 rather than 1.4.12: the major and minor version components are swapped.

SpringBoot boot error ,unrecognized feature http://xml.org/sax/features/external-general-entities

SpringBoot 3.1.5

image

<============ 🚀  JAVA版本:21  CPU核心数:4  🚀 ============>
18:43:09.194 [main] INFO hxy.dream.app.Application -- 当前CPU核心=4main是否为守护线程=false
Logging system failed to initialize using configuration from 'classpath:logback-spring.xml'
java.lang.IllegalStateException: Could not initialize Logback logging from classpath:logback-spring.xml
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:250)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.withLoggingSuppressed(LogbackLoggingSystem.java:460)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:242)
	at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithSpecificConfig(AbstractLoggingSystem.java:66)
	at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:57)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:189)
	at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:335)
	at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:298)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:174)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:145)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:133)
	at org.springframework.boot.context.event.EventPublishingRunListener.multicastInitialEvent(EventPublishingRunListener.java:136)
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:81)
	at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:64)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118)
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112)
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:63)
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:360)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295)
	at hxy.dream.app.Application.main(Application.java:30)
Caused by: ch.qos.logback.core.joran.spi.JoranException: Error during parser creation or parser configuration
	at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:99)
	at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:62)
	at ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(GenericXMLConfigurator.java:184)
	at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:158)
	at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
	at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LogbackLoggingSystem.java:285)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.lambda$loadConfiguration$1(LogbackLoggingSystem.java:247)
	... 25 more
Caused by: org.xml.sax.SAXNotRecognizedException: unrecognized feature http://xml.org/sax/features/external-general-entities
	at org.gjt.xpp.sax2.Driver.setFeature(Driver.java:178)
	at org.gjt.xpp.jaxp11.SAXParserImpl.setFeatures(SAXParserImpl.java:149)
	at org.gjt.xpp.jaxp11.SAXParserImpl.<init>(SAXParserImpl.java:132)
	at org.gjt.xpp.jaxp11.SAXParserFactoryImpl.newSAXParserImpl(SAXParserFactoryImpl.java:114)
	at org.gjt.xpp.jaxp11.SAXParserFactoryImpl.setFeature(SAXParserFactoryImpl.java:142)
	at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:88)
	... 32 more
Disconnected from the target VM, address: '127.0.0.1:51293', transport: 'socket'

Process finished with exit code 1

Logback 1.4.12 outputs “default THREAD FACTORY” to stdout

Logback 1.4.12 has a small issue. It prints “default THREAD FACTORY” to System.out. When looking at the diff between 1.4.11 and 1.4.12 it's immediately showing up as a simple System.out.println.

Here's the diff between 1.4.11 and 1.4.12:

Problem is in the file logback-core/src/main/java/ch/qos/logback/core/util/ExecutorServiceUtil.java.

In fact it prints to System.out in 2 places inside the makeThreadFactory method:

if(EnvUtil.isJDK21OrHigher()) {
    // ...
    System.out.println("virtual THREAD FACTORY");
    // ...
} else {
    System.out.println("default THREAD FACTORY");
    // ...
}

logback SizeAndTimeBasedRollingPolicy not working and filling up the storage

Hi Team,

In our recent rollout, we had a bug in code, which started generating a very high volume of logs and we are expecting logback to remove old logs and keep the storage space in control.
However this was not the case, log files were not removed and storage was filling and bringing the entire appliance to a halt.

log back config:
maxHistory: 2
maxFileSize: 25MB
totalSizeCap: 75MB

Logs generated per sec: 25MB(1.5 GB per minute/ 1 million lines per minute)
Max file size: 25MB, so every second one log file is generated.
Max CAP size: 75MB
within 3 sec the MAX cap is met.
Storage available is 24 GB.
The time taken to fill up the storage is 16Min(1.5 GB per minute generation rate)

I can see logs are successfully written into files but old files are not deleted.

The expectation here is that logback has to clean up old files every 3 seconds to keep up with config and maintain storage. I am not sure this functionality working.

and I need below info if some can help me:

  1. Is maxFileSize, maxHistory, and totalSizeCap is checked for each log message event?
  2. In the documentation it says the async process, Does it mean writing to log files and removal of old files are independent?
  3. Is removing old files serialized?

Below are config we used
`




<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>${CONSOLE_PATTERN}</pattern>
    </encoder>
</appender>
<appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold>
    <queueSize>10000</queueSize>
    <appender-ref ref="STDOUT"/>
    <includeCallerData>true</includeCallerData>
</appender>

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_DIR}/spring.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <FileNamePattern>${LOG_DIR}/spring-%d{yyyyMMdd}.%i.log</FileNamePattern>
        <maxHistory>2</maxHistory>
        <maxFileSize>25MB</maxFileSize>
        <totalSizeCap>75MB</totalSizeCap>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>${FILE_PATTERN}</pattern>
    </encoder>
</appender>
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold>
    <queueSize>10000</queueSize>
    <appender-ref ref="FILE"/>
    <includeCallerData>true</includeCallerData>
</appender>

<logger name="org.springframework.scheduling.support.TaskUtils" level="OFF"/>
<logger name="io.jaegertracing.internal" level="OFF"/>
<logger name="org.apache.ignite.internal" level="OFF"/>
<logger name="org.springframework.web.client" level="OFF"/>

<root level="${SERVICE_LOG_LEVEL}">
    <appender-ref ref="ASYNC_STDOUT"/>
    <appender-ref ref="ASYNC_FILE"/>
</root>

`

Support Removal of ConfigurationEventListener

Originally published in the Logback-Dev Mailing list:


I refer to commit dd2b9fe that enabled
the Context interface to handle a ConfigurationEvent.

Currently, there is only a method to register a
ConfigurationEventListener. It would be useful to have another method to
deregister such a listener. What's more, the current source describes
the registration method as follows:

"The propagation of {@link ConfigurationEvent configuration events} is
intended for internal testing as well as some coordination between
configurators."

I believe a ConfigurationEvent is generally useful. The documentation
should acknowledge that.

BACKGROUND

I use Logback in a Spring web application and need to register
LoggingEvent filter beans programmatically. This requires to hook into
Spring's lifecycle and to perform registration / deregistration on bean
initialization and destruction. Special attention needs to be taken to
Logback's configuration reload. In this case I need to hook into
ReconfigureOnChangeTask to realize when reload has ended since all
filter beans need to be registered again. This can be performed with the
help of listeners, all of which have some drawbacks:

  • LoggerContextListener#onReset( context) : This fires before the
    Logback configuration file has been read and thus, before appenders are
    available. Registration of LoggingEvent filters is not possible here.
  • StatusListener#addStatusEvent( status) : Fires more often (on each
    status message). It is hard to realize the "end of configuration" state
    from just a message, a level and the notifying instance. This also does
    not seem like a stable and consistent solution to me.
  • ReconfigureOnChangeTaskListener#doneReconfiguring( ) : Could be the
    right choice but is currently unused, package-private and was probably
    never intended for general usage.
  • ConfigurationEventListener#listen( configurationEvent) : Seems to be
    ideal since one can identify the end of Logback's configuration
    (ConfigurationEvent#CONFIGURATION_ENDED). This, however, does not offer
    a method to deregister a corresponding listener. The point is I need to
    cleanup resources on shutdown of Spring's ApplicationContext because
    Logback's LoggerContext is a shared singleton that survives Spring. It
    should be easy to add a deregistration method here.

Handle if dynamical selector throws an Exception

Pull request #634 simply adds a try-catch block around the selector initialization so that if a custom selector throws an exception, logback will continue with the default selector instead of throwing an exception back to the container and failing

Action rules are not added to Rule Store

Why is in this class action only created, but addRule is commented in version 1.4.11 ch.qos.logback.core.joran.spi.SimpleRuleStore#addRule(ch.qos.logback.core.joran.spi.ElementSelector, java.lang.String)

we are not able to use censoring from com.tersesystems.logback:logback-censor because line below in our logback is basicaly useless

<newRule pattern="*/censor" actionClass="com.tersesystems.logback.censor.CensorAction"/>

the problem is that ch.qos.logback.core.joran.action.NewRuleAction#begin on line 51 is calling old ec.getSaxEventInterpreter().getRuleStore().addRule(new ElementSelector(pattern), actionClass); addRule method which have commented line on addRule() after initialization of new action

No logs in AWS CloudWatch since upgrading from v1.4.8

In our Maven-based Java-Lambdas we get no application logs if we upgrade from logback-core & logback-classic v1.4.8 to 1.4.9 and above (even with everything else staying the same).
I couldn't find anything in the Release Notes or elsewhere that could explain this.

The applications use:

  • logback-core & logback-classic v1.4.x
  • log4j-api, log4j-jul & log4j-to-slf4j v2.22.0
  • slf4j-api 2.0.9 & jcl-over-slf4j v2.0.9
  • logstash-logback-encoder v7.4

Reload in logback 1.2.6 not working

Hello,
I have used scan="true" and scanPeriod =1 minute in logback configuration file. Still it is not taking up the changes done in configuration file at runtime.Always need to restart application.
logback-classic version : 1.2.6
logback-core version : 1.2.6

DoS Vulnerability was discovered in logback-core

Summary

Denial of service vulnerability in logback-core was discovered by CIFuzz. Method new CyclicBuffer(int) and CyclicBuffer.resize(int) can receive a too big number which can lead to OOM.

POC

pom

<dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-core</artifactId>
       <version>1.4.11</version>
</dependency>

code1

CyclicBuffer cyc = new CyclicBuffer(1611270666);

image

code2

CyclicBuffer cyc = new CyclicBuffer(123);
cyc.resize(1611270666);

image

Jansi 2.4.0 color-coded output not working properly on CMD.EXE console

On Windows, when I use logback 1.4.14 with Jansi 2.4.0 in the old CMD.EXE console, the logback fails to produce color-coded output. The same code executed in Windows Terminal works as expected.

Interestingly, substituting the current Jansi 2.4.0 with an older Jansi 1.18, seems to fix the issue. This suggests that there might be some differences in the newer versions of Jansi that Logback doesn't handle very well.

The following ZIP contains a simple example (requires Java 11+) that produces colored output using standalone Jansi 1.18 and 2.4.0, and Logback with Jansi 1.18 and 2.4.0. To execute: extract and run jansi-examples.bat

jansi-examples.zip

Here's the output produced on the same machine in CMD.EXE console:

image

and in Windows Terminal:

image

Allow alternative ways to specify contextselector

Pull request #671 allows the system environment or a JNDI variable to choose an alternate ContextSelector. This allows the use of JEE deployment descriptors to choose an alternative selector. Consider two JEE applications deployed in the same container that want to use different selectors. This very trivial code update enables this capability

MDC Properties Not Associated with Log Statements

Starting from version 1.4.8 of Logback, an issue has been observed where MDC properties are no longer associated with log statements when a custom MDCAdapter, for instance com.twitter.inject.logging.FinagleMDCAdapter, is set in the application.

The likely root cause is that, beginning with version 1.4.8, Logback obtains the MDCAdapter from ch.qos.logback.classic.LoggerContext instead of directly getting it from MDC. Consequently, the application ends up using two separate and independent MDCAdapters concurrently.

You can find a simplified application created to reproduce this issue in the following repository:
https://github.com/naser-ayat/logback-bug-reproducer

Some file are licensed only under the LGPL v2.1 only

LoggerContext initialization error results in NoSuchMethodError with SLF4j 2.0.10

As of SLF4j 2.0.10, the internal org.slf4j.helpers.Util.report method is commented out: https://github.com/qos-ch/slf4j/blob/v_2.0.10/slf4j-api/src/main/java/org/slf4j/helpers/Util.java#L120-L124

Unfortunately, this method is being used in Logback to report errors initializing the LoggerContext: https://github.com/qos-ch/logback/blob/v_1.4.14/logback-classic/src/main/java/ch/qos/logback/classic/spi/LogbackServiceProvider.java#L49-L65

The result is that if the LoggerContext initialization fails for whatever reason (e.g. an exception thrown in some component's start method), a NoSuchMethodError is thrown and bubbles up to the caller, most likely causing the application using it to exit. In contrast, with SLF4j 2.0.9, an error message is printed including the stack trace of the root cause exception, and no exception is thrown to the caller, so the rest of the program can work as usual (except without logs).

NullPointerException: LOGABCK-1717 regression

Hi,
Starting with logback-classic version 1.4.9, I have the following error:

java.lang.NullPointerException: Cannot invoke "java.lang.ClassLoader.loadClass(String)" because "classLoader" is null
	at ch.qos.logback.classic.util.ContextInitializer.instantiateConfiguratorByClassName(ContextInitializer.java:104)
	at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:94)
	at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:65)
	at ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:52)
	at ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:41)
	at org.slf4j.LoggerFactory.bind(LoggerFactory.java:195)
	at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:182)
	at org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:490)
	at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:476)
	at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:425)

This error happens because the jdk specifies that getClassLoader() may return null when the class is loaded from the bootstrap classloader. See here.

Unfortunately, since the commit LOGABCK-1717, autoConfig() will throw a NullPointerException when getClassLoader() returns null. The same code is working fine with version 1.4.8 and below.

logback 1.2.6 AsyncAppender-Worker-ASYNC_STDOUT worker thread hang at native write method.

The AsyncAppender-Worker-ASYNC_STDOUT worker stack is as follows:

at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122)

  • locked [0x00000000b013a610] (a java.io.BufferedOutputStream)
    at java.io.PrintStream.write(PrintStream.java:480)
  • locked [0x00000000b011d570] (a java.io.PrintStream)
    at java.io.FilterOutputStream.write(FilterOutputStream.java:97)at ch.qos.logback.core.joran.spi.ConsoleTarget$1.write(ConsoleTarget.java:37)
    at ch.qos.logback.core.OutputStreamAppender.writeBytes(OutputStreamAppender.java:199)
    at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:231)
    at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:102)
    at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
    at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
    at ch.qos.logback.core.AsyncAppenderBase$Worker.run(AsyncAppenderBase.java:290)
    --

then the arrayBlockingQueue soon be full, and all business threads stand awaiting.
It happened once, and is difficult to repeat in the production environment.
Could you tell me how can I find the cause of what happened in the invocation of write?
The Java application runs in the containerd runtime on linux os orchestrated by Kubernetes. thanks!

SiftingAppender with Async and File Appender is not working at 1.4 logback

Hi all,

I had the below logback xml in old 1.2 version and it works fine.
But when I upgrade to logback 1.4 , it starts to not working.
I guess it is related to nested Appender which is not allowed anymore.

However I cannot move out some Appender as the name is base on the category id.
Is it intended to not support below anymore? any workaround .

Very thanks you for any suggestion

the below have warning
As of logback version 1.3, nested appenders are not allowed.

<appender class="ch.qos.logback.classic.sift.SiftingAppender" name="SwiftGH">
        <discriminator>
            <defaultValue>unknown</defaultValue>
            <key>category</key>
        </discriminator>
        <sift>
            <appender class="ch.qos.logback.classic.AsyncAppender" name="async-${category}">
                <appender class="ch.qos.logback.core.FileAppender" name="logss-${category}">
                    <append>true</append>
                    <file>chat-${category}.log</file>
                </appender>
            </appender>
        </sift>
</appender>

A way to serialize a model: CLI, web, else

Unless I'm missing something obvious, there's no easy way to serialize the Logback model to scmo file.

One way to do that is to include <serializeModel file="..."> into XML config. When Logback runs such a configuration, it'll serialize itself into the given file. Two problems here. First, it's not very convenient to get a serialized model only when the app starts, especially when maintaining shared configuration, meaning there's no app to start to begin with. Second, the serialized model contains a model to serialize itself, so every time the app starts, it creates a new scmo file.

It would be so much better if there was a CLI tool that users could point to XML files and get SCMO files as an output.

[Question] LOGBACK-1731 using variables in path names

Hello, we are facing the same issue mentioned in https://jira.qos.ch/browse/LOGBACK-1731 and we hoped, it will be fixed in 1.4.12 (as it is listed in fix-versions)

It seems that there was a change in when we migrated from 1.2 to 1.4
Using scope="system" seems to work in spring.

It seems that there is some logical order problem
As far as I could debug the issue, logback builds a "Model" which represents the complete config (with all included files)
and then, the properties are evolved. So due this order problem, it is not possible to use parameters in include tags. (Note: I'm not very familiar with the architecture in logback, so this is just a guess, what I've ssen in debugger)

When you apply scope="system" - logback puts the value in the system-properties. As spring reloads the logback config at least once, the next run can access the value from the previous run.

Note: we do not really rely on this issue if our use cases could be solved in an other way

Our use cases

1. We want to include an optional properties file (which might not exist)

Preferred solution:

<property file="config/application-local.properties" optional="true"/>

This does not work, because there is no optional support for property and the produced error will prevent spring to run the application

Current solution:

<!-- We define a property, that evaluates to "true", if the file exists -->
<define name="APPLICATION_LOCAL_EXISTS" class="ch.qos.logback.core.property.FileExistsPropertyDefiner" scope="system">
	<path>config/application-local.properties</path>
</define>
<!-- if file exists, we include  application-local.properties-true.inc.xml. 
     If the property file does not exist, no XML is found. 
     This works, because 'include' supports 'optional=true' -->
<include resource="logback/application-local.properties-${APPLICATION_LOCAL_EXISTS}.inc.xml" optional="true"/>

<!-- content of application-local.properties-true.inc.xml -->
<included>
	<property file="config/application-local.properties"/>
</included>

Yes this is a workaround, and I'm sure it was not intended to use it this way, but it did work with 1.2

possible fix
Add 'optional' to 'property'

2. We want to include different appenders.

<property name="consoleAppender" value="${de.foconis.log.console.appender:-CONSOLE}" scope="system"/>
<root>
	<appender-ref ref="${consoleAppender}"/>
</root>

By default we want to use the CONSOLE appender, we have also other appenders like CONSOLE_ANSI, CONSOLE_JSON which formats the output to console in a different way.

If we put all appenders "ready for use" in the logback.xml we get warnings like Appender named [CONSOLE_ANSI] not referenced. Skipping further processing. - so we split them up into a CONSOLE.appender.inc.xml, CONSOLE_ANSI.appender.inc.xml, CONSOLE_JSON.inc.xml and include the dedicated file with

<include optional="true" resource="logback/${consoleAppender}.appender.inc.xml"/>

possible fix
Add 'optionalUse' to 'appender'. If this is set, no warnings are printed, if appender is not in use.

RollingFile Appender creates .tmp files

When file compression is enabled and triggered (gz or zip) and the program exits before Logback can complete the compression, the .tmp files created.

Logback file:

<configuration scan="true">
<shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/>
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${BW_LOG_DIR}/test.log</file>
    <!-- <fileNamePattern>${BW_LOG_DIR}/test.log</fileNamePattern> -->
    <append>true</append>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>${BW_LOG_DIR}/test.log.%d{yyyy-MM-dd}.log%i.zip</fileNamePattern>
<!-- each file should be at most 100MB, keep 60 days' worth of history, but at most 1GB -->
<maxFileSize>1KB</maxFileSize>
<maxHistory>0</maxHistory>
<totalSizeCap>1KB</totalSizeCap>
 </rollingPolicy>
 <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] &lt;%X{operationID}&gt; %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

I tried of using shutdownhook as you can see in the above snippet but still .tmp files are generated. I am using logback-core version 1.2.10.
Please help me out with the above issue.

Handling of <include> with properties changes form 1.2.x to 1.3.x

Hello everyone,

we just realized that logback behaves differently when handling the inclusion of files that use properties.
This different behavior was introduced with version 1.3.0 and its changes to the configuration implementation.
I'm not sure whether this is actually a bug. Perhaps we relied on something that was never intended to work.

Our usecase

We want to include a configuration snippet multiple times and use properties to slightly change the snippet every time.

A very simple example is an appender definition with a name derived from a property:

<included>
    <appender name="${name}" class="ch.qos.logback.core.ConsoleAppender">
        <!-- ... -->
    </appender>
</included>

Now we want to include this snippet to create appenders with different names:

    <property name="name" value="A" />
    <include resource="snippet.xml"/>

    <property name="name" value="B" />
    <include resource="snippet.xml"/>

Thus, we want to pass parameters to the snippet.

Version 1.2.x

This works fine with version 1.2.12.
Here's the status log:

09:45:03,179 |-INFO in ch.qos.logback.core.joran.util.ConfigurationWatchListUtil@566776ad - Adding [file://snippet.xml] to configuration watch list.
09:45:03,180 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
09:45:03,182 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [A]
09:45:03,203 |-INFO in ch.qos.logback.core.joran.util.ConfigurationWatchListUtil@566776ad - Adding [file://snippet.xml] to configuration watch list.
09:45:03,205 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
09:45:03,205 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [B]

Version 1.3.x

This doesn't work anymore since version 1.3.0. It doesn't work with 1.4.11 neither.
The properties value is always B (as seen by the included snippets).

10:12:35,409 |-INFO in ch.qos.logback.core.joran.util.ConfigurationWatchListUtil@7b49cea0 - Adding [file:///snippet.xml] to configuration watch list.
10:12:35,413 |-INFO in ch.qos.logback.core.joran.util.ConfigurationWatchListUtil@7b49cea0 - Adding [file:///snippet.xml] to configuration watch list.
10:12:35,458 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - Processing appender named [B]
10:12:35,458 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
10:12:35,476 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - Processing appender named [B]
10:12:35,477 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]

In our real world use case the application does not start anymore, since logback detects the same file name pattern to be used multiple times.

Collisions detected with FileAppender/RollingAppender instances defined earlier. Aborting.

The file name pattern is defined by a property. The file appenders are included with a snippet.

Related issues

There is an open feature request to support passing of parameters to included snippets in a different way: https://jira.qos.ch/browse/LOGBACK-1104
If this is not considered a bug, I vote for this feature request.

https://jira.qos.ch/browse/LOGBACK-1760 might be related, even though the variable is used in the <include> tag not in the included snippet.
Since this ticket states 1.4.12 as fix version, I tried our use case with the 1.4.12-SNAPSHOT but it doesn't work.

Thank you for your support!

How to customiz my owner contextSelector?

I checked that, the logic about contextSelectorBinder had been abandoned by @ceki almost 7 years ago.

The commit is 6660751

image

seems like logback do not support customize my owner contextSelector any more. can I get the reason? and if logback still support the customization, can anyone tell me the new way?

Exception when Upgraded to 1.4.13

hantsy/spring6-sandbox#501

In My Spring 6 example, when upgrading to 1.4.13, it failed the tests run on Github actions.

0.040 s <<< ERROR!
java.lang.NoSuchMethodError: 'java.lang.ClassLoader ch.qos.logback.core.util.Loader.systemClassloaderIfNull(java.lang.ClassLoader)'
	at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:73)
	at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:66)
	at ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:52)
	at ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:41)

Receiver - Can't handle model of type ReceiverModel with tag: receiver

Attempting Logback receiver feature I get this error:
ERROR in ch.qos.logback.core.model.processor.DefaultProcessor@76b10754 - Can't handle model of type class ch.qos.logback.classic.model.ReceiverModel with tag: receiver at line 11

My setup:

  • Arch Linux 6.5.5 kernel
  • Logback 1.3.11 (also tried other versions, including 1.4.x. 1.3 is prefered since I am stuck with java 8 in prod)
  • SLF4J 2.0.9 (also tried 2.0.7)
  • Java 8,11,17 all give same result
  • Also tried run application in a docker-container to rule out my environment ( maven:3.5-jdk-8)

To reproduce:
Structure:

./
├── pom.xml
└── src/
   └── main/
      ├── java/
      │  └── logbackreceiver/
      │     └── server/
      │        └── Main.java
      └── resources/
         └── logback.xml

Main.java:

package logbackreceiver.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
  private static final Logger logger = LoggerFactory.getLogger(Main.class);
  static public void main(String[] args) {
    logger.info("Starting");
  }
}

logback.xml:
(I also tried the canonical style with same result)

<configuration debug="true">
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%date]-%msg%n</pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="CONSOLE" />
    </root>
    <receiver class="ch.qos.logback.classic.net.server.ServerSocketReceiver">
        <port>3331</port>
    </receiver>
</configuration>

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>home.logbackreceiver</groupId>
  <artifactId>server</artifactId>
  <packaging>jar</packaging>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>
  <version>1.0-SNAPSHOT</version>
  <name>logbackreceiverserver</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.3.11</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.3.11</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-access</artifactId>
      <version>1.3.11</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>2.0.9</version>
    </dependency>
  </dependencies>
</project>

To build and run:

mvn clean compile && sudo mvn exec:java -Dexec.mainClass="logbackreceiver.server.Main"

Following the guide here: https://logback.qos.ch/manual/receivers.html
I also cloned code from github (various versions here too) and run the example codes. Everything give me the same problem.
I tried various versions of Logback (3.x and 4.x). I tried Java 8,11,17
I would prefer to make Logback 3.x to work since I am stuck with Java 8 in prod.

I even tried run it in a Docker-container to rule out problems in my environment.

Complete log:

12:50:25,651 |-INFO in ch.qos.logback.classic.LoggerContext[default] - This is logback-classic version 1.3.11
12:50:25,652 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - No custom configurators were discovered as a service.
12:50:25,652 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - Trying to configure with ch.qos.logback.classic.joran.SerializedModelConfigurator
12:50:25,652 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - Constructed configurator of type class ch.qos.logback.classic.joran.SerializedModelConfigurator
12:50:25,664 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.scmo]
12:50:25,664 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.scmo]
12:50:25,664 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - ch.qos.logback.classic.joran.SerializedModelConfigurator.configure() call lasted 12 milliseconds. ExecutionStatus=INVOKE_NEXT_IF_ANY
12:50:25,664 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - Trying to configure with ch.qos.logback.classic.util.DefaultJoranConfigurator
12:50:25,665 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - Constructed configurator of type class ch.qos.logback.classic.util.DefaultJoranConfigurator
12:50:25,665 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
12:50:25,665 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/home/x/Projects/logbackreceiver/server/target/classes/logback.xml]
12:50:25,722 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - Processing appender named [CONSOLE]
12:50:25,722 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
12:50:25,725 |-INFO in ch.qos.logback.core.model.processor.ImplicitModelHandler - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
12:50:25,729 |-INFO in ch.qos.logback.classic.model.processor.RootLoggerModelHandler - Setting level of ROOT logger to DEBUG
12:50:25,729 |-INFO in ch.qos.logback.core.model.processor.AppenderRefModelHandler - Attaching appender named [CONSOLE] to Logger[ROOT]
12:50:25,730 |-ERROR in ch.qos.logback.core.model.processor.DefaultProcessor@270251cf - Can't handle model of type class ch.qos.logback.classic.model.ReceiverModel  with tag: receiver at line
10
12:50:25,730 |-WARN in ch.qos.logback.core.model.processor.ImplicitModelHandler - Ignoring unknown property [port] in [ch.qos.logback.classic.LoggerContext]
12:50:25,730 |-ERROR in ch.qos.logback.core.model.processor.DefaultProcessor@270251cf - Can't handle model of type class ch.qos.logback.classic.model.ReceiverModel  with tag: receiver at line
10
12:50:25,730 |-INFO in ch.qos.logback.core.model.processor.DefaultProcessor@270251cf - End of configuration.
12:50:25,730 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@49fe6dec - Registering current configuration as safe fallback point
12:50:25,730 |-INFO in ch.qos.logback.classic.util.ContextInitializer@2e8123ad - ch.qos.logback.classic.util.DefaultJoranConfigurator.configure() call lasted 65 milliseconds. ExecutionStatus=DO_NOT_INVOKE_NEXT_IF_ANY
[2023-09-29 12:50:25,731]-Starting

JsonEncoder message is not interpolated

Invoking log.info("Destroyed {} gracefully in {} ms.", process, duration) doesn't interpolate the values in the message field when using JsonEncoder.

The arguments are there in the arguments array so technically interpolation can be done downstream (e.g. the consumer of the ndjson-formatted output) but this is a bit surprising and makes integration with log sinks harder.

Any plans to have some form of interpolation supported here? I'd be happy to provide a PR.

appender can't be added to AsyncAppender after being detached.

1. behavior

appender can't be added to AsyncAppender after being detached.

2. reproduce and test case

add following test in AsyncAppenderBaseTest

    @Test
    @Timeout(value=2, unit = TimeUnit.SECONDS)
    public void appenderShouldBeAddedSuccessfullyAfterDetachedByReference() {
        asyncAppenderBase.addAppender(listAppender);
        asyncAppenderBase.start();
        asyncAppenderBase.doAppend(0);
        asyncAppenderBase.detachAppender(listAppender);
        asyncAppenderBase.addAppender(listAppender);
        asyncAppenderBase.doAppend(0);
        asyncAppenderBase.stop();
        verify(listAppender, 2);
    }

3. cause

the value of property "appenderCount" does't decrease in method "detachAppender", the value is 1 after first addAppender, and still 1 after detachAppender, so when addAppender again, it goes into "else".

  public void addAppender(Appender<E> newAppender) {
        if (appenderCount == 0) {
            appenderCount++;
            addInfo("Attaching appender named [" + newAppender.getName() + "] to AsyncAppender.");
            aai.addAppender(newAppender);
        } else {
            addWarn("One and only one appender may be attached to AsyncAppender.");
            addWarn("Ignoring additional appender named [" + newAppender.getName() + "]");
        }
    }

thread blocked in virtual thread envrionment with 1.4.14 version

Env

  • Logback version :1.4.14
  • Springboot version: 3.2.1
  • My server framework with a reactor model which is like the opensource framework-tars :https://github.com/TarsCloud/TarsJava . I support the virtual thread model .
  • The stress request qps: 30_000/s
  • javaVersion:openjdk version "21" 2023-09-19/OpenJDK Runtime Environment (build 21+35-2513)/OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)

Problem

  • My server thread was blocked by logger.error method. And then my program cannot handle new request.

the request and response

The thread stack

  • You can see my reactor thread is waiting for the logger.error method.

  • The full thread stack is in the added file.
    stack1.txt

  • the jcmd thread dump info(jcmd Thread.dump_to_file ):
    thread_jcmdaa.txt
    thread_jcmdab.txt

"ts-reactor-0" #47 [693] prio=5 os_prio=0 cpu=195123.31ms elapsed=69926.73s tid=0x00007fbc7a0daf10 nid=693 waiting on condition  [0x00007fbc4cebf000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@21/Native Method)
	- parking to wait for  <0x0000000759b899e8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(java.base@21/LockSupport.java:371)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@21/AbstractQueuedSynchronizer.java:519)
	at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@21/ForkJoinPool.java:3780)
	at java.util.concurrent.ForkJoinPool.managedBlock(java.base@21/ForkJoinPool.java:3725)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@21/AbstractQueuedSynchronizer.java:1707)
	at java.util.concurrent.ArrayBlockingQueue.put(java.base@21/ArrayBlockingQueue.java:370)
	at ch.qos.logback.core.AsyncAppenderBase.putUninterruptibly(AsyncAppenderBase.java:186)
	at ch.qos.logback.core.AsyncAppenderBase.put(AsyncAppenderBase.java:177)
	at ch.qos.logback.core.AsyncAppenderBase.append(AsyncAppenderBase.java:166)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
	at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:386)
	at ch.qos.logback.classic.Logger.error(Logger.java:539)
	at com.huya.taf.net.core.nio.TCPSession.handleVtServer(TCPSession.java:218)
	at com.huya.taf.net.core.nio.TCPSession.readRequest(TCPSession.java:177)
	at com.huya.taf.net.core.nio.TCPSession.read(TCPSession.java:140)
	at com.huya.taf.net.core.nio.TCPAcceptor.handleReadEvent(TCPAcceptor.java:111)
	at com.huya.taf.net.core.nio.Reactor.dispatchEvent(Reactor.java:197)
	at com.huya.taf.net.core.nio.Reactor.run(Reactor.java:114)

"ts-reactor-1" #48 [694] prio=5 os_prio=0 cpu=223469.95ms elapsed=69926.73s tid=0x00007fbc7a0eda90 nid=694 waiting on condition  [0x00007fbc4ce7e000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@21/Native Method)
	- parking to wait for  <0x0000000759b899e8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(java.base@21/LockSupport.java:371)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@21/AbstractQueuedSynchronizer.java:519)
	at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@21/ForkJoinPool.java:3780)
	at java.util.concurrent.ForkJoinPool.managedBlock(java.base@21/ForkJoinPool.java:3725)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@21/AbstractQueuedSynchronizer.java:1707)
	at java.util.concurrent.ArrayBlockingQueue.put(java.base@21/ArrayBlockingQueue.java:370)
	at ch.qos.logback.core.AsyncAppenderBase.putUninterruptibly(AsyncAppenderBase.java:186)
	at ch.qos.logback.core.AsyncAppenderBase.put(AsyncAppenderBase.java:177)
	at ch.qos.logback.core.AsyncAppenderBase.append(AsyncAppenderBase.java:166)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
	at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:386)
	at ch.qos.logback.classic.Logger.error(Logger.java:539)
	at com.huya.taf.net.core.nio.Reactor.disConnectWithException(Reactor.java:144)
	at com.huya.taf.net.core.nio.Reactor.run(Reactor.java:117)

"ts-reactor-2" #49 [695] prio=5 os_prio=0 cpu=196075.69ms elapsed=69926.73s tid=0x00007fbc7a0eec00 nid=695 waiting on condition  [0x00007fbc4ce3d000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@21/Native Method)
	- parking to wait for  <0x0000000759b895b8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
	at java.util.concurrent.locks.LockSupport.park(java.base@21/LockSupport.java:221)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@21/AbstractQueuedSynchronizer.java:754)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(java.base@21/AbstractQueuedSynchronizer.java:990)
	at java.util.concurrent.locks.ReentrantLock$Sync.lock(java.base@21/ReentrantLock.java:153)
	at java.util.concurrent.locks.ReentrantLock.lock(java.base@21/ReentrantLock.java:322)
	at java.util.concurrent.ArrayBlockingQueue.remainingCapacity(java.base@21/ArrayBlockingQueue.java:485)
	at ch.qos.logback.core.AsyncAppenderBase.isQueueBelowDiscardingThreshold(AsyncAppenderBase.java:170)
	at ch.qos.logback.core.AsyncAppenderBase.append(AsyncAppenderBase.java:162)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
	at ch.qos.logback.classic.Logger.filterAndLog_2(Logger.java:419)
	at ch.qos.logback.classic.Logger.info(Logger.java:592)
	at com.huya.taf.net.core.nio.TCPSession.handleVtServer(TCPSession.java:208)
	at com.huya.taf.net.core.nio.TCPSession.readRequest(TCPSession.java:177)
	at com.huya.taf.net.core.nio.TCPSession.read(TCPSession.java:140)
	at com.huya.taf.net.core.nio.TCPAcceptor.handleReadEvent(TCPAcceptor.java:111)
	at com.huya.taf.net.core.nio.Reactor.dispatchEvent(Reactor.java:197)
	at com.huya.taf.net.core.nio.Reactor.run(Reactor.java:114)

"ts-reactor-3" #50 [696] prio=5 os_prio=0 cpu=194924.27ms elapsed=69926.73s tid=0x00007fbc7a0f0020 nid=696 waiting on condition  [0x00007fbc4cdfc000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@21/Native Method)
	- parking to wait for  <0x0000000759b899e8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(java.base@21/LockSupport.java:371)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@21/AbstractQueuedSynchronizer.java:519)
	at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@21/ForkJoinPool.java:3780)
	at java.util.concurrent.ForkJoinPool.managedBlock(java.base@21/ForkJoinPool.java:3725)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@21/AbstractQueuedSynchronizer.java:1707)
	at java.util.concurrent.ArrayBlockingQueue.put(java.base@21/ArrayBlockingQueue.java:370)
	at ch.qos.logback.core.AsyncAppenderBase.putUninterruptibly(AsyncAppenderBase.java:186)
	at ch.qos.logback.core.AsyncAppenderBase.put(AsyncAppenderBase.java:177)
	at ch.qos.logback.core.AsyncAppenderBase.append(AsyncAppenderBase.java:166)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
	at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:386)
	at ch.qos.logback.classic.Logger.error(Logger.java:539)
	at com.huya.taf.net.core.nio.TCPSession.handleVtServer(TCPSession.java:218)
	at com.huya.taf.net.core.nio.TCPSession.readRequest(TCPSession.java:177)
	at com.huya.taf.net.core.nio.TCPSession.read(TCPSession.java:140)
	at com.huya.taf.net.core.nio.TCPAcceptor.handleReadEvent(TCPAcceptor.java:111)
	at com.huya.taf.net.core.nio.Reactor.dispatchEvent(Reactor.java:197)
	at com.huya.taf.net.core.nio.Reactor.run(Reactor.java:114)

"ts-reactor-4" #51 [697] prio=5 os_prio=0 cpu=194829.49ms elapsed=69926.73s tid=0x00007fbc7a0f15b0 nid=697 waiting on condition  [0x00007fbc4cdbb000]
   java.lang.Thread.State: WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@21/Native Method)
	- parking to wait for  <0x0000000759b899e8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(java.base@21/LockSupport.java:371)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@21/AbstractQueuedSynchronizer.java:519)
	at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@21/ForkJoinPool.java:3780)
	at java.util.concurrent.ForkJoinPool.managedBlock(java.base@21/ForkJoinPool.java:3725)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@21/AbstractQueuedSynchronizer.java:1707)
	at java.util.concurrent.ArrayBlockingQueue.put(java.base@21/ArrayBlockingQueue.java:370)
	at ch.qos.logback.core.AsyncAppenderBase.putUninterruptibly(AsyncAppenderBase.java:186)
	at ch.qos.logback.core.AsyncAppenderBase.put(AsyncAppenderBase.java:177)
	at ch.qos.logback.core.AsyncAppenderBase.append(AsyncAppenderBase.java:166)
	at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:85)
	at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:51)
	at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
	at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
	at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:426)
	at ch.qos.logback.classic.Logger.filterAndLog_2(Logger.java:419)
	at ch.qos.logback.classic.Logger.info(Logger.java:592)
	at com.huya.taf.net.core.nio.TCPSession.handleVtServer(TCPSession.java:208)
	at com.huya.taf.net.core.nio.TCPSession.readRequest(TCPSession.java:177)
	at com.huya.taf.net.core.nio.TCPSession.read(TCPSession.java:140)
	at com.huya.taf.net.core.nio.TCPAcceptor.handleReadEvent(TCPAcceptor.java:111)
	at com.huya.taf.net.core.nio.Reactor.dispatchEvent(Reactor.java:197)
	at com.huya.taf.net.core.nio.Reactor.run(Reactor.java:114)

class org.apache.logging.slf4j.Log4jLogger cannot be cast to class ch.qos.logback.classic.Logger

This bug(?) appears in later versions of ch.qos.logback: classic > 1.2.12

I am using the below code in a unit test class with the following imports and declarations

`
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import org.slf4j.LoggerFactory;

private final Logger logger = (Logger) LoggerFactory.getLogger(MyClass.class);
private final ListAppender listAppender = new ListAppender<>();

@BeforeEach
public void setUp() {
    listAppender.start();
    logger.addAppender(listAppender);

}
`

I am using org.slf4j:api version 2.0.9 and logback-classic version 1.2.12 as that's the last version that doesn't break the casting.

Hoping I can get an answer or a guide to this issue.

Necessary GraalVM reflect-config.json in the logback 4.1.1

To upgrade logback to 1.4.11 in the Micronaut Framework, we had to add the following GraalVM Configuration Metadata via reflect-config.json file:

[
  {
    "name": "ch.qos.logback.classic.joran.SerializedModelConfigurator",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": [

        ]
      }
    ]
  },
  {
    "name": "ch.qos.logback.classic.util.DefaultJoranConfigurator",
    "methods": [
      {
        "name": "<init>",
        "parameterTypes": [

        ]
      }
    ]
  }
]

It would be best if Logback could include this reflect-config.json directly so that everyone using logback could have a smooth GraalVM experience. Would you be interested in such a contribution?

[Question] Upgrade Logback 1.2.x - The method findURLOfDefaultConfigurationFile(boolean) is undefined for the type ContextInitializer

I'm using slf4j with logback 1.2.x and have the following code to reset logback to default configuration:

                ch.qos.logback.classic.LoggerContext loggerContext = (ch.qos.logback.classic.LoggerContext) org.slf4j.LoggerFactory.getILoggerFactory();
                ch.qos.logback.classic.util.ContextInitializer ci = new ch.qos.logback.classic.util.ContextInitializer(loggerContext);
                java.net.URL confUrl = ci.findURLOfDefaultConfigurationFile(true);
                loggerContext.reset();
                ch.qos.logback.classic.joran.JoranConfigurator joranConfigurator = new ch.qos.logback.classic.joran.JoranConfigurator();
                joranConfigurator.setContext(loggerContext);
                joranConfigurator.doConfigure(confUrl);

Upgrading logback to 1.3.x or 1.4.x I get compilation error:

The method findURLOfDefaultConfigurationFile(boolean) is undefined for the type ContextInitializer

How to implement this in the newer versions?

Add support for Virtual Threads

Investigate and implement support for virtual threads introduced in JDK 21.

Java documentation states:

Virtual threads are lightweight threads that reduce the effort of writing, maintaining, and debugging high-throughput concurrent applications.

Two difficulties were encountered while adding virtual threads in logback.

First, while Multi-Release Jar files make it easy to support JDK version dependent code in projects, support for support for Multi-Release jar files in IDEs when combined with build tools is lacking (as of 2023-11-25). When the Multi-Release path seemed blocked, the project reverted to the old practice of adding support via reflection.

Second, virtual threads are meant to be used for tasks which spend most of their time waiting for blocking I/O operations. Thus virtual threads are meant to reduce resource consumption which is not easy to measure and requires good judgement.

[Question] LOGBACK-1673 and conditional appender configuration

In LOGBACK-1673 it was mentioned that

One notable change is that, <if>/<then> elements cannot be embedded within "second phase" elements such as <appender>/<root>/<logger>. The<if>/<then> elements must be located under <configuration> or other "first phase elements", i.e. all elements other than <appender>/<root>/<logger>.

In my case, I have a conditional configuration for an appender. There's a chunk of attributes that I don't include when some property is not set. For example,

<appender name="..." class="...">
    <log>...</log>
    <flushLevel>...</flushLevel>
    <if condition='...'>
        <then>
            <partialSuccess>true</partialSuccess>
            <logbackBatchingSettings>
                <elementCountThreshold>...</elementCountThreshold>
                ...
            </logbackBatchingSettings>
        </then>
    </if>
</appender>

With the sanity check in place, I don't see any way to configure this properly without duplicating appenders: one with these settings and the same one but without, then introducing a logic to include only one of them later. That looks like a lot of duplication and exposing properties/logic that I'd rather have in the <include>d xml.

What's the best way to express a conditional configuration for an appender in 1.3/1.4?

Logback stop working

Hi , someone know why my logback settings stopped working , I didn't even change them

            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.14</version>
            <scope>compile</scope>

src\main\resources\logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %blue(LogBack) %magenta(Logger) [%thread] %highlight(%-5level){TRACE=blue, DEBUG=green, INFO=white, WARN=yellow, ERROR=red} %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>


    <!--    Intergacja z discord za pomocą JDA-->

    <!--    <logger name="net.dv8tion.jda" level="OFF"/>-->
    <logger name="net.dv8tion.jda" level="ERROR,WARN"/>


    <!--    Strona -->
    <logger name="org.eclipse.jetty" level="ERROR,WARN"/>
    <logger name="io.javalin" level="ERROR,WARN"/>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.