概述
2019独角兽企业重金招聘Python工程师标准>>>
每一个servlet容器都需要去定位问题,那日志肯定是必不可少的。我们平时启动系统的时候发现日志一直在打印一些信息,信息或是来自容器系统中,或是来自我们的应用系统。下面介绍简单的文件日志系统搭建。
日志文件搭建主要包含以下几个部分:
1、日志文件搭建
2、将日志文件配置到容器中。
3、连接器获得容器的logger实例写信息
4、HttpProcessor通过连接器获得容器的logger实例写信息
1、日志文件搭建:
日志文件的接口关系如图:
public interface Logger {
/**
* 详细的日志等级信息常亮
*/
public static final int FATAL = Integer.MIN_VALUE;
public static final int ERROR = 1;
public static final int WARNING = 2;
public static final int INFORMATION = 3;
public static final int DEBUG = 4;
//获取容器
public Container getContainer();
//设置容器
public void setContainer(Container container);
//获得关于日志实现和对应版本号的详细信息
public String getInfo();
//返回日志等级,比该等级高的日志信息会被忽略
public int getVerbosity();
//设置日志的等级信息,比该等级高的日志信息会被忽略
public void setVerbosity(int verbosity);
//添加该属性变化该组件的属性变化监听
public void addPropertyChangeListener(PropertyChangeListener listener);
//给servlet日志文件写特殊的信息,通常是一个环境日志。servlet日志的名字和类型对于容器来说是指定的具体的。该种类的信息被无条件的被记录。
public void log(String message);
//写错误信息给servlet日志文件。该方法的实现最终由log(msg, exception)实现
public void log(Exception exception, String msg);
//为servlet日志文件写入异常信息和堆栈信息
public void log(String message, Throwable throwable);
//为servlet日志文件写入特定信息,通常是事件日志,记录日志等级比verbosity设置的高或者相等的信息。
public void log(String message, int verbosity);
public void log(String message, Throwable throwable, int verbosity);
//删除属性变更监听器
public void removePropertyChangeListener(PropertyChangeListener listener);
}
------------------------------
package org.apache.catalina.logger;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import org.apache.catalina.Container;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Logger;
public abstract class LoggerBase
implements Logger {
//与日志关联的容器
protected Container container = null;
//debug等级
protected int debug = 0;
//包描述信息
protected static final String info =
"org.apache.catalina.logger.LoggerBase/1.0";
//容器的属性变更support实例
protected PropertyChangeSupport support = new PropertyChangeSupport(this);
//日志信息过滤级别,高于该级别的信息被记录下来
protected int verbosity = ERROR;
public Container getContainer() {
return (container);
}
//容器设置
public void setContainer(Container container) {
Container oldContainer = this.container;
this.container = container;
support.firePropertyChange("container", oldContainer, this.container);
}
//返回容器debugging详细级别。
public int getDebug() {
return (this.debug);
}
public void setDebug(int debug) {
this.debug = debug;
}
public String getInfo() {
return (info);
}
public int getVerbosity() {
return (this.verbosity);
}
public void setVerbosity(int verbosity) {
this.verbosity = verbosity;
}
public void setVerbosityLevel(String verbosity) {
if ("FATAL".equalsIgnoreCase(verbosity))
this.verbosity = FATAL;
else if ("ERROR".equalsIgnoreCase(verbosity))
this.verbosity = ERROR;
else if ("WARNING".equalsIgnoreCase(verbosity))
this.verbosity = WARNING;
else if ("INFORMATION".equalsIgnoreCase(verbosity))
this.verbosity = INFORMATION;
else if ("DEBUG".equalsIgnoreCase(verbosity))
this.verbosity = DEBUG;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
//抽象方法 具体的日志系统去实现
public abstract void log(String msg);
public void log(Exception exception, String msg) {
log(msg, exception);
}
//打印出错servlet的堆栈信息
public void log(String msg, Throwable throwable) {
CharArrayWriter buf = new CharArrayWriter();
PrintWriter writer = new PrintWriter(buf);
writer.println(msg);
throwable.printStackTrace(writer);
Throwable rootCause = null;
if (throwable instanceof LifecycleException)
rootCause = ((LifecycleException) throwable).getThrowable();
else if (throwable instanceof ServletException)
rootCause = ((ServletException) throwable).getRootCause();
if (rootCause != null) {
writer.println("----- Root Cause -----");
rootCause.printStackTrace(writer);
}
log(buf.toString());
}
//高于verbosity的信息被写打印出来
public void log(String message, int verbosity) {
if (this.verbosity >= verbosity)
log(message);
}
//高于verbosity的错误信息被写打印出来
public void log(String message, Throwable throwable, int verbosity) {
if (this.verbosity >= verbosity)
log(message, throwable);
}
//删除属性变更监听器
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
文件日志
public class FileLogger
extends LoggerBase
implements Lifecycle {
//日期字段
private String date = "";
/**
* 目录字段
*/
private String directory = "logs";
/**
* 文件名称/版本号信息,即该日志实现的详细信息
*/
protected static final String info =
"org.apache.catalina.logger.FileLogger/1.0";
/**
* 观察者
*/
protected LifecycleSupport lifecycle = new LifecycleSupport(this);
/**
* 日志前缀
*/
private String prefix = "catalina.";
/**
* 是否启动flag
*/
private boolean started = false;
//日志文件后缀
private String suffix = ".log";
//是否有时间戳
private boolean timestamp = false;
private PrintWriter writer = null;
public void setDirectory(String directory) {
String oldDirectory = this.directory;
this.directory = directory;
//如果目录文件有改变触发属性变更监听器
support.firePropertyChange("directory", oldDirectory, this.directory);
}
public void setPrefix(String prefix) {
String oldPrefix = this.prefix;
this.prefix = prefix;
support.firePropertyChange("prefix", oldPrefix, this.prefix);
}
public void setSuffix(String suffix) {
String oldSuffix = this.suffix;
this.suffix = suffix;
support.firePropertyChange("suffix", oldSuffix, this.suffix);
}
public boolean getTimestamp() {
return (timestamp);
}
public void setTimestamp(boolean timestamp) {
boolean oldTimestamp = this.timestamp;
this.timestamp = timestamp;
support.firePropertyChange("timestamp", new Boolean(oldTimestamp),
new Boolean(this.timestamp));
}
public void log(String msg) {
// 创建一个时间戳
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
//截取日期信息
String tsDate = tsString.substring(0, 10);
// 如果日期和原信息不一致
if (!date.equals(tsDate)) {
//线程安全的重新生成新的日志文件
synchronized (this) {
if (!date.equals(tsDate)) {
close();
date = tsDate;
open();
}
}
}
// 想日志里面写信息
if (writer != null) {
//如果设置了时间戳标识,则写时间戳信息+信息
if (timestamp) {
writer.println(tsString + " " + msg);
} else {
//如果没有设置时间戳,则直接写信息
writer.println(msg);
}
}
}
private void close() {
//将输出流的信息全部写入文件,并关闭输出流
if (writer == null)
return;
writer.flush();
writer.close();
writer = null;
date = "";
}
private void open() {
// 根据目录信息写文件
File dir = new File(directory);
//如果dir不是绝对路径
if (!dir.isAbsolute())
//则获取容器安装目录,再通过directory定位文件绝对位置
dir = new File(System.getProperty("catalina.base"), directory);
//创建目录
dir.mkdirs();
// Open the current log file
try {
//拼文件名称
String pathname = dir.getAbsolutePath() + File.separator +
prefix + date + suffix;
//为文件设置写出流。
writer = new PrintWriter(new FileWriter(pathname, true), true);
} catch (IOException e) {
writer = null;
}
}
//增加监听信息
public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
//返回日志系统所有的监听器
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
//删除某监听器
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
//启动日志系统
public void start() throws LifecycleException {
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("fileLogger.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
}
//关闭日志系统
public void stop() throws LifecycleException {
// Validate and update our current component state
if (!started)
throw new LifecycleException
(sm.getString("fileLogger.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
close();
}
}
2、将日志文件配置到容器中
Context context = new SimpleContext();
FileLogger logger = new FileLogger();
logger.setPrefix("FileLog_");
logger.setSuffix(".txt");
logger.setTimestamp(true);
logger.setDirectory("webroot");
context.setLogger(logger);
3、连接器获得容器的logger实例写信息
private void log(String message) {
Logger logger = container.getLogger();
String localName = threadName;
if (localName == null)
localName = "HttpConnector";
if (logger != null)
logger.log(localName + " " + message);
else
System.out.println(localName + " " + message);
}
4、HttpProcessor通过连接器获得容器的logger实例写信息
private void log(String message) {
Logger logger = connector.getContainer().getLogger();
if (logger != null)
logger.log(threadName + " " + message);
}
转载于:https://my.oschina.net/zjItLife/blog/613135
最后
以上就是可耐萝莉为你收集整理的servlet解析演进(5)-添加日志的全部内容,希望文章能够帮你解决servlet解析演进(5)-添加日志所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复