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