WebLogic Server ロギング サービスの使い方
WebLogic Server メッセージ カタログおよび NonCatalogLogger
でメッセージが生成されるとき、それらのメッセージは java.util.logging.Logger
オブジェクトに配信されます。Logger
オブジェクトは、メッセージを説明する WLLogRecord
オブジェクトを割り当て、Logger
をサブスクライブしているすべてのメッセージ ハンドラにその WLLogRecord
をパブリッシュします。
WebLogic Server は、ログ メッセージを受信して出力するメッセージ ハンドラをインスタンス化し、サブスクライブさせます。独自のメッセージ ハンドラを作成して、WebLogic Server Logger
オブジェクトをサブスクライブするようにもできます (図 5-1 を参照)。
たとえば、アプリケーションがクライアント JVM で動作しており、そのアプリケーションがアプリケーションの生成するメッセージをリスンするようにしたい場合は、ハンドラを作成し、それにクライアント JVM の Logger
オブジェクトをサブスクライブさせることができます。アプリケーションが特定サブシステムの障害を知らせるログ メッセージを受信した場合、そのアプリケーションは以下のようなアクションを実行できます。
以下の節では、メッセージ ハンドラの作成とサブスクライブについて説明されています。
WebLogic Server の Logger と Handler の詳細については、「メッセージの配信とフィルタ処理の概要」を参照してください。
作成し、Logger
オブジェクトをサブスクライブさせたハンドラは、その Logger のレベルとフィルタ基準を満たすすべてのメッセージを受信します。ハンドラでは、Logger がパブリッシュする特定のメッセージだけに応答するように追加のレベルとフィルタ基準を指定することもできます。
ハンドラを作成してサブスクライブさせるには、次の手順に従います。
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.ErrorManager;
import weblogic.logging.WLLogRecord;
import weblogic.logging.WLLevel;
import weblogic.logging.WLErrorManager;
import weblogic.logging.LoggingHelper;
リソースと連係して機能するハンドラはすべて、flush
メソッド (バッファされた出力をフラッシュするため) および close
メソッド (開いているリソースを閉じるため) を実装する必要があります。
親 Logger
オブジェクトが閉じると、すべてのハンドラで Handler.close
メソッドが呼び出されます。close メソッドは、flush
メソッドを呼び出してからそれ独自のロジックを実行します。
Handler
オブジェクトが受信するメッセージのタイプを指定するフィルタ クラスを作成します。詳細については、「Logger と Handler のフィルタの設定」を参照してください。
この例では、JDBC データ ソースに接続し、メッセージをデータベース テーブルに挿入する SQL 文を発行するハンドラを作成します。この例では、以下のクラスを実装します。
Handler
クラス。「例 : Handler クラスの実装」を参照してください。Filter
クラス。「Logger と Handler のフィルタの設定」を参照してください。Logger
クラスをサブスクライブさせるクラス。「例 : Logger クラスのサブスクライブ」を参照してください。 コード リスト 5-1 の Handler
クラス例は、次のようにしてデータベースにメッセージを書き込みます:
javax.naming.InitialContext
オブジェクトを作成し、Context.lookup
メソッドを呼び出して myPoolDataSource
というデータ ソースをルックアップします。エラー マネージャの詳細については、Sun API のドキュメントで java.util.logging.ErrorManager
を参照してください。
WLLogRecord
メソッドの詳細については、WLLogRecord
の「Javadoc」を参照してください。
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Filter;
import java.util.logging.ErrorManager;
import weblogic.logging.WLLogRecord;
import weblogic.logging.WLLevel;
import weblogic.logging.WLErrorManager;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import weblogic.logging.LoggingHelper;
public class MyJDBCHandler extends Handler {
private Connection con = null;
public MyJDBCHandler() throws NamingException, SQLException {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("myPoolDataSource");
con = ds.getConnection();
setErrorManager(new ErrorManager() {
public void error(String msg, Exception ex, int code) {
System.err.println("Error reported by MyJDBCHandler "
+ msg + ex.getMessage());
//このハンドラのインスタンスをすべて削除
LoggingHelper.getServerLogger().removeHandler(
MyJDBCHandler.this);
}
});
}
public void publish(LogRecord record) {
WLLogRecord rec = (WLLogRecord)record;
if (!isLoggable(rec)) return;
try {
PreparedStatement stmt = con.prepareStatement(
"INSERT INTO myserverLog VALUES (?, ?, ?,?)");
stmt.setEscapeProcessing(true);
stmt.setString(1, rec.getId());
stmt.setString(2, rec.getLevel().getLocalizedName());
stmt.setString(3, rec.getLoggerName());
stmt.setString(4, rec.getMessage());
stmt.executeUpdate();
flush();
} catch(SQLException sqex) {
reportError("Error publihsing to SQL", sqex,
ErrorManager.WRITE_FAILURE);
}
}
public void flush() {
try {
con.commit();
} catch(SQLException sqex) {
reportError("Error flushing connection of MyJDBCHandler",
sqex, ErrorManager.FLUSH_FAILURE);
}
}
public boolean isLoggable(LogRecord record) {
Filter filter = getFilter();
if (filter != null) {
return filter.isLoggable(record);
} else {
return true;
}
}
public void close() {
try {
con.close();
} catch(SQLException sqex) {
reportError("Error closing connection of MyJDBCHandler",
sqex, ErrorManager.CLOSE_FAILURE);
}
}
}
コード リスト 5-2 のクラス例は次のように機能します:
サーバが起動するたびにハンドラとフィルタがサーバの Logger
オブジェクトをサブスクライブするようにしたい場合は、このクラスを WebLogic Server 起動クラスとしてデプロイします。起動クラスの詳細については、Administration Console オンライン ヘルプの「起動クラスと停止クラス」を参照してください。
コード リスト 5-2例 : Logger クラスのサブスクライブ
import java.util.logging.Logger;
import java.util.logging.Handler;
import java.util.logging.Filter;
import java.util.logging.LogRecord;
import weblogic.logging.LoggingHelper;
import weblogic.logging.FileStreamHandler;
import weblogic.logging.WLLogRecord;
import weblogic.logging.WLLevel;
import java.rmi.RemoteException;
import weblogic.jndi.Environment;
import javax.naming.Context;
public class LogConfigImpl {
public void configureLogger() throws RemoteException {
Logger logger = LoggingHelper.getServerLogger();
try {
Handler h = null;
h = new MyJDBCHandler();
logger.addHandler(h);
h.setFilter(new MyFilter());
} catch(Exception nmex) {
System.err.println("Error adding MyJDBCHandler to logger "
+ nmex.getMessage());
logger.removeHandler(h);
}
}
public static void main(String[] argv) throws Exception {
LogConfigImpl impl = new LogConfigImpl();
impl.configureLogger();
}
}
WebLogic Server 8.1 より前のリリースでは、WebLogic ロギング サービスからメッセージを受信する唯一の方法は、Java Management Extensions (JMX) リスナを作成して、それを LogBroadcasterRuntimeMBean
に登録することでした。WebLogic Server 8.1 では、JDK 1.4 ハンドラを使用してログ メッセージを受信 (サブスクライブ) できます。
JDK 1.4 ハンドラでも JMX リスナでも同様の結果が得られますが、JDK 1.4 API には Formatter
クラスがあり、Handler
オブジェクトはこのクラスを使用して受信したメッセージをフォーマットできます。JMX では、メッセージをフォーマットするこのような API は提供されません。フォーマッタの詳細については、Sun API のドキュメントで、Formatter
(http://java.sun.com/j2se/1.4/docs/api/java/util/logging/Formatter.html) を参照してください。
さらに、JDK 1.4 Handler
API は JMX API よりも使いやすく、過程が直接的です。たとえば、次のコードは JDK 1.4 Logger
オブジェクトを取得し、ハンドラにそのオブジェクトをサブスクライブさせます。
Logger logger = LoggingHelper.getServerLogger();
Handler h = null;
h = new MyJDBCHandler();
logger.addHandler(h)
JMX リスナを登録して同様の結果を得るには、コード リスト 5-3 のようなコードを使用する必要があります。そのコードは MBeanHome
インタフェース、RemoteMBeanServer
インタフェース、および LogBroadcasterRuntimeMBean
をルックアップして、それからリスナを登録します。
JMX リスナの使い方については、『WebLogic JMX Service プログラマーズ ガイド』の「WebLogic Server MBean の通知とモニタの使い方」を参照してください。
MBeanHome home = null;
RemoteMBeanServer rmbs = null;
//ドメイン変数
String url = "t3://localhost:7001";
String serverName = "Server1";
String domainName= "mydomain"
String username = "weblogic";
String password = "weblogic";
//MBeanHome を使用して MBeanServer を取得
try {
Environment env = new Environment();
env.setProviderUrl(url);
env.setSecurityPrincipal(username);
env.setSecurityCredentials(password);
Context ctx = env.getInitialContext();
//管理 MBeanHome インタフェースを取得
home = (MBeanHome) ctx.lookup(MBeanHome.ADMIN_JNDI_NAME);
System.out.println("Got the Admin MBeanHome: " + home );
rmbs = home.getMBeanServer();
} catch (Exception e) {
System.out.println("Caught exception: " + e);
}
try {
//リスナ クラスをインスタンス化
MyListener listener = new MyListener();
MyFilter filter = new MyFilter();
//サーバのログ ブロードキャスタのWebLogicObjectName logBCOname = new
//WebLogicObjectName を作成
WebLogicObjectName("TheLogBroadcaster",
"LogBroadcasterRuntime", domainName, serverName);
//MBean の名前とリスナ クラスを MBeanServer の
//addNotificationListener メソッドに渡す
rmbs.addNotificationListener(logBCOname, listener, filter, null);
} catch(Exception e) {
System.out.println("Exception: " + e);
}
}