2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.config.yang.logback.config;
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;
30 import org.slf4j.LoggerFactory;
33 * Implementation of {@link ContextSetter}. Resets running logback
36 public class ContextSetterImpl implements ContextSetter, Closeable {
38 private final LogbackStatusListener statusListener;
39 private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ContextSetterImpl.class);
41 public ContextSetterImpl(final LogbackRuntimeRegistrator rootRuntimeBeanRegistratorWrapper) {
42 statusListener = new LogbackStatusListener(rootRuntimeBeanRegistratorWrapper);
43 statusListener.register();
47 public void updateContext(final LogbackModule module) {
48 LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
50 List<ch.qos.logback.classic.Logger> loggersBefore = context.getLoggerList();
52 createLoggers(context, module, Sets.newHashSet(loggersBefore));
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());
66 app.setEncoder(encoder);
67 ThresholdFilter filter = new ThresholdFilter();
68 filter.setContext(context);
69 filter.setLevel(appender.getThresholdFilter());
71 app.getCopyOfAttachedFiltersList().add(filter);
72 app.setName(appender.getName());
74 appendersMap.put(app.getName(), app);
79 private void createLoggers(final LoggerContext context, final LogbackModule module,
80 final Set<ch.qos.logback.classic.Logger> loggersBefore) {
82 Map<String, Appender<ILoggingEvent>> appendersMap = getAppenders(module, context);
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());
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");
92 logbackLogger.setLevel(Level.toLevel(logger.getLevel()));
94 addNewAppenders(appendersMap, logger, logbackLogger, appendersBefore);
95 removeBeforeAppenders(loggersBefore, logger, logbackLogger, appendersBefore);
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);
107 throw new IllegalStateException("No appender " + appenderName
108 + " found. This error should have been discovered by validation");
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());
123 loggersBefore.remove(logbackLogger);
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());
135 return Optional.of(appendersBefore);
137 return Optional.absent();
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));
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",
156 allAppenders.put(appenderName, appendersToAdd.get(appenderName));
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());
172 app.setEncoder(encoder);
173 app.setFile(appender.getFileName());
174 app.setName(appender.getName());
176 appendersMap.put(app.getName(), app);
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());
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);
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());
212 policy.setFileNamePattern(appender.getFileNamePattern());
213 policy.setParent(app);
215 app.setRollingPolicy(policy);
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());
224 appendersMap.put(app.getName(), app);
230 public void close() throws IOException {
231 statusListener.close();