blob: d64e772fd48d4afe7ac5886af7cdd34a65622294 [file] [log] [blame]
/**
// Class JDBCAppender, writes messages into a database
// The JDBCAppender is configurable at runtime in two alternatives :
// 1. Configuration-file
// Define the options in a file and call a PropertyConfigurator.configure(file)-method.
// 2. method JDBCAppender::setOption(JDBCAppender.xxx_OPTION, String value)
// The sequence of some options is important :
// 1. Connector-option OR/AND Database-options
// Any database connection is required !
// 2. (Table-option AND Columns-option) OR SQL-option
// Any statement is required !
// 3. All other options can be set at any time...
// The other options are optional and have a default initialization, which can be custumized.
// All available options are defined as static String-constants in JDBCAppender named xxx_OPTION.
// Here is a description of all available options :
// 1. Database-options to connect to the database
// - URL_OPTION : a database url of the form jdbc:subprotocol:subname
// - USERNAME_OPTION : the database user on whose behalf the connection is being made
// - PASSWORD_OPTION : the user's password
//
// 2. Connector-option to specify your own JDBCConnectionHandler
// - CONNECTOR_OPTION : a classname which is implementing the JDBCConnectionHandler-interface
// This interface is used to get a customized connection.
// If in addition the database-options are given, these options will be used
// for invocation of the JDBCConnectionHandler-interface to get a connection.
// Else if no database-options are given, the JDBCConnectionHandler-interface is called without these options.
//
// 3. SQL-option to specify a static sql-statement which will be performed with every occuring message-event
// - SQL_OPTION : a sql-statement which will be used to write to the database
// If you give this option, the table-option and columns-option will be ignored !
// Use the variable @MSG@ on that location in the statement, which has to be dynamically replaced by the message.
//
// 4. Table-option to specify one table contained by the database
// - TABLE_OPTION : the table in which the logging will be done
//
// 5. Columns-option to describe the important columns of the table (Not nullable columns are mandatory to describe!)
// - COLUMNS_OPTION : a formatted list of column-descriptions
// Each column description consists of
// - the name of the column (required)
// - a logtype which is a static constant of class LogType (required)
// - and a value which depends by the LogType (optional/required, depending by logtype)
// Here is a description of the available logtypes of class LogType :
// o MSG = a value will be ignored, the column will get the message. (One columns need to be of this type!)
// o STATIC = the value will be filled into the column with every logged message. (Ensure that the type of value can be casted into the sql-type of the column!)
// o ID = value must be a classname, which implements the JDBCIDHandler-interface.
// o TIMESTAMP = a value will be ignored, the column will be filled with a actually timestamp with every logged message.
// o EMPTY = a value will be ignored, the column will be ignored when writing to the database (Ensure to fill not nullable columns by a database trigger!)
// If there are more than one column to describe, the columns must be separated by a TAB-delimiter (' ') !
// The arguments of a column-description must be separated by the delimiter '~' !
// (Example : name1~logtype1~value1 name2~logtype2~value2...)
//
// 6. Layout-options to define the layout of the messages (optional)
// - the layout wont be set by a xxx_OPTION
// Configuration-file : see at the following configuration-file example
// JDBCAppender::setOption() : see at the following code example
// The default is a layout of class org.apache.log4j.PatternLayout with ConversionPattern=%m
//
// 7. Buffer-option to define the size of the message-event-buffer (optional)
// - BUFFER_OPTION : define how many messages will be buffered until they will be updated to the database.
// The default is a update on every message (buffer=1=no buffer).
//
// 8. Commit-option to define a auto-commitment
// - COMMIT_OPTION : define whether updated messages should be committed to the database (Y) or not (N).
// The default is a commit on every buffer-flush.
// Here is a Configuration-file example, which can be used with the PropertyConfigurator :
//
// Declare a appender variable named JDBC
log4j.rootCategory=JDBC
// JDBC is a class of JDBCAppender, which writes messages into a database
log4j.appender.JDBC=JDBCAppender
// 1. Database-options to connect to the database
log4j.appender.JDBC.url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))
log4j.appender.JDBC.username=mex_pr_dev60
log4j.appender.JDBC.password=mex_pr_dev60
// 2. Connector-option to specify your own JDBCConnectionHandler
log4j.appender.JDBC.connector=MyConnectionHandler
// 3. SQL-option to specify a static sql-statement which will be performed with every occuring message-event
log4j.appender.JDBC.sql=INSERT INTO LOGTEST (id, msg, created_on, created_by) VALUES (1, @MSG@, sysdate, 'me')
// 4. Table-option to specify one table contained by the database
log4j.appender.JDBC.table=logtest
// 5. Columns-option to describe the important columns of the table (Not nullable columns are mandatory to describe!)
log4j.appender.JDBC.columns=id_seq~EMPTY id~ID~MyIDHandler msg~MSG created_on~TIMESTAMP created_by~STATIC~Thomas Fenner (t.fenner@klopotek.de)
// 6. Layout-options to define the layout of the messages (optional)
log4j.appender.JDBC.layout=org.apache.log4j.PatternLayout
log4j.appender.JDBC.layout.ConversionPattern=%m
// 7. Buffer-option to define the size of the message-event-buffer (optional)
log4j.appender.JDBC.buffer=1
// 8. Commit-option to define a auto-commitment
log4j.appender.JDBC.commit=Y
*/
// Here is a code example to configure the JDBCAppender with a configuration-file :
import org.apache.log4j.*;
import java.sql.*;
import java.lang.*;
import java.util.*;
public class Log4JTest
{
// Create a category instance for this class
static Category cat = Category.getInstance(Log4JTest.class.getName());
public static void main(String[] args)
{
// Ensure to have all necessary drivers installed !
try
{
Driver d = (Driver)(Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
DriverManager.registerDriver(d);
}
catch(Exception e){}
// Set the priority which messages have to be logged
cat.setPriority(Priority.INFO);
// Configuration with configuration-file
PropertyConfigurator.configure("log4jtestprops.txt");
// These messages with Priority >= setted priority will be logged to the database.
cat.debug("debug"); //this not, because Priority DEBUG is less than INFO
cat.info("info");
cat.error("error");
cat.fatal("fatal");
}
}
// Here is a code example to configure the JDBCAppender without a configuration-file :
/*
import org.apache.log4j.*;
import java.sql.*;
import java.lang.*;
import java.util.*;
public class Log4JTest
{
// Create a category instance for this class
static Category cat = Category.getInstance(Log4JTest.class.getName());
public static void main(String[] args)
{
// A JDBCIDHandler
MyIDHandler idhandler = new MyIDHandler();
// Ensure to have all necessary drivers installed !
try
{
Driver d = (Driver)(Class.forName("oracle.jdbc.driver.OracleDriver").newInstance());
DriverManager.registerDriver(d);
}
catch(Exception e){}
// Set the priority which messages have to be logged
cat.setPriority(Priority.DEBUG);
// Create a new instance of JDBCAppender
JDBCAppender ja = new JDBCAppender();
// Set options with method setOption()
ja.setOption(JDBCAppender.CONNECTOR_OPTION, "MyConnectionHandler");
ja.setOption(JDBCAppender.URL_OPTION, "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))");
ja.setOption(JDBCAppender.USERNAME_OPTION, "mex_pr_dev60");
ja.setOption(JDBCAppender.PASSWORD_OPTION, "mex_pr_dev60");
ja.setOption(JDBCAppender.TABLE_OPTION, "logtest");
// There are two ways to setup the column-descriptions :
// 1. Use the the method setOption(JDBCAppender.COLUMNS_OPTION, column-description)
//ja.setOption(JDBCAppender.COLUMNS_OPTION, "id_seq~EMPTY id~ID~MyIDHandler msg~MSG created_on~TIMESTAMP created_by~STATIC~:-) Thomas Fenner (t.fenner@klopotek.de)");
// 2. Use the better way of coding with method setLogType(String columnname, int LogType.xxx, Object xxx)
ja.setLogType("id_seq", LogType.EMPTY, "");
ja.setLogType("id", LogType.ID, idhandler);
ja.setLogType("msg", LogType.MSG, "");
ja.setLogType("created_on", LogType.TIMESTAMP, "");
ja.setLogType("created_by", LogType.STATIC, "FEN");
// If you just want to perform a static sql-statement, forget about the table- and columns-options,
// and use this one :
//ja.setOption(JDBCAppender.SQL_OPTION, "INSERT INTO LOGTEST (id, msg, created_on, created_by) VALUES (1, @MSG@, sysdate, 'me')");
// other options
//ja.setOption(JDBCAppender.BUFFER_OPTION, "1");
//ja.setOption(JDBCAppender.COMMIT_OPTION, "Y");
// Define a layout
//ja.setLayout(new PatternLayout("%m"));
// Add the appender to a category
cat.addAppender(ja);
// These messages with Priority >= setted priority will be logged to the database.
cat.debug("debug");
cat.info("info");
cat.error("error");
cat.fatal("fatal");
}
}
*/
// Implement a sample JDBCConnectionHandler
class MyConnectionHandler implements JDBCConnectionHandler
{
Connection con = null;
//Default connection
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1521))(ADDRESS=(COMMUNITY=tcp.world)(PROTOCOL=TCP)(Host=LENZI)(Port=1526)))(CONNECT_DATA=(SID=LENZI)))";
String username = "mex_pr_dev60";
String password = "mex_pr_dev60";
public Connection getConnection()
{
return getConnection(url, username, password);
}
public Connection getConnection(String _url, String _username, String _password)
{
try
{
if(con != null && !con.isClosed()) con.close();
con = DriverManager.getConnection(_url, _username, _password);
con.setAutoCommit(false);
}
catch(Exception e){}
return con;
}
}
// Implement a sample JDBCIDHandler
class MyIDHandler implements JDBCIDHandler
{
private static long id = 0;
public synchronized Object getID()
{
return new Long(++id);
}
}