log4j输出到文件和数据库

官方API地址:http://logging.apache.org/log4j/1.2/apidocs/index.html?org/apache/log4j/PatternLayout.html

控制台的实现就不说了,这里提供两种实例的配置,一种是输出为文件的(每天输出一个文件),一种为输出到数据库的配置。

1、输出到文件:

log4j.rootCategory=WARN, CONSOLE, FILE

log4j.logger.com.surfilter.bt=FATAL,TOFILE

log4j.appender.TOFILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.TOFILE.Threshold=FATAL
log4j.appender.TOFILE.File=E:/javascpace/bt/logs/union.html
log4j.appender.TOFILE.Append=true
log4j.appender.TOFILE.ImmediateFlush=true
log4j.appender.TOFILE.DatePattern='.'yyyy-MM-dd'.html'
log4j.appender.TOFILE.layout=com.surfilter.bt.util.FormatHTMLLayout

 

这里的com.surfilter.bt.util.FormatHTMLLayout是重写了log4j提供的HTMLLayout类,具体代码如下:

import java.text.SimpleDateFormat;
import java.util.Map;

import org.apache.log4j.HTMLLayout;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.helpers.Transform;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;

import com.opensymphony.xwork2.ActionContext;
import com.surfilter.core.Constants;
import com.surfilter.security.domain.User;

public class FormatHTMLLayout extends HTMLLayout {

	public FormatHTMLLayout() {
	}

	protected final int BUF_SIZE = 256;

	protected final int MAX_CAPACITY = 1024;

	static String TRACE_PREFIX = "<br>&nbsp;&nbsp;&nbsp;&nbsp;";

	// output buffer appended to when format() is invoked
	private StringBuffer sbuf = new StringBuffer(BUF_SIZE);
	
	String title="系统操作日志";

	/**
	 * A string constant used in naming the option for setting the the HTML
	 * document title. Current value of this string constant is <b>Title</b>.
	 */
	public static final String TITLE_OPTION = "Title";

	// Print no location info by default
	boolean locationInfo = true;
	
	public String format(LoggingEvent event) {
		if (sbuf.capacity() > MAX_CAPACITY) {
			sbuf = new StringBuffer(BUF_SIZE);
		} else {
			sbuf.setLength(0);
		}
		sbuf.append(Layout.LINE_SEP + "<tr>" + Layout.LINE_SEP);
		
/*		sbuf.append("<td>");
		sbuf.append(String.valueOf(i));
		sbuf.append("</td>" + Layout.LINE_SEP);
*/		
		sbuf.append("<td>");
		sbuf.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
		sbuf.append("</td>" + Layout.LINE_SEP);

	/*	String escapedThread = Transform.escapeTags(event.getThreadName());
		sbuf.append("<td title=\"" + escapedThread + " thread\">");
		sbuf.append(escapedThread);
		sbuf.append("</td>" + Layout.LINE_SEP);
	*/
		sbuf.append("<td title=\"级别\">");
		if (event.getLevel().equals(Level.FATAL)) {
			sbuf.append("<font color=\"#339933\">");
			sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));
			sbuf.append("</font>");
		} else if (event.getLevel().isGreaterOrEqual(Level.WARN)) {
			sbuf.append("<font color=\"#993300\"><strong>");
			sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));
			sbuf.append("</strong></font>");
		} else {
			sbuf.append(Transform.escapeTags(String.valueOf(event.getLevel())));
		}
		sbuf.append("</td>" + Layout.LINE_SEP);
		
/*		String escapedLogger = Transform.escapeTags(event.getLoggerName().substring(event.getLoggerName().lastIndexOf(".")));
		sbuf.append("<td title=\"类名\">");
		sbuf.append(escapedLogger);
		sbuf.append("</td>" + Layout.LINE_SEP);
*/
		if (locationInfo) {
			LocationInfo locInfo = event.getLocationInformation();
			sbuf.append("<td title=\"行号\">");
			sbuf.append(Transform.escapeTags(locInfo.getFileName()));
			sbuf.append(':');
			sbuf.append(locInfo.getLineNumber());
			sbuf.append("</td>" + Layout.LINE_SEP);
		}
		Map session = ActionContext.getContext().getSession();
		if(session!=null){
			User user = (User) session.get(Constants.USER_IN_SESSION);
			sbuf.append("<td>"+user.getName()+"</td>");
		}else{
			sbuf.append("<td>&nbsp;</td>");
		}
		sbuf.append("<td title=\"日志信息\">");
		sbuf.append(Transform.escapeTags(event.getRenderedMessage()));
		sbuf.append("</td>" + Layout.LINE_SEP);
		sbuf.append("</tr>" + Layout.LINE_SEP);

		if (event.getNDC() != null) {
			sbuf.append("<tr><td bgcolor=\"#EEEEEE\" style=\"font-size : xx-small;\" colspan=\"6\" title=\"Nested Diagnostic Context\">");
			sbuf.append("NDC: " + Transform.escapeTags(event.getNDC()));
			sbuf.append("</td></tr>" + Layout.LINE_SEP);
		}

		String[] s = event.getThrowableStrRep();
		if (s != null) {
			sbuf.append("<tr><td bgcolor=\"#993300\" style=\"color:White; font-size : xx-small;\" colspan=\"4\">");
			appendThrowableAsHTML(s, sbuf);
			sbuf.append("</td></tr>" + Layout.LINE_SEP);
		}
		return sbuf.toString();
	}

	private void appendThrowableAsHTML(String[] s, StringBuffer sbuf) {
		if (s != null) {
			int len = s.length;
			if (len == 0)
				return;
			sbuf.append(Transform.escapeTags(s[0]));
			sbuf.append(Layout.LINE_SEP);
			for (int i = 1; i < len; i++) {
				sbuf.append(TRACE_PREFIX);
				sbuf.append(Transform.escapeTags(s[i]));
				sbuf.append(Layout.LINE_SEP);
			}
		}
	}

	/**
	 * Returns appropriate HTML headers.
	 */
	public String getHeader() {
		StringBuffer sbuf = new StringBuffer();
		sbuf.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" + Layout.LINE_SEP);
		sbuf.append("<html>" + Layout.LINE_SEP);
		sbuf.append("<head>" + Layout.LINE_SEP);
	//	sbuf.append("<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">");
		sbuf.append("<title>" + title + "</title>" + Layout.LINE_SEP);
		sbuf.append("<style type=\"text/css\">" + Layout.LINE_SEP);
		sbuf.append("<!--" + Layout.LINE_SEP);
		sbuf.append("body, table {font-family: '宋体',arial,sans-serif; font-size: 12px;}" + Layout.LINE_SEP);
		sbuf.append("th {background: #336699; color: #FFFFFF; text-align: left;}" + Layout.LINE_SEP);
		sbuf.append("-->" + Layout.LINE_SEP);
		sbuf.append("</style>" + Layout.LINE_SEP);
		sbuf.append("</head>" + Layout.LINE_SEP);
		sbuf.append("<body bgcolor=\"#FFFFFF\" topmargin=\"6\" leftmargin=\"6\">" + Layout.LINE_SEP);
	//	sbuf.append("<hr size=\"1\" noshade>" + Layout.LINE_SEP);
	//	sbuf.append("Log session start time " + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new java.util.Date()) + "<br>" + Layout.LINE_SEP);
	//	sbuf.append("<p>" + Layout.LINE_SEP);
		sbuf.append("<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\" bordercolor=\"#224466\" width=\"100%\">" + Layout.LINE_SEP);
		sbuf.append("<tr>" + Layout.LINE_SEP);
	//	sbuf.append("<th>序列</th>" + Layout.LINE_SEP);
		sbuf.append("<th>执行时间</th>" + Layout.LINE_SEP);
		sbuf.append("<th>级别</th>" + Layout.LINE_SEP);
	//	sbuf.append("<th>所在类</th>" + Layout.LINE_SEP);
		if (locationInfo) {
			sbuf.append("<th>所在行</th>" + Layout.LINE_SEP);
		}
		sbuf.append("<th>操作人</th>");
		sbuf.append("<th>信息</th>" + Layout.LINE_SEP);
		sbuf.append("</tr>" + Layout.LINE_SEP);
		sbuf.append("<br></br>" + Layout.LINE_SEP);
		return sbuf.toString();
	}

}

注,上面输出里包含了从当前session里取到的用户信息,只需要重写getHeader,format,appendThrowableAsHTML三个方法就可以了。LoggingEvent 提供的方法可以获取各种日志信息。 

 

2、输入到数据库,现在配置是将日志信息同时输出到文件和数据库

log4j.rootCategory=WARN, CONSOLE, FILE

log4j.logger.com.surfilter.bt=FATAL,TOFILE,JDBC

log4j.appender.TOFILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.TOFILE.Threshold=FATAL
log4j.appender.TOFILE.File=E:/javascpace/bt/logs/union.html
log4j.appender.TOFILE.Append=true
log4j.appender.TOFILE.ImmediateFlush=true
log4j.appender.TOFILE.DatePattern='.'yyyy-MM-dd'.html'
log4j.appender.TOFILE.layout=com.surfilter.bt.util.FormatHTMLLayout
log4j.appender.JDBC=org.apache.log4j.jdbc.JDBCAppender
#log4j.appender.JDBC=com.surfilter.bt.util.Log4jToDBAppender 
log4j.appender.JDBC.Threshold=FATAL
log4j.appender.JDBC.URL=jdbc:oracle:thin:@127.0.0.1:1521:orcl
log4j.appender.JDBC.driver=oracle.jdbc.driver.OracleDriver
log4j.appender.JDBC.user=db_user
log4j.appender.JDBC.password=db_password
log4j.appender.JDBC.sql=insert into sys_log(id,loginid,PRIORITY,LOGDATE,CLASS,METHOD,MSG) values (seq_sys_log.nextval,'0','%p','%d{yyyy-MM-dd HH:mm:ss}','%c{1}','%-10.50l','%m')
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout

 

 以上配置将会同时输出到文件和数据库,注意这里有一行注释掉的实现com.surfilter.bt.util.Log4jToDBAppender,如果你要使用连接池可以继承JDBCAppender重写实现,下面是JDBCAppender的实现源码,可以从log4j官网上down到:

package org.apache.log4j.jdbc;

import org.apache.log4j.spi.*;
import org.apache.log4j.PatternLayout;

import java.util.ArrayList;
import java.util.Iterator;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.SQLException;

public class JDBCAppender extends org.apache.log4j.AppenderSkeleton
    implements org.apache.log4j.Appender {

  protected String databaseURL = "jdbc:odbc:myDB";

  protected String databaseUser = "me";

  protected String databasePassword = "mypassword";

  protected Connection connection = null;

  protected String sqlStatement = "";

  protected int bufferSize = 1;

  protected ArrayList buffer;

  protected ArrayList removes;

  public JDBCAppender() {
    super();
    buffer = new ArrayList(bufferSize);
    removes = new ArrayList(bufferSize);
  }

  public void append(LoggingEvent event) {
    buffer.add(event);

    if (buffer.size() >= bufferSize)
      flushBuffer();
  }

  protected String getLogStatement(LoggingEvent event) {
    return getLayout().format(event);
  }

  protected void execute(String sql) throws SQLException {

    Connection con = null;
    Statement stmt = null;

    try {
        con = getConnection();

        stmt = con.createStatement();
        stmt.executeUpdate(sql);
    } catch (SQLException e) {
       if (stmt != null)
	     stmt.close();
       throw e;
    }
    stmt.close();
    closeConnection(con);

    //System.out.println("Execute: " + sql);
  }

  protected void closeConnection(Connection con) {
  }

  protected Connection getConnection() throws SQLException {
      if (!DriverManager.getDrivers().hasMoreElements())
	     setDriver("sun.jdbc.odbc.JdbcOdbcDriver");

      if (connection == null) {
        connection = DriverManager.getConnection(databaseURL, databaseUser,
					databasePassword);
      }

      return connection;
  }

  public void close()
  {
    flushBuffer();

    try {
      if (connection != null && !connection.isClosed())
          connection.close();
    } catch (SQLException e) {
        errorHandler.error("Error closing connection", e, ErrorCode.GENERIC_FAILURE);
    }
    this.closed = true;
  }

  public void flushBuffer() {
    //Do the actual logging
    removes.ensureCapacity(buffer.size());
    for (Iterator i = buffer.iterator(); i.hasNext();) {
      try {
        LoggingEvent logEvent = (LoggingEvent)i.next();
	    String sql = getLogStatement(logEvent);
	    execute(sql);
        removes.add(logEvent);
      }
      catch (SQLException e) {
	    errorHandler.error("Failed to excute sql", e,
			   ErrorCode.FLUSH_FAILURE);
      }
    }
    
    // remove from the buffer any events that were reported
    buffer.removeAll(removes);
    
    // clear the buffer of reported events
    removes.clear();
  }

  public void finalize() {
    close();
  }

  public boolean requiresLayout() {
    return true;
  }

  public void setSql(String s) {
    sqlStatement = s;
    if (getLayout() == null) {
        this.setLayout(new PatternLayout(s));
    }
    else {
        ((PatternLayout)getLayout()).setConversionPattern(s);
    }
  }

  public String getSql() {
    return sqlStatement;
  }


  public void setUser(String user) {
    databaseUser = user;
  }

  public void setURL(String url) {
    databaseURL = url;
  }

  public void setPassword(String password) {
    databasePassword = password;
  }

  public void setBufferSize(int newBufferSize) {
    bufferSize = newBufferSize;
    buffer.ensureCapacity(bufferSize);
    removes.ensureCapacity(bufferSize);
  }

  public String getUser() {
    return databaseUser;
  }

  public String getURL() {
    return databaseURL;
  }

  public String getPassword() {
    return databasePassword;
  }

  public int getBufferSize() {
    return bufferSize;
  }

  public void setDriver(String driverClass) {
    try {
      Class.forName(driverClass);
    } catch (Exception e) {
      errorHandler.error("Failed to load driver", e,
			 ErrorCode.GENERIC_FAILURE);
    }
  }
}

 
然后说一下PatternLayout里的ConversionPattern主要的格式化输开形式,Log4J采用类似C语言中的printf函数的打印,格式化日志信息,打印参数如下:

 %m 输出代码中指定的消息


 %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL


 %r 输出自应用启动到输出该log信息耗费的毫秒数


 %c 输出所属的类目,通常就是所在类的全名,例%c{1}: 类名"a.b.c" 时输出 "c"


 %t 输出产生该日志事件的线程名


 %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”

 %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比 如:%d{yyyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921

 %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。

你可能感兴趣的:(apache,oracle,sql,log4j,jdbc)