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教程。