Example 1: Displaying a Supplementary Log Window for Trace Events
This example uses a
custom Java class to display trace events in a separate log window
in the SAS windowing environment, while preserving the contents of
the main Log window.
Step 1: Create a custom
Java class called TraceWindow.
Note that the main class
cannot inherit directly from JFrame. To prevent a HeadlessException,
you must set the java.awt.headless system property before the JFrame
constructor runs.
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import java.awt.Font;
public class TraceWindow
{
JFrame window;
JTextArea console;
String separator;
public TraceWindow(){
System.setProperty( "java.awt.headless", "false" );
separator = System.getProperty("line.separator");
}
public void activate() {
window = new JFrame( "Trace window" );
console = new JTextArea();
console.setFont( new Font("Courier New", Font.PLAIN, 12) );
console.setEditable( false );
JScrollPane scroll = new JScrollPane( console );
window.getContentPane().add(scroll);
window.setSize( 600, 600 );
window.setLocation( 200, 200 );
window.setVisible( true );
}
public void terminate() {
window.dispose();
}
public void append( int level, String logger, String msg ){
window.setVisible( true );
console.append( msg );
console.append( separator );
console.setCaretPosition( console.getText().length() );
}
}
Step 2: Create the following
logging configuration file. The file specifies JavaAppender with the
custom Java class TraceWindow, which is displayed in the preceding
code. Because of the specified threshold, only trace events are sent
to the custom class.
<?xml version="1.0"?>
<logging:configuration xmlns:logging="http://www.sas.com/xml/logging/1.0/"
threshold="trace">
<appender name="java" class="JavaAppender">
<param name="Class" value="TraceWindow"/>
<layout>
<param name="ConversionPattern" value="[%F:%L] %c %6p - %m"/>
</layout>
</appender>
<root>
<level value="info"/>
<appender-ref ref="java"/>
</root>
</logging:configuration>
Example 2: Sending Events to a Database Using a JDBC Driver
This example uses a
custom Java class to connect to a MySQL server via JDBC and write
events to a table.
Step 1: Use the following
MySQL code to create the database and the table:
CREATE DATABASE log;
CREATE TABLE log ( level varchar(10), logger varchar(50), msg varchar(500) );
Step 2: Create the following
Java class, called LogToJDBC. This class uses JDBC to connect to the
MySQL server and writes events to the table.
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
class LogToJDBC {
String driver;
String url;
String tablename;
String username;
String password;
long rowsetsize;
long eventCount;
Connection connection;
PreparedStatement stmt;
public LogToJDBC() {
/*-------------------------------------------------------------+
| Nothing to do in the constructor. |
+-------------------------------------------------------------*/
}
/*-----------------------------------------------------------------+
| Appender API |
+-----------------------------------------------------------------*/
public void setOption( String name, Object value ) {
if( name.equalsIgnoreCase( "driver" ) ) {
driver = value.toString();
} else if( name.equalsIgnoreCase( "url" ) ) {
url = value.toString();
} else if( name.equalsIgnoreCase( "tablename" ) ) {
tablename= value.toString();
} else if( name.equalsIgnoreCase( "username" ) ) {
username = value.toString();
} else if( name.equalsIgnoreCase( "password" ) ) {
password = value.toString();
} else if( name.equalsIgnoreCase( "rowsetsize" ) ) {
rowsetsize = Long.valueOf(value.toString());
}
}
public void activate() throws Exception {
/*-------------------------------------------------------------+
| Set up all of our JDBC objects and set any properties we |
| cached from setOption. |
+-------------------------------------------------------------*/
Class.forName( driver );
connection = DriverManager.getConnection( url, username,
password );
connection.setAutoCommit( false );
stmt = connection.prepareStatement( "insert into " + tablename +
" (level, logger, msg ) values (?, ?, ?)" );
}
public void append( int level, String logger, String msg ) throws Exception {
/*-------------------------------------------------------------+
| Set the columns of our statement and if we have batched |
| enough rows then commit them to the data base. |
+-------------------------------------------------------------*/
stmt.setString( 1, new Integer(level).toString() );
stmt.setString( 2, logger );
stmt.setString( 3, msg );
stmt.addBatch();
eventCount++;
if( eventCount >= rowsetsize )
{
stmt.executeBatch();
connection.commit();
eventCount = 0L;
}
}
public void destroy() throws Exception {
/*-------------------------------------------------------------+
| Send any batched events to the server. |
+-------------------------------------------------------------*/
if( eventCount > 0 )
{
stmt.executeBatch();
connection.commit();
eventCount = 0L;
}
/*-------------------------------------------------------------+
| Clean up our objects if we have any. |
+-------------------------------------------------------------*/
if( stmt != null )
stmt.close();
if( connection != null )
connection.close();
}
}
Step 3: Create the following
logging configuration file. This file specifies JavaAppender with
the custom Java class LogToJDBC, which is displayed in the preceding
code. The Driver, URL, TableName, UserName, Password, and RowSetSize
parameters are passed to LogToJDBC, which uses them to connect to
the server and to write to the table.
<?xml version="1.0" encoding="UTF-8" ?>
<logging:configuration xmlns:logging="http://www.sas.com/xml/logging/1.0/">
<appender name="java" class="JavaAppender">
<param name="classpath"
value="mysql-connector-java-commercial-5.0.8-bin.jar"/>
<param name="class" value="LogToJDBC"/>
<param name="Driver" value="com.mysql.jdbc.Driver"/>
<param name="URL" value="jdbc:mysql://mysql.example.com:3306/log"/>
<param name="TableName" value="log"/>
<param name="UserName" value="myusername"/>
<param name="Password" value="mypassword"/>
<param name="RowSetSize" value="1000" />
<param name="MaxBufferedEvents" value="2000" />
<layout>
<param name="conversionpattern" value="%sn %d %c %p %m"/>
</layout>
</appender>
<root>
<level value="info" />
<appender-ref ref="java" />
</root>
</logging:configuration>
Example 3: Sending Events to log4j Appenders
This example uses a
custom Java class to invoke a log4j configuration. The example uses
org.apache.log4j.net.SocketServer to listen for events, which are
then sent to the log4j ConsoleAppender. By following these steps,
you can send events to any log4j appender.
Step 1: Create a custom
Java class called SendToLog4j that sends events from SAS to log4j:
import org.apache.log4j.*;
public class SendToLog4j
{
public SendToLog4j(){
PropertyConfigurator.configure(System.getProperty("log4j.configuration"));
}
public void append( int level, String logger, String msg ){
Logger l = Logger.getLogger( logger );
switch( level ) {
case 0:
case 1:
case 2:
l.log( Level.TRACE, msg );
break;
case 3:
l.log( Level.DEBUG, msg );
break;
default:
case 4:
l.log( Level.INFO, msg );
break;
case 5:
l.log( Level.WARN, msg );
break;
case 6:
l.log( Level.ERROR, msg );
break;
case 7:
l.log( Level.FATAL, msg );
break;
}
}
}
Step 2: Create a SAS
logging configuration file called socket.xml. In the file, specify
JavaAppender with the custom Java class SendToLog4j.
<?xml version="1.0"?>
<logging:configuration xmlns:logging="http://www.sas.com/xml/logging/1.0/"
threshold="trace">
<appender name="java" class="JavaAppender">
<param name="class" value="SendToLog4j"/>
<layout>
<param name="ConversionPattern" value="%d - %S{hostname} - %S{pid}
- %c - %m"/>
</layout>
</appender>
<root>
<level value="info"/>
<appender-ref ref="java"/>
</root>
</logging:configuration>
Step 3: Create a client-side
log4j configuration file called client.properties. In the file, specify
the use of SocketAppender to listen for events.
log4j.rootLogger=DEBUG,A2
log4j.appender.A2=org.apache.log4j.net.SocketAppender
log4j.appender.A2.Port=55555
log4j.appender.A2.RemoteHost=localhost
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
Step 4: Create a server-side
log4j configuration file called server.properties. In the file, specify
the use of ConsoleAppender. (Any log4j appender could be specified.)
log4j.rootLogger=DEBUG,A2
log4j.appender.A2=org.apache.log4j.net.SocketAppender
log4j.appender.A2.Port=55555
log4j.appender.A2.RemoteHost=localhost
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
Step 5: Use the following
command to start the socket server. The command specifies the server.properties
log4j configuration file.
java –classpath log4j.jar org.apache.log4j.net.SocketServer 55555
server.properties
Step 6: Specify the
following options when you start SAS. The first option specifies the
socket.xml logging configuration file, and the second option passes
the client.properties log4j configuration file to the SAS Java environment.
-logconfigloc socket.xml
-jreoptions '(-Dlog4j.configuration=client.properties)'