1 /*
2  * Copyright 2008-2019 by Emeric Vernat
3  *
4  *     This file is part of Java Melody.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package net.bull.javamelody;
19
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 import ch.qos.logback.classic.Level;
24 import ch.qos.logback.classic.LoggerContext;
25 import ch.qos.logback.classic.PatternLayout;
26 import ch.qos.logback.classic.spi.ILoggingEvent;
27 import ch.qos.logback.core.UnsynchronizedAppenderBase;
28
29 /**
30  * Appender pour les logs de logback, configuré automatiquement par {@link MonitoringFilter}.
31  * @author Emeric Vernat
32  */

33 public class LogbackAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
34     private static final String MESSAGE_PATTERN = "%-5level %logger{36} - %msg%nopex%n";
35     private static final String EXCEPTION_PATTERN = "%ex";
36     private static final Level THRESHOLD = Level.WARN;
37
38     private static final LogbackAppender SINGLETON = new LogbackAppender();
39
40     private final PatternLayout exceptionLayout = new PatternLayout();
41
42     private final PatternLayout messageLayout = new PatternLayout();
43
44     /**
45      * Constructeur.
46      */

47     public LogbackAppender() {
48         super();
49         final LoggerContext lc = getDefaultContext();
50         messageLayout.setContext(lc);
51         messageLayout.setPattern(MESSAGE_PATTERN);
52         messageLayout.start();
53
54         exceptionLayout.setContext(lc);
55         exceptionLayout.setPattern(EXCEPTION_PATTERN);
56         exceptionLayout.start();
57
58         setContext(lc);
59         start();
60     }
61
62     private static LoggerContext getDefaultContext() {
63         return (LoggerContext) LoggerFactory.getILoggerFactory();
64     }
65
66     static LogbackAppender getSingleton() {
67         return SINGLETON;
68     }
69
70     void register() {
71         getDefaultContext().getLogger(Logger.ROOT_LOGGER_NAME).addAppender(this);
72     }
73
74     void deregister() {
75         getDefaultContext().getLogger(Logger.ROOT_LOGGER_NAME).detachAppender(this);
76     }
77
78     /**
79      * {@inheritDoc}
80      */

81     @Override
82     protected void append(ILoggingEvent event) {
83         // inutile de vérifier que l'appender est bien "started",
84         // car il est démarré dans le constructeur et si cela ne fonctionne pas il n'y a pas d'instance
85         if (event.getLevel().isGreaterOrEqual(THRESHOLD)) {
86             final String output = messageLayout.doLayout(event);
87             String stackTrace = exceptionLayout.doLayout(event);
88             if (stackTrace.isEmpty()) {
89                 stackTrace = null;
90             }
91             LoggingHandler.addErrorLogToCounter(output, stackTrace);
92         }
93     }
94 }
95