[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / common / openecomp-logging-lib / openecomp-logging-core / src / main / java / org / openecomp / core / logging / logback / DispatchingAppender.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.core.logging.logback;
22
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;
32
33 import java.util.Iterator;
34 import java.util.Map;
35 import java.util.concurrent.ConcurrentHashMap;
36
37 /**
38  * <p>Allows to use EELF logging configuration almost as is, by using a custom routing function, but
39  * pre-configured appenders attached to the standard EELF loggers.</p> <p>Changes that must be made
40  * in <i>logback.xml</i> supplied with EELF:</p>
41  * <pre>
42  *     &lt;appender name="DISPATCHER" class="DispatchingAppender"&gt;
43  *          &lt;discriminator class="EventTypeDiscriminator"/&gt;
44  *          &lt;appenderNamePattern&gt;asyncEELF%s&lt;/appenderNamePattern&gt;
45  *     &lt;/appender&gt;
46  *     &lt;root level="INFO" additivity="false"&gt;
47  *          &lt;appender-ref ref="DISPATCHER" /&gt;
48  *      &lt;/root&gt;
49  * </pre>
50  */
51 public class DispatchingAppender extends AppenderBase<ILoggingEvent> {
52
53   // "magic" appender to indicate a missing appender
54   private static final Appender<ILoggingEvent> NO_APPENDER = new DispatchingAppender();
55
56   private Map<String, Appender<ILoggingEvent>> appenders = new ConcurrentHashMap<>();
57
58   private Discriminator<ILoggingEvent> discriminator;
59   private String appenderNamePattern;
60
61   public Discriminator<ILoggingEvent> getDiscriminator() {
62     return this.discriminator;
63   }
64
65   @DefaultClass(MDCBasedDiscriminator.class)
66   public void setDiscriminator(Discriminator<ILoggingEvent> discriminator) {
67     this.discriminator = discriminator;
68   }
69
70   public String getAppenderNamePattern() {
71     return this.appenderNamePattern;
72   }
73
74   public void setAppenderNamePattern(String pattern) {
75     this.appenderNamePattern = pattern;
76   }
77
78   @Override
79   protected void append(ILoggingEvent event) {
80
81     if (this.isStarted()) {
82
83       String discriminatingValue = this.discriminator.getDiscriminatingValue(event);
84       String appenderName = String.format(this.appenderNamePattern, discriminatingValue);
85       Appender<ILoggingEvent> appender = this.lookupAppender(appenderName);
86       if (appender == NO_APPENDER) {
87         this.addError(String.format("Appender %s does not exist", appenderName));
88       } else {
89         appender.doAppend(event);
90       }
91     }
92   }
93
94   private Appender<ILoggingEvent> lookupAppender(String key) {
95
96     Appender<ILoggingEvent> appender = appenders.get(key);
97     if (appender != null) {
98       return appender;
99     }
100
101     LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
102     for (Logger log : context.getLoggerList()) {
103
104       Iterator<Appender<ILoggingEvent>> iterator = log.iteratorForAppenders();
105       while (iterator.hasNext()) {
106
107         Appender<ILoggingEvent> element = iterator.next();
108         if (key.equals(element.getName())) {
109           this.appenders.putIfAbsent(key, element);
110           return element;
111         }
112       }
113     }
114
115     // to avoid consecutive lookups if the required appender does not exist
116     this.appenders.putIfAbsent(key, NO_APPENDER);
117     return NO_APPENDER;
118   }
119
120   @Override
121   public void start() {
122
123     int errors = 0;
124     if (this.discriminator == null) {
125       this.addError("Missing discriminator. Aborting");
126     }
127
128     if (!this.discriminator.isStarted()) {
129       this.addError("Discriminator has not started successfully. Aborting");
130       ++errors;
131     }
132
133     if (this.appenderNamePattern == null) {
134       this.addError("Missing name pattern. Aborting");
135       ++errors;
136     }
137
138     if (errors == 0) {
139       super.start();
140     }
141   }
142 }