java Tomcat WAR - 配置 Logback 以在路径中使用应用程序名称

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10465301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:09:41  来源:igfitidea点击:

Tomcat WAR - Configure Logback to use app name in path

javatomcatslf4jlogback

提问by HaxElit

I have logback deployed in my war file lib folder and I have the following logback.xml in the classes folder.

我在我的 war 文件 lib 文件夹中部署了 logback,并且在 classes 文件夹中有以下 logback.xml。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
  <property name="destination" value="${catalina.base:-./temp}/logs/${appName:-myapp}" />

  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${destination}.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!-- rollover daily -->
      <fileNamePattern>${destination}-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
      <!-- Keep logs for 7 days -->
      <maxHistory>7</maxHistory>

      <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <!-- or whenever the file size reaches 100MB -->
        <maxFileSize>100MB</maxFileSize>
      </timeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="error">
    <appender-ref ref="ROLLING" />
  </root>
</configuration>

On line 3 I have some variable substitutions that create the path for my log file.

在第 3 行,我有一些变量替换为我的日志文件创建路径。

  <property name="destination" value="${catalina.base:-./temp}/logs/${appName:-myapp}" />

I want to make it so ${appName}evaluates to the current name of the war file as deployed.

我想让它${appName}评估为部署的War文件的当前名称。

So if my web apps folder looked like so

所以如果我的网络应用程序文件夹看起来像这样

webapps
 - myapp.war
 - myapp-dev.war

The ${destination}property for myapp.war would evaluate to .../logs/myappand myapp-dev.war would evaluate to .../logs/myapp-dev. Is there a JNDI property or something I can access to access the appName ?

${destination}myapp.war的属性将评估为,.../logs/myapp而 myapp-dev.war 将评估为.../logs/myapp-dev。是否有 JNDI 属性或我可以访问的内容来访问 appName ?

I would like to avoid having to manually reconfigure the logger.

我想避免手动重新配置记录器。

Thanks!

谢谢!

采纳答案by Michael-O

EDIT 2013-06: I have made this Listeneravailable as OSS on Maven Central. Check out the project homepage.

编辑 2013-06:我已将其Listener作为 Maven Central 上的 OSS 提供。查看项目主页

Yes, this is feasible. First of all, you can always rely on catalina.basebecause without it Tomcat won't run. In order to inject the context name as property. Write a context listenerwhich will put the context name into the JNDI context and remove at shutdown. After you have done that, You can retrieve the value with JNDI directly with logback. There is direct support for that. Write that in the the contextName element and you're done.

是的,这是可行的。首先,您始终可以依靠,catalina.base因为没有它Tomcat 将无法运行。为了注入上下文名称作为属性。编写一个上下文侦听器,它将上下文名称放入 JNDI 上下文并在关闭时删除。完成后,您可以直接使用 logback 使用 JNDI 检索值。对此有直接的支持。把它写在 contextName 元素中,你就完成了。

I have implemented this on my own already and it works for all of my projects. I can share the entire code on monday if you or someone else is interested.

我已经自己实现了它,它适用于我的所有项目。如果您或其他人感兴趣,我可以在星期一分享整个代码。

Edit, here is the code:

编辑,这里是代码:

import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.deploy.ContextEnvironment;
import org.apache.commons.lang.StringUtils;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

public class LogbackContextNameListener implements LifecycleListener {

    private static final Log logger = LogFactory
            .getLog(LogbackContextNameListener.class);
    private Context context;

    private String name = "logback/contextName";

    @Override
    public void lifecycleEvent(LifecycleEvent le) {

        if (le.getLifecycle() instanceof Context)
            context = (Context) le.getLifecycle();
        else
            return;

        if (le.getType().equals(Lifecycle.START_EVENT)) {
            ContextEnvironment ce = new ContextEnvironment();
            ce.setName(getName());
            ce.setOverride(false);
            ce.setType("java.lang.String");
            String value = StringUtils.remove(context.getServletContext()
                    .getContextPath(), '/');
            ce.setValue(value);
            logger.debug(String.format("Adding env entry '%s' with value '%s'",
                    getName(), value));
            context.getNamingResources().addEnvironment(ce);
        }

        if (le.getType().equals(Lifecycle.STOP_EVENT)) {
            logger.debug(String.format("Removing env entry '%s'", getName()));
            context.getNamingResources().removeEnvironment(name);
        }

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (StringUtils.isEmpty(name))
            throw new IllegalArgumentException(
                    "Parameter 'name' cannot be empty");

        this.name = name;
    }

}

A suitable config looks like this:

合适的配置如下所示:

<configuration scan="true" scanPeriod="30 minutes">

    <insertFromJNDI env-entry-name="java:comp/env/logback/contextName" as="contextName" />
    <contextName>${contextName}</contextName>

    <appender name="FILE"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${catalina.base}/logs/${CONTEXT_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover -->
            <fileNamePattern>${catalina.base}/logs/${CONTEXT_NAME}.log.%d.gz</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%-27(%d{HH:mm:ss.SSS} [%.-12thread]) %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO"><!-- WARN -->
        <appender-ref ref="FILE" />
    </root>

</configuration>

This works flawlessly in Tomcat 6. I guess, it will run on Tomcat 7 w/o changes.

这在 Tomcat 6 中可以完美运行。我想,它可以在 Tomcat 7 上运行而无需更改。

回答by Ceki

This builds on Michael-O's answer. Considering that catalina.baseis always a defined system property when running under Tomcat, we only have to worry about defining appName. Logback offers support for retrieving variables from JNDI. If appName is defined in JNDI, your configuration file becomes:

这建立在 Michael-O 的回答之上。考虑到catalina.base在 Tomcat 下运行时总是一个定义的系统属性,我们只需要担心定义appName. Logback 支持从 JNDI 检索变量。如果在 JNDI 中定义了 appName,您的配置文件将变为:

<configuration>
  <!-- retrieve appName from JNDI to set the variable appName -->
  <insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" />
  <!-- let the context name be the applicaiton name -->
  <contextName>${appName}</contextName>

  <property name="destination" 
            value="${catalina.base:-./temp}/logs/${CONTEXT_NAME:-myapp}" />

  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${destination}.log</file>
    ... remainder of config file omitted for brevity  
  </appender>
</configuration>

I'd like to mention that you could also just define appName directly in logback.xml instead of in JNDI. (After all, the logback.xml file ships with your web-app where its name is already established. However, your question explicitly excludes this hypothesis.) Thus, you logback.xml file could be simplified to:

我想提一下,您也可以直接在 logback.xml 中而不是在 JNDI 中定义 appName。(毕竟,logback.xml 文件随您的网络应用程序一起提供,其名称已经建立。但是,您的问题明确排除了这个假设。)因此,您的 logback.xml 文件可以简化为:

<configuration>
  <contextName>the_name_of_your_webapp</contextName>
  <property name="destination" 
            value="${catalina.base:-./temp}/logs/${CONTEXT_NAME:-myapp}" />
   ... the rest omitted for brevity
</configuration? 

BTW, once you find a satisfactory solution, do not hesitate to share it by posting on logback-user list.

顺便说一句,一旦你找到一个满意的解决方案,不要犹豫,通过在 logback-user 列表上发布来分享它。

回答by thomasmey

Isn't that the ContextSelector for? You may have a look at ContextJNDISelector and here http://logback.qos.ch/manual/contextSelector.html

那不是 ContextSelector 吗?你可以看看 ContextJNDISelector 和这里http://logback.qos.ch/manual/contextSelector.html

回答by Dawoon Yi

maxHistory doesn't mean the number of log files. It means the number of months.

maxHistory 并不意味着日志文件的数量。意思是月数。