2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.logging.logback;
23 import ch.qos.logback.classic.Logger;
24 import ch.qos.logback.classic.LoggerContext;
25 import ch.qos.logback.classic.sift.MDCBasedDiscriminator;
26 import ch.qos.logback.classic.spi.ILoggingEvent;
27 import ch.qos.logback.core.Appender;
28 import ch.qos.logback.core.AppenderBase;
29 import ch.qos.logback.core.joran.spi.DefaultClass;
30 import ch.qos.logback.core.sift.Discriminator;
31 import org.slf4j.LoggerFactory;
33 import java.util.Iterator;
35 import java.util.concurrent.ConcurrentHashMap;
38 * <p>Allows to use EELF logging configuration almost as is, by using a custom routing function, but pre-configured
39 * appenders attached to the standard EELF loggers.</p>
41 * <p>Changes that must be made in <i>logback.xml</i> supplied with EELF:</p>
44 * <appender name="DISPATCHER" class="org.openecomp.sdc.logging.logback.DispatchingAppender">
45 * <discriminator class="org.openecomp.sdc.logging.logback.EventTypeDiscriminator"/>
46 * <appenderNamePattern>asyncEELF%s</appenderNamePattern>
49 * <root level="INFO" additivity="false">
50 * <appender-ref ref="DISPATCHER" />
57 public class DispatchingAppender extends AppenderBase<ILoggingEvent> {
59 // "magic" appender to indicate a missing appender
60 private static final Appender<ILoggingEvent> NO_APPENDER = new DispatchingAppender();
62 private Map<String, Appender<ILoggingEvent>> appenders = new ConcurrentHashMap<>();
64 private Discriminator<ILoggingEvent> discriminator;
65 private String appenderNamePattern;
67 @DefaultClass(MDCBasedDiscriminator.class)
68 public void setDiscriminator(Discriminator<ILoggingEvent> discriminator) {
69 this.discriminator = discriminator;
72 public Discriminator<ILoggingEvent> getDiscriminator() {
73 return this.discriminator;
76 public void setAppenderNamePattern(String pattern) {
77 this.appenderNamePattern = pattern;
80 public String getAppenderNamePattern() {
81 return this.appenderNamePattern;
85 protected void append(ILoggingEvent event) {
87 if (this.isStarted()) {
89 String discriminatingValue = this.discriminator.getDiscriminatingValue(event);
90 String appenderName = String.format(this.appenderNamePattern, discriminatingValue);
91 Appender<ILoggingEvent> appender = this.lookupAppender(appenderName);
92 if (appender == NO_APPENDER) {
93 this.addError(String.format("Appender %s does not exist", appenderName));
95 appender.doAppend(event);
100 private Appender<ILoggingEvent> lookupAppender(String key) {
102 Appender<ILoggingEvent> appender = appenders.get(key);
103 if (appender != null) {
107 LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
108 for (Logger log : context.getLoggerList()) {
110 Iterator<Appender<ILoggingEvent>> iterator = log.iteratorForAppenders();
111 while (iterator.hasNext()) {
113 Appender<ILoggingEvent> element = iterator.next();
114 if (key.equals(element.getName())) {
115 this.appenders.putIfAbsent(key, element);
121 // to avoid consecutive lookups if the required appender does not exist
122 this.appenders.putIfAbsent(key, NO_APPENDER);
127 public void start() {
130 if (this.discriminator == null) {
131 this.addError("Missing discriminator. Aborting");
134 if (!this.discriminator.isStarted()) {
135 this.addError("Discriminator has not started successfully. Aborting");
139 if (this.appenderNamePattern == null) {
140 this.addError("Missing name pattern. Aborting");