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 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;
29 import org.slf4j.LoggerFactory;
32 * Implementation of {@link ContextSetter}. Resets running logback
35 public class ContextSetterImpl implements ContextSetter, Closeable {
37 private final LogbackStatusListener statusListener;
38 private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ContextSetterImpl.class);
40 public ContextSetterImpl(final LogbackRuntimeRegistrator rootRuntimeBeanRegistratorWrapper) {
41 statusListener = new LogbackStatusListener(rootRuntimeBeanRegistratorWrapper);
42 statusListener.register();
46 public void updateContext(final LogbackModule module) {
47 LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
49 List<ch.qos.logback.classic.Logger> loggersBefore = context.getLoggerList();
51 createLoggers(context, module, Sets.newHashSet(loggersBefore));
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());
65 app.setEncoder(encoder);
66 ThresholdFilter filter = new ThresholdFilter();
67 filter.setContext(context);
68 filter.setLevel(appender.getThresholdFilter());
70 app.getCopyOfAttachedFiltersList().add(filter);
71 app.setName(appender.getName());
73 appendersMap.put(app.getName(), app);
78 private void createLoggers(final LoggerContext context, final LogbackModule module,
79 final Set<ch.qos.logback.classic.Logger> loggersBefore) {
81 Map<String, Appender<ILoggingEvent>> appendersMap = getAppenders(module, context);
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());
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");
91 logbackLogger.setLevel(Level.toLevel(logger.getLevel()));
93 addNewAppenders(appendersMap, logger, logbackLogger, appendersBefore);
94 removeBeforeAppenders(loggersBefore, logger, logbackLogger, appendersBefore);
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);
106 throw new IllegalStateException("No appender " + appenderName
107 + " found. This error should have been discovered by validation");
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());
122 loggersBefore.remove(logbackLogger);
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());
134 return Optional.of(appendersBefore);
136 return Optional.absent();
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));
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",
155 allAppenders.put(appenderName, appendersToAdd.get(appenderName));
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());
171 app.setEncoder(encoder);
172 app.setFile(appender.getFileName());
173 app.setName(appender.getName());
175 appendersMap.put(app.getName(), app);
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());
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);
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());
211 policy.setFileNamePattern(appender.getFileNamePattern());
212 policy.setParent(app);
214 app.setRollingPolicy(policy);
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());
223 appendersMap.put(app.getName(), app);
229 public void close() throws IOException {
230 statusListener.close();