Spring Logback multitenancy implementation with custom config per tenant

时间:2016-09-01 06:20:35

标签: spring maven logback multi-tenant

I'm trying to implement a multitenency compatible logging which logs each tenants log in a different file AND can be configured for each tenant individually.

I'm using Spring Boot in a Maven build with SLF4j and Logback.

To achieve a different file for each tenant i'm using MCP to set a tenant identifier for each request.

 MDC.put("tenant", "tenant-" + tenant_id);

It's now easily possible to logout the tenant like this

<encoder>
    <pattern>%X{tenant} %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n</pattern>
</encoder>

However, I'm not able to put them in different files. Moreover I do not have any concept on how to define the logback xml per tenant.

I cannot find any good examples to go beyond the basics - do you have any suggestions?

1 个答案:

答案 0 :(得分:1)

你运气不好,你将不得不实施自己的appender。不过应该不会太难。界面非常简单:

    public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachable<E> {

    /**
     * Get the name of this appender. The name uniquely identifies the appender.
     */
    String getName();

    /**
     * This is where an appender accomplishes its work. Note that the argument 
     * is of type Object.
     * @param event
     */
    void doAppend(E event) throws LogbackException;

    /**
     * Set the name of this appender. The name is used by other components to
     * identify this appender.
     * 
     */
    void setName(String name);
}

您将在LoggingEvent中获得具有此方法的doAppendgetMDCPropertyMap,您可以从中区分要附加的文件。 如果我是你,我可能不会理解处理文件的细节,并且实际上会有一个常规RollingFileAppender的地图。所以你的doAppend方法看起来像这样:

private Map<String, Appender> appenders = new ConcurrentHashMap<>();

void doAppend(LoggingEvent event) {
    String tenant = event.getMDCPropertyMap().get("tenant");
    Appender appender = appenders.get(tenant);
    if(appender == null) { //may need to synchronize, careful
        appender = initTenantAppender(tenant);
        appenders.put(tenant, appender);
    }
    appender.doAppend(event);
}