Revision 72ddab96
Added by Andreas Kohlbecker over 2 years ago
.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
ref #7085 using logback MDC for centralized logging into a rolling file appender and to system out