Jetty 中的日志记录
最后修改于 2024 年 1 月 27 日
日志记录 是在程序生命周期中记录程序的活动。日志记录用于问题诊断、审计、调试或信息收集。
Java 中有几种日志框架可用。如果我们不指定日志框架,Jetty 会默认使用其内置的 org.eclipse.jetty.util.log.StdErrLog 实现。
默认日志记录
在本节中,我们将展示如何配置 Jetty 的标准日志记录。
$ java -jar $JETTY_HOME/start.jar 2014-09-12 12:06:25.699:INFO::main: Logging initialized @496ms 2014-09-12 12:06:25.973:INFO:oejs.Server:main: jetty-9.2.2.v20140723 2014-09-12 12:06:26.006:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:/home/janbodnar/prog/jetty/my-base/webapps/] at interval 1 ...
默认情况下,Jetty 会将消息打印到控制台。消息会出现在我们启动服务器的控制台上。
$ java -jar $JETTY_HOME/start.jar --add-to-start=logging
INFO: logging initialised in ${jetty.base}/start.ini (appended)
MKDIR: ${jetty.base}/logs
要开始配置日志记录功能,我们需要启用 Jetty 的日志记录模块。日志目录也会被创建。
$ pwd /home/janbodnar/prog/jetty/my-base $ mkdir resources $ cat resources/jetty-logging.properties org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StrErrLog org.eclipse.jetty.LEVEL=INFO jetty.logs=logs
在我们的 Jetty 基本目录中,我们创建 resources 目录。在 jetty-logging.properties 文件中,我们配置标准日志记录。消息会被定向到 logs 子目录。
$ java -jar $JETTY_HOME/start.jar
2014-09-12 17:05:41.535:INFO::main: Logging initialized @2575ms
2014-09-12 17:05:42.040:INFO::main: Redirecting stderr/stdout to
/home/janbodnar/prog/jetty/my-base/logs/2014_09_12.stderrout.log
启动 Jetty 后,我们会发现日志记录被重定向到了 logs 子目录。
$ ls -1 logs/ 2014_09_12.stderrout.log 2014_09_12.stderrout.log.105458616 2014_09_12.stderrout.log.150542014
日志文件被创建在 logs 子目录中。
启用 log4j
Apache log4j 是一个流行的日志库。Jetty 通过 Slf4j 门面和 Slf4j 到 log4j 的绑定层支持 log4j。
Java 的简单日志门面 (SLF4J) 作为各种日志框架(如 java.util.logging、logback 和 log4j)的简单门面或抽象。它允许在部署时插入所需的日志框架。
$ cat resources/jetty-logging.properties org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.Slf4jLog
在 jetty-logging.properties 文件中,我们选择简单日志门面来在 Jetty 中进行日志记录。
$ mkdir -p lib/logging/ $ mv ~/Downloads/log4j-1.2.17.jar lib/logging/ $ mv ~/Downloads/slf4j-api-1.7.7.jar lib/logging/ $ mv ~/Downloads/slf4j-log4j12-1.7.7.jar lib/logging/
lib/logging 目录被创建。必要的 JAR 文件从 Maven 仓库下载并移动到新创建的目录。
$ java -jar $JETTY_HOME/start.jar --list-modules ... Jetty Active Module Tree: ------------------------- + Module: jsp-impl [enabled] + Module: jstl-impl [enabled] + Module: logging [enabled] ...
请记住,必须为 Jetty 基本目录启用 logging 模块。
package com.zetcode;
import org.apache.log4j.Logger;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.WebServlet;
@WebServlet(urlPatterns = "/mylogservlet")
public class MyLoggingServlet extends HttpServlet {
static Logger log = Logger.getLogger(MyLoggingServlet.class.getName());
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("MyLogginServlet called");
log.info("MyLoggingServlet called");
}
}
我们创建一个简单的 Java servlet,并在其中进行一些基本的日志记录。
static Logger log = Logger.getLogger(MyLoggingServlet.class.getName());
创建了 Logger 类。
log.info("MyLoggingServlet called");
写入一条 INFO 级别的消息。
log4j.rootLogger=INFO, filer
log4j.appender.filer=org.apache.log4j.FileAppender
log4j.appender.filer.layout=org.apache.log4j.PatternLayout
log4j.appender.filer.layout.ConversionPattern=[%d] %p %c - %m%n
log4j.appender.filer.File=${jetty.base}/logs/jetty.log
log4j.appender.filer.append=true
log4j.properties 是 log4j 的配置文件。我们将其放在 resources 目录中。在配置文件中,我们选择将日志记录到具有特定日志模式的文件中。日志消息将包含日期、日志级别和应用程序消息。
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyLoggingServlet" default="compile">
<property name="name" value="mls"/>
<property environment="env"/>
<property name="src.dir" value="src"/>
<property name="web.dir" value="${src.dir}/web"/>
<property name="build.dir" location="${web.dir}/WEB-INF/classes"/>
<property name="jetty.lib.dir" location="${env.JETTY_HOME}/lib"/>
<property name="log4j.lib.dir" location="${env.JETTY_BASE}/lib/logging"/>
<property name="dist.dir" location="dist"/>
<property name="deploy.path" location="${env.JETTY_BASE}/webapps"/>
<path id="compile.classpath">
<fileset dir="${jetty.lib.dir}"/>
<fileset dir="${log4j.lib.dir}"/>
</path>
<target name="init">
<mkdir dir="${build.dir}"/>
<mkdir dir="${dist.dir}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src.dir}" destdir="${build.dir}"
includeantruntime="false">
<classpath refid="compile.classpath"/>
</javac>
<echo>Compilation completed</echo>
</target>
<target name="archive" depends="compile">
<war destfile="${dist.dir}/${name}.war" needxmlfile="false">
<fileset dir="${web.dir}"/>
</war>
<echo>Archive created</echo>
</target>
<target name="clean" depends="init">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}"/>
<echo>Cleaning completed</echo>
</target>
<target name="deploy" depends="archive">
<copy file="${dist.dir}/${name}.war" overwrite="true"
todir="${deploy.path}"/>
<echo>Archive deployed</echo>
</target>
</project>
这是我们示例的 Ant 构建文件。
$ ant deploy $ curl localhost:8080/mls/mylogservlet MyLogginServlet called
构建并部署包含我们的 servlet 的 Web 存档。调用该 servlet。
$ tail -2 logs/jetty.log [2014-09-16 15:11:25,254] INFO org.eclipse.jetty.server.Server - Started @2719ms [2014-09-16 15:11:42,214] INFO com.zetcode.MyLoggingServlet - MyLoggingServlet called
构建并运行示例后,我们在日志文件中找到了日志消息。
请求日志
记录请求是为了提供有用的网站所有者统计信息。Jetty 有 NCSARequestLog 类来保存传入的请求日志。该类可以使用 NCSA 通用和 NCSA 扩展日志格式。(NCSA HTTPd 是国家超级计算应用中心开发的早期 Web 服务器。)这些格式包含客户端的 IP 地址和用户代理、请求时间、状态码和 HTTP 方法等项目。它们被大多数 Web 分析软件理解。
该示例演示了如何在 Jetty 中启用请求日志记录。
<!DOCTYPE html> <html> <body> Simple page. </body> </html>
我们的应用程序将显示这个简单的网页。
<?xml version="1.0" encoding="UTF-8"?>
<project name="RequestLog" default="archive">
<property name="name" value="relog"/>
<property environment="env"/>
<property name="src.dir" value="src"/>
<property name="web.dir" value="${src.dir}/web"/>
<property name="dist.dir" location="dist"/>
<property name="deploy.path" location="${env.JETTY_BASE}/webapps"/>
<target name="init">
<mkdir dir="${dist.dir}"/>
</target>
<target name="archive">
<war destfile="${dist.dir}/${name}.war" needxmlfile="false">
<fileset dir="${web.dir}"/>
</war>
<echo>Archive created</echo>
</target>
<target name="clean" depends="init">
<delete dir="${dist.dir}"/>
<echo>Cleaning completed</echo>
</target>
<target name="deploy" depends="archive">
<copy file="${dist.dir}/${name}.war" overwrite="true"
todir="${deploy.path}"/>
<echo>Archive deployed</echo>
</target>
</project>
这是示例代码的 Ant 构建文件。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/relog</Set>
<Set name="war">/home/janbodnar/prog/jetty/logging2/dist/relog.war</Set>
<Set name="handler">
<New id="RequestLog"
class="org.eclipse.jetty.server.handler.RequestLogHandler">
<Set name="requestLog">
<New id="RequestLogImpl"
class="org.eclipse.jetty.server.NCSARequestLog">
<Set name="filename"><Property name="jetty.logs"
default="./logs"/>/access-yyyy_mm_dd.request.log</Set>
<Set name="filenameDateFormat">yyyy_MM_dd</Set>
<Set name="LogTimeZone">CET</Set>
<Set name="retainDays">90</Set>
<Set name="append">true</Set>
<Set name="logLatency">true</Set>
</New>
</Set>
</New>
</Set>
</Configure>
这是我们 Web 应用程序的 XML 配置。请求日志处理器仅为该 Web 应用程序启用。每天都会创建一个新的日志文件。日志文件保留 90 天后会被删除。
$ cp relog.xml $JETTY_BASE/webapps
relog.xml 文件被复制到 Jetty 基本目录的 webapps 目录中。该文件用作应用程序部署程序。
$ curl localhost:8080/relog/ <!DOCTYPE html> <html> <body> Simple page. </body> </html>
使用 curl 客户端发出请求。
$ tail -1 logs/access-2014_09_13.request.log
127.0.0.1 - - [13/Sep/2014:13:29:11 +0200] "GET /relog/ HTTP/1.1" 200
60 "-" "curl/7.35.0" 18
这是访问日志文件中的一个请求示例。
在 Jetty 教程的本章中,我们进行了一些基本的日志记录。
作者
列出所有Java教程。