日志路径配的是/usr/local/log目录,发现mac对应的目录下没有生成日志文件,原因是因为磁盘目录禁止写数据,导致appender没有启动,所以就没有写日志文件。

做一些初始化工作,比如是否启动xxxAppender。

启动的标志字段是started

1.如果启动了,started就是true
只有启动了,才会调用启动方法,更新started为true。
2.如果没启动,started就是默认值false
如果日志的磁盘目录没有写权限,就不会调用启动方法,也就不会更新started为true。

方法调用栈

start:105, UnsynchronizedAppenderBase (ch.qos.logback.core)
start:82, OutputStreamAppender (ch.qos.logback.core)
start:138, FileAppender (ch.qos.logback.core)
start:100, RollingFileAppender (ch.qos.logback.core.rolling)
end:90, AppenderAction (ch.qos.logback.core.joran.action)
callEndAction:309, Interpreter (ch.qos.logback.core.joran.spi)
endElement:193, Interpreter (ch.qos.logback.core.joran.spi)
endElement:179, Interpreter (ch.qos.logback.core.joran.spi)
play:62, EventPlayer (ch.qos.logback.core.joran.spi)
doConfigure:165, GenericConfigurator (ch.qos.logback.core.joran)
doConfigure:152, GenericConfigurator (ch.qos.logback.core.joran)
doConfigure:110, GenericConfigurator (ch.qos.logback.core.joran)
doConfigure:53, GenericConfigurator (ch.qos.logback.core.joran)
configureByResource:75, ContextInitializer (ch.qos.logback.classic.util)
contextInitialized:147, LogbackConfigListener (xxx.log.logback.web)
listenerStart:5197, StandardContext (org.apache.catalina.core)
startInternal:5720, StandardContext (org.apache.catalina.core)
start:145, LifecycleBase (org.apache.catalina.util)
addChildInternal:1018, ContainerBase (org.apache.catalina.core)
addChild:994, ContainerBase (org.apache.catalina.core)
addChild:662, StandardHost (org.apache.catalina.core)
manageApp:1899, HostConfig (org.apache.catalina.startup)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:301, BaseModelMBean (org.apache.tomcat.util.modeler)
invoke:819, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)
invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)
createStandardContext:619, MBeanFactory (org.apache.catalina.mbeans)
createStandardContext:566, MBeanFactory (org.apache.catalina.mbeans)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:301, BaseModelMBean (org.apache.tomcat.util.modeler)
invoke:819, DefaultMBeanServerInterceptor (com.sun.jmx.interceptor)
invoke:801, JmxMBeanServer (com.sun.jmx.mbeanserver)
invoke:468, MBeanServerAccessController (com.sun.jmx.remote.security)
doOperation:1468, RMIConnectionImpl (javax.management.remote.rmi)
access$300:76, RMIConnectionImpl (javax.management.remote.rmi)
run:1309, RMIConnectionImpl$PrivilegedOperation (javax.management.remote.rmi)
doPrivileged:-1, AccessController (java.security)
doPrivilegedOperation:1408, RMIConnectionImpl (javax.management.remote.rmi)
invoke:829, RMIConnectionImpl (javax.management.remote.rmi)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
dispatch:357, UnicastServerRef (sun.rmi.server)
run:200, Transport$1 (sun.rmi.transport)
run:197, Transport$1 (sun.rmi.transport)
doPrivileged:-1, AccessController (java.security)
serviceCall:196, Transport (sun.rmi.transport)
handleMessages:573, TCPTransport (sun.rmi.transport.tcp)
run0:834, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
lambda$run$0:688, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
run:-1, 1189693891 (sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$5)
doPrivileged:-1, AccessController (java.security)
run:687, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:748, Thread (java.lang)

写日志流程

核心方法的源码

* Similar to AppenderBase except that derived appenders need to handle * thread synchronization on their own. * @author Ceki G&uuml;lc&uuml; * @author Ralph Goers abstract public class UnsynchronizedAppenderBase<E> extends ContextAwareBase implements Appender<E> { public void doAppend(E eventObject) { // WARNING: The guard check MUST be the first statement in the // doAppend() method. // prevent re-entry. if (Boolean.TRUE.equals(guard.get())) { return; try { guard.set(Boolean.TRUE); if (!this.started) { //如果某个xxxAppender没有启动,就不会写日志 if (statusRepeatCount++ < ALLOWED_REPEATS) { addStatus(new WarnStatus("Attempted to append to non started appender [" + name + "].", this)); return; if (getFilterChainDecision(eventObject) == FilterReply.DENY) { return; // ok, we now invoke derived class' implementation of append this.append(eventObject); //只有xxxAppender启动了,才会写日志 } catch (Exception e) { if (exceptionCount++ < ALLOWED_REPEATS) { addError("Appender [" + name + "] failed to append.", e); } finally { guard.set(Boolean.FALSE);
public class OutputStreamAppender<E> extends UnsynchronizedAppenderBase<E> {
protected void append(E eventObject) {
    if (!isStarted()) { //xxxAppender必须要启动,才会写日志
        return;
    subAppend(eventObject); //写日志
 * Actual writing occurs here.
 * Most subclasses of <code>WriterAppender</code> will need to override this
 * method.
 * @since 0.9.0
protected void subAppend(E event) {
    if (!isStarted()) {
        return;
    try {
        // this step avoids LBCLASSIC-139
        if (event instanceof DeferredProcessingAware) {
            ((DeferredProcessingAware) event).prepareForDeferredProcessing();
        // the synchronization prevents the OutputStream from being closed while we
        // are writing. It also prevents multiple threads from entering the same
        // converter. Converters assume that they are in a synchronized block.
        // lock.lock();
        byte[] byteArray = this.encoder.encode(event); //编码的作用?如果有自定义日志格式,这里会调用自定义日志格式类
        writeBytes(byteArray); //写日志
    } catch (IOException ioe) {
        // as soon as an exception occurs, move to non-started state
        // and add a single ErrorStatus to the SM.
        this.started = false;
        addStatus(new ErrorStatus("IO failure in appender", this, ioe));
private void writeBytes(byte[] byteArray) throws IOException {
    if(byteArray == null || byteArray.length == 0)
        return;
    lock.lock();
    try {
        this.outputStream.write(byteArray); //写数据到磁盘日志文件
        if (immediateFlush) {
            this.outputStream.flush();
    } finally {
        lock.unlock();

方法调用栈

writeBytes:194, OutputStreamAppender (ch.qos.logback.core) //写数据到磁盘日志文件
subAppend:231, OutputStreamAppender (ch.qos.logback.core)
subAppend:235, RollingFileAppender (ch.qos.logback.core.rolling)
append:102, OutputStreamAppender (ch.qos.logback.core)
doAppend:84, UnsynchronizedAppenderBase (ch.qos.logback.core)
appendLoopOnAppenders:51, AppenderAttachableImpl (ch.qos.logback.core.spi)
appendLoopOnAppenders:270, Logger (ch.qos.logback.classic)
callAppenders:257, Logger (ch.qos.logback.classic)
buildLoggingEventAndAppend:421, Logger (ch.qos.logback.classic)
filterAndLog_0_Or3Plus:383, Logger (ch.qos.logback.classic)
info:579, Logger (ch.qos.logback.classic)
xxx:33, xxxController (com.xxx.payment.controller)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:205, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:133, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:97, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:827, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:738, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:85, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:967, DispatcherServlet (org.springframework.web.servlet)
doService:901, DispatcherServlet (org.springframework.web.servlet)
processRequest:970, FrameworkServlet (org.springframework.web.servlet)
doGet:861, FrameworkServlet (org.springframework.web.servlet)
service:621, HttpServlet (javax.servlet.http)
service:846, FrameworkServlet (org.springframework.web.servlet)
service:728, HttpServlet (javax.servlet.http)
internalDoFilter:303, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
doFilter:52, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:241, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
handle:438, CatFilter$Context (com.dianping.cat.servlet)
handle:235, CatFilter$CatHandler$3 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
handle:328, CatFilter$CatHandler$4 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
handle:218, CatFilter$CatHandler$2 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
handle:127, CatFilter$CatHandler$1 (com.dianping.cat.servlet)
handle:436, CatFilter$Context (com.dianping.cat.servlet)
doFilter:65, CatFilter (com.dianping.cat.servlet)
internalDoFilter:241, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
doFilter:31, EncodingFilter (hikefa.core.web.filter)
internalDoFilter:241, ApplicationFilterChain (org.apache.catalina.core)
doFilter:208, ApplicationFilterChain (org.apache.catalina.core)
invoke:219, StandardWrapperValve (org.apache.catalina.core)
invoke:110, StandardContextValve (org.apache.catalina.core)
invoke:444, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:169, StandardHostValve (org.apache.catalina.core)
invoke:104, ErrorReportValve (org.apache.catalina.valves)
invoke:1025, AccessLogValve (org.apache.catalina.valves)
invoke:116, StandardEngineValve (org.apache.catalina.core)
service:445, CoyoteAdapter (org.apache.catalina.connector)
process:1137, AbstractHttp11Processor (org.apache.coyote.http11)
process:637, AbstractProtocol$AbstractConnectionHandler (org.apache.coyote)
run:319, JIoEndpoint$SocketProcessor (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)
最终写数据到磁盘日志文件的类是OutputStreamAppender

自定义日志格式

如果有自定义日志格式类,那么就会调用自定义日志格式类。

1.写日志
自定义日志格式类
3.回到写日志流程

方法调用栈

getCurrentThreadLogPreFix:94, LogPreFixConverter (xxx.log.logback.layout.converter)
convert:79, LogPreFixConverter (xxx.log.logback.layout.converter)
convert:19, LogPreFixConverter (xxx.log.logback.layout.converter) //自定义格式类
write:36, FormattingConverter (ch.qos.logback.core.pattern)
writeLoopOnConverters:115, PatternLayoutBase (ch.qos.logback.core.pattern)
doLayout:141, PatternLayout (ch.qos.logback.classic)
doLayout:39, PatternLayout (ch.qos.logback.classic)
encode:115, LayoutWrappingEncoder (ch.qos.logback.core.encoder) //编码:调用自定义格式类
subAppend:230, OutputStreamAppender (ch.qos.logback.core)
subAppend:235, RollingFileAppender (ch.qos.logback.core.rolling)
append:102, OutputStreamAppender (ch.qos.logback.core)
doAppend:84, UnsynchronizedAppenderBase (ch.qos.logback.core)
appendLoopOnAppenders:51, AppenderAttachableImpl (ch.qos.logback.core.spi)
appendLoopOnAppenders:270, Logger (ch.qos.logback.classic)
callAppenders:257, Logger (ch.qos.logback.classic)
buildLoggingEventAndAppend:421, Logger (ch.qos.logback.classic)
filterAndLog_0_Or3Plus:383, Logger (ch.qos.logback.classic)
info:579, Logger (ch.qos.logback.classic)
run:1156, ClientCnxn$SendThread (org.apache.zookeeper)
复制代码
分类:
后端
标签: