Project

General

Profile

« Previous | Next » 

Revision 72ddab96

Added by Andreas Kohlbecker over 2 years ago

ref #7085 using logback MDC for centralized logging into a rolling file appender and to system out

View differences:

.gitignore
6 6
/maven-eclipse.xml
7 7
/target
8 8
cdmlib-developer.log
9
cdm-server.log
9 10
workbench.xmi
pom.xml
668 668
      <artifactId>jetty-webapp</artifactId>
669 669
      <version>${jetty-version}</version>
670 670
    </dependency>
671
    <dependency>
672
        <groupId>org.eclipse.jetty</groupId>
673
        <artifactId>jetty-webapp-logging</artifactId>
674
        <version>9.4.20.v20190813</version><!-- versioning independent of jetty core -->
675
        <type>pom</type><!-- we only need the dependencies like jul-to-slf4j managed in this pom! -->
676
    </dependency>
671 677
    <dependency>
672 678
      <groupId>org.eclipse.jetty</groupId>
673 679
      <artifactId>jetty-plus</artifactId>
src/main/java/eu/etaxonomy/cdm/server/Bootloader.java
16 16
import static eu.etaxonomy.cdm.server.CommandOptions.HELP;
17 17
import static eu.etaxonomy.cdm.server.CommandOptions.HTTP_PORT;
18 18
import static eu.etaxonomy.cdm.server.CommandOptions.JMX;
19
import static eu.etaxonomy.cdm.server.CommandOptions.LOG_DIR;
20 19
import static eu.etaxonomy.cdm.server.CommandOptions.WEBAPP;
21 20
import static eu.etaxonomy.cdm.server.CommandOptions.WEBAPP_CLASSPATH;
22 21
import static eu.etaxonomy.cdm.server.CommandOptions.WIN32SERVICE;
......
68 67
import eu.etaxonomy.cdm.server.instance.InstanceManager;
69 68
import eu.etaxonomy.cdm.server.instance.SharedAttributes;
70 69
import eu.etaxonomy.cdm.server.instance.Status;
70
import eu.etaxonomy.cdm.server.logging.LoggingConfigurator;
71 71
import eu.etaxonomy.cdm.server.win32service.Win32Service;
72 72

  
73 73

  
......
115 115
    private File cdmRemoteWebAppFile = null;
116 116
    private File defaultWebAppFile = null;
117 117

  
118
    private String logPath = null;
119

  
120 118
    private String webAppClassPath = null;
121 119

  
122 120
    /**
......
127 125

  
128 126
    private Server server = null;
129 127
    private final ContextHandlerCollection contexts = new ContextHandlerCollection();
128
    private final LoggingConfigurator loggingConfigurator = new LoggingConfigurator();
130 129

  
131 130
    private CommandLine cmdLine;
132 131

  
......
343 342
    public void startServer() throws IOException,
344 343
            FileNotFoundException, Exception, InterruptedException {
345 344

  
346

  
347
        if(cmdLine.hasOption(LOG_DIR.getOpt())){
348
            logPath = cmdLine.getOptionValue(LOG_DIR.getOpt());
349
        } else {
350
            logPath = LOG_PATH;
351
        }
352

  
353

  
354
        //assure LOG_PATH exists
355
        File logPathFile = new File(logPath);
356
        if(!logPathFile.exists()){
357
            FileUtils.forceMkdir(new File(logPath));
358
        }
359

  
360
        //append logger
361
//        configureFileLogger();
362

  
363
        logger.info("Starting "+APPLICATION_NAME);
345
        logger.info("Starting " + APPLICATION_NAME);
364 346
        logger.info("Using  " + System.getProperty("user.home") + " as home directory. Can be specified by -Duser.home=<FOLDER>");
365 347

  
366 348
        //assure TMP_PATH exists and clean it up
......
466 448

  
467 449
        jdk8MemleakFixServer();
468 450

  
451
        loggingConfigurator.configureServer();
452

  
469 453
        server.addLifeCycleListener(instanceManager);
470 454
        ServerConnector connector = new ServerConnector(server);
471 455
        connector.setPort(httpPort);
......
533 517

  
534 518
        logger.info("setting contexts ...");
535 519
        server.setHandler(contexts);
520
        // server.setContexts(contexts);
521

  
536 522
        logger.info("starting jetty ...");
537 523
//        try {
538 524

  
......
656 642
    }
657 643

  
658 644

  
659
    /**
660
     * Configures and adds a {@link RollingFileAppender} to the root logger
661
     *
662
     * The log files of the cdm-remote instances are configured by the
663
     * {@link eu.etaxonomy.cdm.api.config.LoggingConfigurer}
664
     *
665
     *
666
     */
667
//   ===== removing useless RollingFileAppender logger === see #6287
668
//    private void configureFileLogger() {
669
//
670
//        PatternLayout layout = new PatternLayout("%d %p [%c] - %m%n");
671
//        try {
672
//            String logFile = logPath + File.separator + "cdmserver.log";
673
//            RollingFileAppender appender = new RollingFileAppender(layout, logFile);
674
//            appender.setMaxBackupIndex(3);
675
//            appender.setMaxFileSize("2MB");
676
//            Logger.getRootLogger().addAppender(appender);
677
//            logger.info("logging to :" + logFile);
678
//        } catch (IOException e) {
679
//            logger.error("Creating RollingFileAppender failed:", e);
680
//        }
681
//    }
682

  
683

  
684 645
    /**
685 646
     * Adds a new WebAppContext to the contexts of the running jetty instance.
686 647
     * <ol>
......
740 701
        }
741 702
        setWebApp(cdmWebappContext, getCdmRemoteWebAppFile());
742 703

  
743
        cdmWebappContext.setInitParameter(SharedAttributes.ATTRIBUTE_CDM_LOGFILE,
744
                logPath + File.separator + "cdm-"
745
                        + conf.getInstanceName() + ".log");
746

  
747 704
        if( isRunningFromSource ){
748 705

  
749 706
            /*
......
770 727
            cdmWebappContext.setClassLoader(classLoader);
771 728
        }
772 729

  
773
        contexts.addHandler(cdmWebappContext);
730
        contexts.addHandler(loggingConfigurator.configureWebApp(cdmWebappContext, instance));
774 731
        instance.setWebAppContext(cdmWebappContext);
775 732
        cdmWebappContext.addLifeCycleListener(instance);
776 733
        instance.setStatus(Status.stopped);
src/main/java/eu/etaxonomy/cdm/server/instance/StartupQueue.java
15 15
import org.apache.log4j.Logger;
16 16
import org.eclipse.jetty.util.component.LifeCycle;
17 17
import org.eclipse.jetty.util.component.LifeCycle.Listener;
18
import org.slf4j.MDC;
19

  
20
import eu.etaxonomy.cdm.server.logging.InstanceLogWrapper;
18 21

  
19 22
/**
20 23
 * @author a.kohlbecker
......
182 185
        @Override
183 186
        public void run() {
184 187
            try {
188
                MDC.put(InstanceLogWrapper.CDM_INSTANCE, instance.getName());
189

  
185 190
                instance.getWebAppContext().setThrowUnavailableOnStartupException(true);
186 191
                instance.getWebAppContext().start();
187 192
                // release reference to the instance so
......
205 210
                } catch (Exception e1) {
206 211
                    /* IGNORE */
207 212
                }
213
            } finally {
214
                MDC.clear();
208 215
            }
209 216

  
210 217
        }
src/main/java/eu/etaxonomy/cdm/server/logging/InstanceLogWrapper.java
1
/**
2
* Copyright (C) 2020 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.server.logging;
10

  
11
import java.io.IOException;
12

  
13
import javax.servlet.ServletException;
14
import javax.servlet.http.HttpServletRequest;
15
import javax.servlet.http.HttpServletResponse;
16

  
17
import org.eclipse.jetty.server.Request;
18
import org.eclipse.jetty.server.handler.HandlerWrapper;
19
import org.slf4j.MDC;
20

  
21
/**
22
 * @author a.kohlbecker
23
 * @since Jun 9, 2020
24
 */
25
public class InstanceLogWrapper extends HandlerWrapper {
26

  
27

  
28
    /**
29
     * Key under which the instance name stored in the
30
     * Mapped Diagnostic Context (MDC)
31
     */
32
    public static final String CDM_INSTANCE = "cdmInstance";
33

  
34
    private String instanceName;
35

  
36
    public InstanceLogWrapper(String instanceName) {
37
        this.instanceName = instanceName;
38
    }
39

  
40
    @Override
41
    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
42
    {
43
        // Collect Info for NDC/MDC
44
        MDC.put(CDM_INSTANCE, instanceName);
45
        try
46
        {
47
            super.handle(target, baseRequest, request, response);
48
        }
49
        finally
50
        {
51
            // Pop info out / clear the NDC/MDC
52
            MDC.clear();
53
        }
54
    }
55

  
56
}
src/main/java/eu/etaxonomy/cdm/server/logging/LoggingConfigurator.java
1
/**
2
* Copyright (C) 2020 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.server.logging;
10

  
11
import org.eclipse.jetty.server.Handler;
12
import org.eclipse.jetty.webapp.WebAppContext;
13
import org.slf4j.bridge.SLF4JBridgeHandler;
14

  
15
import eu.etaxonomy.cdm.server.instance.CdmInstance;
16

  
17
/**
18
 * The technique used in this class is based on the example
19
 * for a jetty server which uses a deployment manager, explained
20
 * in https://www.eclipse.org/jetty/documentation/9.4.29.v20200521/example-logging-logback-centralized.html.
21
 * In our situation of an embedded jetty which manages the cdm-webapp instance directly the
22
 * configuration need to be a bit different.
23
 *
24
 * The config files of the official example can be downloaded from
25
 * https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-webapp-logging/9.4.20.v20190813/jetty-webapp-logging-9.4.20.v20190813-config.jar
26
 * extract the jar to examine the contained config files.
27
 *
28
 * @author a.kohlbecker
29
 * @since Jun 10, 2020
30
 */
31
public class LoggingConfigurator {
32

  
33
    public void configureServer() {
34
        // Configure logging (1)
35

  
36

  
37
        // > jetty-webapp-logging-9.4.20.v20190813-config/etc/jetty-jul-to-slf4j.xml
38
        SLF4JBridgeHandler.removeHandlersForRootLogger();
39
        SLF4JBridgeHandler.install();
40
        // >
41
        // jetty-webapp-logging-9.4.20.v20190813-config/resources/jetty-logging.properties
42
        System.setProperty("org.eclipse.jetty.util.log.class", org.eclipse.jetty.util.log.Slf4jLog.class.getName());
43

  
44
    }
45

  
46
    public Handler configureWebApp(WebAppContext cdmWebappContext, CdmInstance instance) {
47

  
48
        // > jetty-webapp-logging-9.4.20.v20190813-config/etc/jetty-webapp-logging.xml
49
        // ---> adds the org.eclipse.jetty.webapp.logging.CentralizedWebAppLoggingBinding
50
        // (from jetty-webapp-logging-9.4.20.v20190813.jar) to the DeploymentManager,
51
        // in the  cdm-server we are not using the DeploymentManager so
52
        // this needs to be done per web app explicitely:
53
        cdmWebappContext.addSystemClass("org.apache.log4j.");
54
        cdmWebappContext.addSystemClass("org.slf4j.");
55
        cdmWebappContext.addSystemClass("org.apache.commons.logging.");
56

  
57
        // > jetty-webapp-logging-9.4.20.v20190813-config/etc/jetty-mdc-handler.xml
58
        InstanceLogWrapper mdcHandler = new InstanceLogWrapper(instance.getName());
59
        mdcHandler.setHandler(cdmWebappContext); // wrap context handler
60
        return mdcHandler;
61
    }
62
}
src/main/resources/logback.xml
1
<!-- 
2
This is the default logfile for the cdm-sever. 
3

  
4
Logback provides a system property variable (see ch.qos.logback.classic.util.ContextInitializer#CONFIG_FILE_PROPERTY) 
5
by which custom configuration files can be specified for production and test environments:
6

  
7
-Dlogback.configurationFile=file:/app/logback.xml
8

  
9
 -->
10
<configuration>
11
  <!-- address performance concern with jul-to-slf4j -->
12
  <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
13
    <resetJUL>true</resetJUL>
14
  </contextListener>
15

  
16
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
17
  
18
  <property name="LOG_FOLDER" value="${cdm.logDir}:-${user.home}/.cdmLibrary/log}" />
19
  <property name="ROLL_DAY" value="%d{yyyy-MM-dd}" />
20
  <property name="ROLL_MINUTE" value="%d{yyyy-MM-dd-mm}" />
21

  
22
  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
23
    <append>true</append>
24
    <file>${LOG_FOLDER}/cdm-server.log</file>
25
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
26
      <!-- daily rollover -->
27
      <fileNamePattern>${LOG_FOLDER}/cdm-server.${ROLL_DAY}.log.gz</fileNamePattern>
28
      <!-- keep 30 days' worth of history capped at 3GB total size -->
29
      <maxHistory>30</maxHistory>
30
      <totalSizeCap>3GB</totalSizeCap>
31
    </rollingPolicy>
32
    <encoder>
33
      <pattern>%d{HH:mm:ss.SSS} [%X{cdmInstance}] [%thread] %-5level %logger{36} - %msg%n</pattern>
34
    </encoder>
35
  </appender>
36

  
37
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
38
    <layout>
39
      <pattern>%d{HH:mm:ss.SSS} [%X{cdmInstance}] [%thread] %-5level %logger{36} - %msg%n</pattern>
40
    </layout>
41
  </appender>
42
  
43
  <logger name="eu.etaxonomy.cdm.server" level="INFO" />
44

  
45
  <logger name="eu.etaxonomy.cdm" level="INFO" />
46
  <!-- avoid vast amount of "getCitation not yet implemented" & "getProblems not yet implemented" messages -->
47
  <logger name="eu.etaxonomy.cdm.model.name.TaxonNameBase" level="ERROR" />
48
  <logger name="eu.etaxonomy.cdm.persistence.dao.initializer" level="ERROR" />
49
  <logger name="eu.etaxonomy.cdm.cache.CdmTransientEntityCacher" level="WARN" />
50
  <logger name="eu.etaxonomy.cdm.remote.controller.interceptor" level="WARN" />
51
  <!-- prevent CdmExceptionResolver from logging errors -->
52
  <logger name="eu.etaxonomy.cdm.persistence.dao.initializer" level="ERROR" />
53
  <!-- json-lib -->
54
  <logger name="net.sf.json.JSONObject" level="ERROR" />
55
  <!-- Hibernate -->
56
  <logger name="org.hibernate" level="WARN" />
57
  <logger name="org.hibernate.search" level="ERROR" />
58
  <logger name="org.hibernate.engine.StatefulPersistenceContext.ProxyWarnLog" level="ERROR" />
59
  <!--      > supress HHH90000003 -->
60
  <logger name="org.hibernate.orm.deprecation" level="ERROR" />
61
  <!--  connection pool -->
62
  <logger name="com.mchange.v2.c3p0" level="WARN" />
63
  
64
  <!-- suppress nasty ehcache OutOfMemory warnings -->
65
  <logger name="net.sf.ehcache.config.CacheConfiguration" level="WARN" />
66
  
67
  <logger name="org.eclipse.jetty" level="INFO" />
68

  
69
  <root level="WARN">
70
    <appender-ref ref="FILE" />
71
    <appender-ref ref="STDOUT" />
72
  </root>
73
</configuration>

Also available in: Unified diff