1

我使用 logback 并将 pettern 放入 dbappender,但它不起作用。

    <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource
        class="ch.qos.logback.core.db.DriverManagerConnectionSource">
        <driverClass>net.sourceforge.jtds.jdbc.Driver</driverClass>
        <url>jdbc:jtds:sqlserver://xxx.xxx.xxx.xx:1433/granica</url>
        <user>java</user>
        <password>java</password>
    </connectionSource>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} - %msg%n</pattern>
    </encoder>
</appender> 

有人知道如何解决吗?提前致谢!

4

2 回答 2

2

您不能在 DBAppender 中放置模式:

“DBAppender 以独立于 Java 编程语言的格式将日志事件插入到三个数据库表中。

*这三个表是 logging_event、logging_event_property 和 logging_event_exception。在使用 DBAppender 之前,它们必须存在。Logback 附带将创建表的 SQL 脚本。"*

替代解决方案:如果您真的需要这种模式,那么您应该,根据现有表为您生成输出。这可以通过简单的 SQL、视图或触发器来完成。使用标准 SQL 创建您需要的输出。

祝你好运!

于 2014-02-06T07:54:05.723 回答
0

通过定义几个自定义类,我设法很容易地自定义格式化消息,一个扩展DBAppender和另一个实现ILoggingEvent接口:

package com.mypackage;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Map;

import org.slf4j.Marker;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.db.DBAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.LoggerContextVO;

/**
 * 
 * @author PJ_Finnegan
 * 
 *         To override the default DBAppender with a custom FORMATTED_MESSAGE
 *
 */
public class MdcDbAppender extends DBAppender {

    @Override
    protected void subAppend(ILoggingEvent event, Connection connection, PreparedStatement insertStatement)
            throws Throwable {
        // use a special event with custom formatted message
        MdcLoggingEvent customEvent = new MdcLoggingEvent(event);
        super.subAppend(customEvent, connection, insertStatement);
    }

}

/**
 * 
 * @author PJ_Finnegan
 * 
 *         To override the getFormattedMessage() method prepending MDC info
 *
 */
class MdcLoggingEvent implements ILoggingEvent {

    private ILoggingEvent mOrigEvent;

    public MdcLoggingEvent(ILoggingEvent origEvent) {
        mOrigEvent = origEvent;
    }

    @Override
    public String getThreadName() {
        return mOrigEvent.getThreadName();
    }

    @Override
    public Level getLevel() {
        return mOrigEvent.getLevel();
    }

    @Override
    public String getMessage() {
        return mOrigEvent.getMessage();
    }

    @Override
    public Object[] getArgumentArray() {
        return mOrigEvent.getArgumentArray();
    }

    @Override
    public String getFormattedMessage() {
        // add my MDC info as a prefix
        String mdcVals[] = new String[] { "NA", "NA", "NA" };
        Map<String, String> mpm = mOrigEvent.getMDCPropertyMap();
        if (mpm != null) {
            int i = 0;
            for (String key : new String[] { "jobName", "jobInstanceId", "jobExecutionId" }) {
                if (mpm.containsKey(key)) {
                    mdcVals[i] = mpm.get(key);
                }
                i++;
            }
        }
        return String.format("[%s-%s-%s] ", mdcVals[0], mdcVals[1], mdcVals[2]) + mOrigEvent.getFormattedMessage();
    }

    @Override
    public String getLoggerName() {
        return mOrigEvent.getLoggerName();
    }

    @Override
    public LoggerContextVO getLoggerContextVO() {
        return mOrigEvent.getLoggerContextVO();
    }

    @Override
    public IThrowableProxy getThrowableProxy() {
        return mOrigEvent.getThrowableProxy();
    }

    @Override
    public StackTraceElement[] getCallerData() {
        return mOrigEvent.getCallerData();
    }

    @Override
    public boolean hasCallerData() {
        return mOrigEvent.hasCallerData();
    }

    @Override
    public Marker getMarker() {
        return mOrigEvent.getMarker();
    }

    @Override
    public Map<String, String> getMDCPropertyMap() {
        return mOrigEvent.getMDCPropertyMap();
    }

    @Override
    public Map<String, String> getMdc() {
        return mOrigEvent.getMdc();
    }

    @Override
    public long getTimeStamp() {
        return mOrigEvent.getTimeStamp();
    }

    @Override
    public void prepareForDeferredProcessing() {
        mOrigEvent.prepareForDeferredProcessing();
    }

}

这样LOGGING_EVENT.FORMATTED_MESSAGE,数据库上的列值将在前面加上字符串[jobName-jobInstanceId-jobExecutionId](我之前将其值放入 M​​DC):

TIMESTMP FORMATTED_MESSAGE
1635255763784 [test-2760-3980] HikariPool-1 - 关机完成。

当然你想在你的logback.xml文件中使用你的自定义类而不是股票 DBAppender:

    <!-- DB appender -->
    <!-- use our custom class to override the FORMATTED_MESSAGE default pattern -->
    <!-- <appender name="ORADB" class="ch.qos.logback.classic.db.DBAppender"> -->
    <appender name="ORADB" class="com.mypackage.MdcDbAppender">
        <connectionSource
...

没有什么能阻止ILoggingEvent.getFormattedMessage()用更复杂的操作来覆盖该方法。

于 2021-10-26T14:42:30.040 回答