Merge "Add MD-SAL artifacts"
[controller.git] / opendaylight / config / logback-config / src / main / java / org / opendaylight / controller / config / yang / logback / config / ContextSetterImpl.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.config.yang.logback.config;
9
10 import ch.qos.logback.classic.Level;
11 import ch.qos.logback.classic.LoggerContext;
12 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
13 import ch.qos.logback.classic.filter.ThresholdFilter;
14 import ch.qos.logback.classic.spi.ILoggingEvent;
15 import ch.qos.logback.core.Appender;
16 import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
17 import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
18 import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
19 import com.google.common.base.Optional;
20 import com.google.common.base.Preconditions;
21 import com.google.common.collect.Sets;
22 import java.io.Closeable;
23 import java.io.IOException;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Implementation of {@link ContextSetter}. Resets running logback
33  * configuration.
34  */
35 public class ContextSetterImpl implements ContextSetter, Closeable {
36
37     private final LogbackStatusListener statusListener;
38     private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ContextSetterImpl.class);
39
40     public ContextSetterImpl(final LogbackRuntimeRegistrator rootRuntimeBeanRegistratorWrapper) {
41         statusListener = new LogbackStatusListener(rootRuntimeBeanRegistratorWrapper);
42         statusListener.register();
43     }
44
45     @Override
46     public void updateContext(final LogbackModule module) {
47         LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
48
49         List<ch.qos.logback.classic.Logger> loggersBefore = context.getLoggerList();
50
51         createLoggers(context, module, Sets.newHashSet(loggersBefore));
52     }
53
54     private Map<String, Appender<ILoggingEvent>> createConsoleAppenders(final LoggerContext context, final LogbackModule module) {
55         Map<String, Appender<ILoggingEvent>> appendersMap = new HashMap<>();
56         for (ConsoleAppenderTO appender : module.getConsoleAppenderTO()) {
57             Preconditions.checkState(appendersMap.containsKey(appender.getName()) == false,
58                     "Duplicate appender name %s", appender.getName());
59             ch.qos.logback.core.ConsoleAppender<ILoggingEvent> app = new ch.qos.logback.core.ConsoleAppender<>();
60             app.setContext(context);
61             PatternLayoutEncoder encoder = new PatternLayoutEncoder();
62             encoder.setContext(context);
63             encoder.setPattern(appender.getEncoderPattern());
64             encoder.start();
65             app.setEncoder(encoder);
66             ThresholdFilter filter = new ThresholdFilter();
67             filter.setContext(context);
68             filter.setLevel(appender.getThresholdFilter());
69             filter.start();
70             app.getCopyOfAttachedFiltersList().add(filter);
71             app.setName(appender.getName());
72             app.start();
73             appendersMap.put(app.getName(), app);
74         }
75         return appendersMap;
76     }
77
78     private void createLoggers(final LoggerContext context, final LogbackModule module,
79             final Set<ch.qos.logback.classic.Logger> loggersBefore) {
80
81         Map<String, Appender<ILoggingEvent>> appendersMap = getAppenders(module, context);
82
83         for (LoggerTO logger : module.getLoggerTO()) {
84             LOG.trace("Setting configuration for logger {}", logger.getLoggerName());
85             final ch.qos.logback.classic.Logger logbackLogger = context.getLogger(logger.getLoggerName());
86
87             Optional<Set<Appender<ILoggingEvent>>> appendersBefore = getAppendersBefore(loggersBefore, logbackLogger);
88             LOG.trace("Logger {}: Appenders registered before: {}", logger.getLoggerName(),
89                     appendersBefore.isPresent() ? appendersBefore.get() : "NO APPENDERS BEFORE");
90
91             logbackLogger.setLevel(Level.toLevel(logger.getLevel()));
92
93             addNewAppenders(appendersMap, logger, logbackLogger, appendersBefore);
94             removeBeforeAppenders(loggersBefore, logger, logbackLogger, appendersBefore);
95         }
96     }
97
98     private void addNewAppenders(final Map<String, Appender<ILoggingEvent>> appendersMap, final LoggerTO logger,
99             final ch.qos.logback.classic.Logger logbackLogger, final Optional<Set<Appender<ILoggingEvent>>> appendersBefore) {
100         if (logger.getAppenders() != null) {
101             for (String appenderName : logger.getAppenders()) {
102                 if (appendersMap.containsKey(appenderName)) {
103                     logbackLogger.addAppender(appendersMap.get(appenderName));
104                     LOG.trace("Logger {}: Adding new appender: {}", logger.getLoggerName(), appenderName);
105                 } else {
106                     throw new IllegalStateException("No appender " + appenderName
107                             + " found. This error should have been discovered by validation");
108                 }
109             }
110         }
111     }
112
113     private void removeBeforeAppenders(final Set<ch.qos.logback.classic.Logger> loggersBefore, final LoggerTO logger,
114             final ch.qos.logback.classic.Logger logbackLogger, final Optional<Set<Appender<ILoggingEvent>>> appendersBefore) {
115         if (appendersBefore.isPresent()) {
116             for (Appender<ILoggingEvent> appenderBefore : appendersBefore.get()) {
117                 logbackLogger.detachAppender(appenderBefore);
118                 appenderBefore.stop();
119                 LOG.trace("Logger {}: Removing old appender: {}", logger.getLoggerName(),
120                         appenderBefore.getName());
121             }
122             loggersBefore.remove(logbackLogger);
123         }
124     }
125
126     private Optional<Set<Appender<ILoggingEvent>>> getAppendersBefore(final Set<ch.qos.logback.classic.Logger> loggersBefore,
127             final ch.qos.logback.classic.Logger logbackLogger) {
128         if (loggersBefore.contains(logbackLogger)) {
129             Iterator<Appender<ILoggingEvent>> appenderIt = logbackLogger.iteratorForAppenders();
130             Set<Appender<ILoggingEvent>> appendersBefore = Sets.newHashSet();
131             while (appenderIt.hasNext()) {
132                 appendersBefore.add(appenderIt.next());
133             }
134             return Optional.of(appendersBefore);
135         } else {
136             return Optional.absent();
137         }
138
139     }
140
141     private Map<String, Appender<ILoggingEvent>> getAppenders(final LogbackModule module, final LoggerContext context) {
142         Map<String, Appender<ILoggingEvent>> appendersMap = new HashMap<>();
143         addAllAppenders(appendersMap, createRollingAppenders(context, module));
144         addAllAppenders(appendersMap, createFileAppenders(context, module));
145         addAllAppenders(appendersMap, createConsoleAppenders(context, module));
146
147         return appendersMap;
148     }
149
150     private void addAllAppenders(final Map<String, Appender<ILoggingEvent>> allAppenders,
151             final Map<String, Appender<ILoggingEvent>> appendersToAdd) {
152         for (String appenderName : appendersToAdd.keySet()) {
153             Preconditions.checkState(allAppenders.containsKey(appenderName) == false, "Duplicate appender name %s",
154                     appenderName);
155             allAppenders.put(appenderName, appendersToAdd.get(appenderName));
156         }
157     }
158
159     private Map<String, Appender<ILoggingEvent>> createFileAppenders(final LoggerContext context, final LogbackModule module) {
160         Map<String, Appender<ILoggingEvent>> appendersMap = new HashMap<>();
161         for (FileAppenderTO appender : module.getFileAppenderTO()) {
162             Preconditions.checkState(appendersMap.containsKey(appender.getName()) == false,
163                     "Duplicate appender name %s", appender.getName());
164             ch.qos.logback.core.FileAppender<ILoggingEvent> app = new ch.qos.logback.core.FileAppender<>();
165             app.setAppend(appender.getAppend());
166             app.setContext(context);
167             PatternLayoutEncoder encoder = new PatternLayoutEncoder();
168             encoder.setContext(context);
169             encoder.setPattern(appender.getEncoderPattern());
170             encoder.start();
171             app.setEncoder(encoder);
172             app.setFile(appender.getFileName());
173             app.setName(appender.getName());
174             app.start();
175             appendersMap.put(app.getName(), app);
176         }
177
178         return appendersMap;
179     }
180
181     private Map<String, Appender<ILoggingEvent>> createRollingAppenders(final LoggerContext context, final LogbackModule module) {
182         Map<String, Appender<ILoggingEvent>> appendersMap = new HashMap<>();
183         for (RollingFileAppenderTO appender : module.getRollingFileAppenderTO()) {
184             Preconditions.checkState(appendersMap.containsKey(appender.getName()) == false,
185                     "Duplicate appender name %s", appender.getName());
186             ch.qos.logback.core.rolling.RollingFileAppender<ILoggingEvent> app = new ch.qos.logback.core.rolling.RollingFileAppender<>();
187             app.setAppend(appender.getAppend());
188             app.setContext(context);
189             PatternLayoutEncoder encoder = new PatternLayoutEncoder();
190             encoder.setContext(context);
191             encoder.setPattern(appender.getEncoderPattern());
192             encoder.start();
193             app.setEncoder(encoder);
194             app.setFile(appender.getFileName());
195             if (appender.getRollingPolicyType().equals("FixedWindowRollingPolicy")) {
196                 FixedWindowRollingPolicy policy = new FixedWindowRollingPolicy();
197                 policy.setContext(context);
198                 policy.setMaxIndex(appender.getMaxIndex());
199                 policy.setMinIndex(appender.getMinIndex());
200                 policy.setFileNamePattern(appender.getFileNamePattern());
201                 policy.setParent(app);
202                 policy.start();
203                 app.setRollingPolicy(policy);
204             } else if (appender.getRollingPolicyType().equals("TimeBasedRollingPolicy")) {
205                 TimeBasedRollingPolicy<ILoggingEvent> policy = new TimeBasedRollingPolicy<>();
206                 policy.setContext(context);
207                 policy.setMaxHistory(appender.getMaxHistory());
208                 if (appender.getCleanHistoryOnStart() != null) {
209                     policy.setCleanHistoryOnStart(appender.getCleanHistoryOnStart());
210                 }
211                 policy.setFileNamePattern(appender.getFileNamePattern());
212                 policy.setParent(app);
213                 policy.start();
214                 app.setRollingPolicy(policy);
215             }
216             SizeBasedTriggeringPolicy<ILoggingEvent> triggeringPolicy = new SizeBasedTriggeringPolicy<>();
217             triggeringPolicy.setContext(context);
218             triggeringPolicy.setMaxFileSize(appender.getMaxFileSize());
219             triggeringPolicy.start();
220             app.setTriggeringPolicy(triggeringPolicy);
221             app.setName(appender.getName());
222             app.start();
223             appendersMap.put(app.getName(), app);
224         }
225         return appendersMap;
226     }
227
228     @Override
229     public void close() throws IOException {
230         statusListener.close();
231     }
232 }