To configure a database connection to log4j

Source: Internet
Author: User
Tags connection pooling stmt log4j
We all know that log4j is an excellent open source logging project, we can not only customize the format of the output log, but also define the destination of the log output, such as: screen, text file, database, even through the socket output.
Now let's configure the log output to the database
The configuration is as follows:
#---JDBC---output to database
# jdbcappender Log4j.properties File
#log4j. Rootcategory=warn,jdbc
# Appender JDBC
Log4j.appender.jdbc=org.apache.log4j.jdbc.jdbcappender
Log4j.appender.jdbc.driver= Com.mysql.jdbc.Driver
Log4j.appender.jdbc.url= Jdbc:mysql://localhost:3306/test
Log4j.appender.jdbc.user=use
Log4j.appender.jdbc.password=password
Log4j.appender.jdbc.layout=org.apache.log4j.patternlayout
Log4j.appender.jdbc.sql=insert into LOGGING (log_date, Log_level, location, message) VALUES ('%d{iso8601} ', '%-5p ', '%c, %l ', '%m ')

The table structure is as follows:
Log_date VARCHAR2 (50)
Log_level VARCHAR2 (5)
Location VARCHAR2 (100)
Message VARCHAR2 (1000)
I do, but did not run successfully, and this method is to use the traditional database connection method, for the database management and inefficient, in the current era of the connection pool, why we can not give the log4j with the connection pool, let log4j use the data connection pool connection and database communication. Now look at the Log4j API and find that the Jdbcappender class has the following paragraphs: warning:this version of Jdbcappender is very likely to being completely replaced in the future. Moreoever, it does not log exceptions. The Jdbcappender provides for sending log events to a database.

For use as a base class:override getconnection () to pass any connection you want. Typically this are used to enable application wide connection pooling. Override closeconnection (Connection con)--If you Override getconnection make sure to implement CloseConnection to handle The connection you generated. Typically this would return the connection to the pool it came from. Override getlogstatement (Loggingevent event) to produce specialized or dynamic statements. The default uses the SQL option value.

Originally log4j recommended that we use the jdbcappender provided as a base class, and then override the method of three parent classes: getconnection (), CloseConnection (Connection con) and Getlogstatement (Loggingevent event).
So, write a subclass of Jdbcpoolappender to replace this jdbcappender.
The Jdbcpoolappender code and its associated code are as follows:

Jdbcpoolappender.java:

Package common.log;
Import java.sql.Connection;
Import org.apache.log4j.spi.LoggingEvent;
Import java.sql.SQLException;
Import java.sql.Statement;
Import Java.util.Iterator;
Import Org.apache.log4j.spi.ErrorCode;
Import Org.apache.log4j.PatternLayout;
Import Common.sql.MyDB;
Import Common.sql.GeneralDb;

public class Jdbcpoolappender extends Org.apache.log4j.jdbc.JDBCAppender {

Private MyDB MyDB = null;
Protected String sqlname= ""; Increase the properties of a database Jndiname
protected Connection Connection = null;
protected String SQLStatement = "";
/**
* Size of loggingevent buffer before writting to the database.
* Default is 1.
*/
protected int buffersize = 1;

Public Jdbcpoolappender () {
Super ();
}

   /**
     * ArrayList holding the buffer of Logging Events.
     */
    public void Append (Loggingevent event) {
         Buffer.add (event);
        if (buffer.size () >= buffersize)
             Flushbuffer ();
   }

/**
* By default Getlogstatement sends the event to the required Layout object.
* The layout would format the given into a workable SQL string.
*
* Overriding this provides direct access to the Loggingevent
* When constructing the logging statement.
*
*/
Protected String Getlogstatement (Loggingevent event) {
Return GetLayout (). Format (event);
}

/**
*
* Override this to provide a alertnate method of getting
* Connections (such as caching). One method to the fix is to open
* Connections at the "start of" Flushbuffer () and close them at the
* End. I use a connection pool outside the Jdbcappender which is
* Accessed in a override of this method.
* */
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);
}


/**
* Override this to return the connection to a pool
* Resource.
*
* The default behavior holds a single connection open until the Appender
* is closed (typically when garbage collected).
*/
protected void CloseConnection (Connection con) {
Mydb=null;
try {
if (connection!= null &&!connection.isclosed ())
Connection.close ();
catch (SQLException e) {
Errorhandler.error ("Error closing connection", E,
Errorcode.generic_failure);
}

}

/**
* Override This function to return a Connetion object using the connection pool
*
*/
Protected Connection getconnection () throws SQLException {
try {
MyDB = Generaldb.getinstance (sqlname);
Connection = Mydb.getconnection ();
catch (Exception e) {
Errorhandler.error ("Error opening connection", E, errorcode.generic_failure);
}
return connection;
}

   /**
     * Closes the appender, flushing the buffer, the then, the de Fault
     * connection if it is open.
     */
    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;
}

/**
* Loops through the buffer of loggingevents, gets a
* SQL string from getlogstatement () and sends it to execute ().
* Errors are sent to the ErrorHandler.
*
* If A statement fails the loggingevent stays in the buffer!
*/
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 ();
}


/** closes the appender before disposal * *
public void Finalize () {
Close ();
}


/**
* Jdbcappender requires a layout.
* */
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);
}
}


/**
* Returns pre-formated statement eg:insert into logtable (msg) VALUES ("%m")
*/
Public String GetSQL () {
return sqlstatement;
}

public void Setsqlname (String sqlname) {
Sqlname=sqlname;
}

Public String Getsqlname () {
return sqlname;
}


public void setbuffersize (int newbuffersize) {
buffersize = newbuffersize;
Buffer.ensurecapacity (buffersize);
Removes.ensurecapacity (buffersize);
}


public int getbuffersize () {
return buffersize;
}
}


Mydb.java:
Package common.sql;
Import java.sql.*;
Import com.codestudio.sql.*; Introduction of Open Source project Poolman database connection pool Package

public class MyDB {
public static final String module = MyDB.class.getName ();
Private String dbname = "";
Private Poolman PLMN = null;


Public MyDB (String dbname) {
try {
if (PLMN = = null) {
PLMN = (Poolman) class.forname ("Com.codestudio.sql.PoolMan").
Newinstance ();
}
catch (Exception EC) {
System.out.println (ec.tostring () +module);
}
This.dbname = dbname;
}


Private Connection getnewconnection () {
Connection conn = null;
try {
conn = Plmn.connect ("jdbc:poolman://" + dbname);
Conn.setautocommit (TRUE);
catch (Exception EC) {
System.out.println (ec.tostring () + "First:connect Sqlsever failed" +module);
try {
Thread.Sleep (1000);
conn = Plmn.connect ("jdbc:poolman://" + dbname);
Conn.setautocommit (TRUE);
catch (Exception ECS) {
System.out.println (ecs.tostring () + "Again:connect sqlsever faile" +module);
}
}
Return conn;
}

Public Connection getconnection () {
return GetNewConnection ();
}
}
Generaldb.java:

Package common.sql; Package common.sql;

Import java.util.*;

public class Generaldb {
private static Hashtable Dbpool;
public static MyDB getinstance (String dbname) {
if (Dbpool = = null) {
Dbpool = new Hashtable ();
}
MyDB db = (MyDB) dbpool.get (dbname);
if (db = = null) {
db = new MyDB (dbname);
Dbpool.put (dbname, DB);
}
return DB;
}
}

The LOG4J database connection pool is configured as follows:
Log4j.appender.jdbc=common.log.jdbcpoolappender
Log4j.appender.jdbc.sqlname=log
Log4j.appender.jdbc.layout=org.apache.log4j.patternlayout
Log4j.appender.jdbc.sql=insert into LOGGING (log_date, Log_level, location, message) VALUES ('%d{iso8601} ', '%-5p ', '%c, %l ', '%m ')


The Poolman.xml configuration is as follows:

〈?xml version= "1.0" encoding= "UTF-8"?>
〈poolman>
〈management-mode>local〈/management-mode>
〈datasource>
〈dbname>log〈/dbname>
〈jndiname>log〈/jndiname>
〈driver>com.mysql.jdbc.driver〈/driver>
〈url>jdbc:mysql://localhost:3306/test〈/url>
〈username>use〈/username>
〈password>password〈/password>
〈minimumsize>0〈/minimumsize>
〈maximumsize>10〈/maximumsize>
〈logfile>logs/mysql.log〈/logfile>
〈/datasource>

〈/poolman>


Run successfully. For Jdbcpoolappender properties (such as the Sqlname attribute) we can add it by using the log4j reflection mechanism, as long as the configuration file attaches a value to it and the original parent class has some properties (username what) and its get, The set method is deleted because it is not required in the connection pool. And in the Jdbcpoolappender class, I just override the Getconnection method, in which we can generate our connection objects as needed, and the other two ways you can decide how to override according to your needs. :)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.