![]() ![]() ![]() ![]() |
WebLogic Server メッセージ カタログおよび NonCatalogLogger
でメッセージが生成されるとき、それらのメッセージは java.util.logging.Logger
オブジェクトに配信されます。Logger
オブジェクトは、メッセージを説明する WLLogRecord
オブジェクトを割り当て、Logger
をサブスクライブしているすべてのメッセージ ハンドラにその WLLogRecord
をパブリッシュします。
以下の節では、メッセージ ハンドラの作成とサブスクライブについて説明します。
WebLogic Server のロガーとハンドラの詳細については、「ロガーとハンドラの役割」を参照してください。
WebLogic Server は、ログ メッセージを受信して出力するメッセージ ハンドラをインスタンス化し、サブスクライブさせます。独自のメッセージ ハンドラを作成して、WebLogic Server Logger
オブジェクトをサブスクライブするようにもできます (図 5-1 を参照)。
たとえば、アプリケーションがクライアント JVM で動作しており、そのアプリケーションがアプリケーションの生成するメッセージをリスンするようにする場合は、ハンドラを作成してクライアント JVM の Logger
オブジェクトをサブスクライブさせることができます。アプリケーションが特定サブシステムの障害を知らせるログ メッセージを受信した場合、そのアプリケーションは以下のようなアクションを実行できます。
注意 : | ユーザ独自のメッセージ ハンドラを作成する場合は、サーバの初期化が完了して実行状態になる前に、WebLogic Server プロセスで実行されるカスタム コードを実行しないように注意します。場合によっては、初期化中のサーバ サービスにカスタム コードが干渉する場合があります。たとえば、IIOP サーバ サービスの初期化の前に PortableRemoteObject を使用する発信 RMI 呼び出しを行うカスタム ログ ハンドラは、サーバの起動が失敗する原因になる場合があります。 |
作成し、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;
java.util.logging.Handler
を拡張します。Handler.publish(LogRecord record)
メソッドを実装します。Handler.flush
メソッドと Handler.close
メソッドを実装します。
リソースと連係して機能するハンドラはすべて、flush
メソッド (バッファされた出力をフラッシュするため) および close
メソッド (開いているリソースを閉じるため) を実装する必要があります。
親 Logger
オブジェクトが閉じると、すべてのハンドラで Handler.close
メソッドが呼び出されます。close メソッドは、flush
メソッドを呼び出してからそれ独自のロジックを実行します。
Handler
オブジェクトが受信するメッセージのタイプを指定するフィルタ クラスを作成します。「ロガーとハンドラのフィルタの設定」を参照してください。getClientLogger
(現在のコンテキストがクライアント JVM である場合)。getServerLogger
(現在のコンテキストがサーバ JVM であり、サーバの Logger
オブジェクトにハンドラをアタッチする必要がある場合)。getDomainLogger
(現在のコンテキストが管理サーバであり、ドメインの Logger
オブジェクトにハンドラをアタッチする必要がある場合)。
LoggingHelper.getDomainLogger()
は、ドメイン ログを管理する Logger
オブジェクトを取得します。カスタム ハンドラにこのロガーをサブスクライブさせて、単一の場所にある全サーバからのログ メッセージを処理できます。
Logger.addHandler(Handler myHandler)
メソッドを呼び出します。 Logger.setFilter(Filter myFilter)
メソッドを呼び出してフィルタを設定します。
この例では、JDBC データ ソースに接続し、メッセージをデータベース テーブルに挿入する SQL 文を発行するハンドラを作成します。この例では、以下のクラスを実装します。
Handler
クラス。「例 : ハンドラ クラスの実装」を参照してください。Filter
クラス。「ロガーとハンドラのフィルタの設定」を参照してください。Logger
クラスをサブスクライブさせるクラス。「例 : ロガー クラスのサブスクライブ」を参照してください。
コード リスト 5-1 の Handler
クラスの例では、次のようにしてデータベースにメッセージを書き込みます。
java.util.logging.Handler
を拡張します。javax.naming.InitialContext
オブジェクトを作成し、Context.lookup
メソッドを呼び出して myPoolDataSource
というデータ ソースをルックアップします。javax.sql.DataSource.getConnection
メソッドを呼び出して、データ ソースとの接続を確立します。setErrorManager
メソッドを実装します。このメソッドは、このハンドラの java.util.logging.ErrorManager
オブジェクトを作成します。
このハンドラでエラーが生じると、エラー マネージャの error
メソッドが呼び出されます。この例の error
メソッドは次のように機能します。
LoggingHelper.getServerLogger().removeHandler(MyJDBCHandler.this)
を呼び出してハンドラを無効にします。注意 : | 独立したクラス ファイルで ErrorManager クラスを定義する代わりに、この例では ErrorManager が無名内部クラスとして内包されています。 |
エラー マネージャの詳細については、Sun API のドキュメントで java.util.logging.ErrorManager
を参照してください。
Handler.publish(LogRecord record)
メソッドを実装します。このメソッドは、次のことを実行します。LogRecord
オブジェクトを WLLogRecord
オブジェクトとしてキャストします。 isLoggable
メソッドを呼び出して、ハンドラに設定されているフィルタを適用します。isLoggable
メソッドは、このハンドラ クラスの最後に定義されています。WLLogRecord
のメソッドを使用して、メッセージからデータを取得します。
WLLogRecord
メソッドの詳細については、WLLogRecord
の Javadoc を参照してください。
prepareStatement
としてフォーマットし、データベースの更新を実行します。flush
メソッドを呼び出して、接続をフラッシュします。Handler.close
メソッドを実装して、データ ソースとの接続を閉じます。
親 Logger
オブジェクトが閉じると、Handler.close
メソッドが呼び出されます。このメソッドは、Handler.flush
メソッドを呼び出してからそれ独自のロジックを実行します。
コード リスト 5-1 に、この節で説明した手順を示します。
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;
private PreparedStatement stmt = null;
public MyJDBCHandler() throws NamingException, SQLException {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("myPoolDataSource");
con = ds.getConnection();
PreparedStatement stmt = con.prepareStatement
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 {
("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
クラスの例では、以下のことを行います。
サーバが起動するたびにハンドラとフィルタがサーバの Logger
オブジェクトをサブスクライブするようにする場合は、このクラスを WebLogic Server 起動クラスとしてデプロイします。起動クラスについては、Administration Console オンライン ヘルプの「カスタム クラスを使用したサーバのコンフィグレーション」を参照してください。
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();
}
}
コード リスト 5-3 の Appender
クラスの例では、JDBC データ ソースに接続し、メッセージをデータベース テーブルに挿入する SQL 文を発行します。
AppenderSkelton
を拡張します。javax.naming.InitialContext
オブジェクトを作成し、Context.lookup
メソッドを呼び出して MyDataSource
というデータ ソースをルックアップします。javax.sql.DataSource.getConnection
メソッドを呼び出して、データ ソースとの接続を確立します。append(LoggingEvent event)
メソッドを実装します。このメソッドは、次のことを実行します。LoggingEvent
オブジェクトを WLLog4jLogEvent
としてキャストします。WLLog4jLogEvent
のメソッドを使用して、メッセージからデータを取得します。
WLLog4jLogEvent
メソッドの詳細については、WLLog4jLogEvent
の Javadoc を参照してください。
prepareStatement
を作成し、ロギング イベントを受け取るたびにデータベースを更新します。close
メソッドを実装して、データ ソースとの接続を閉じます。
コード リスト 5-3 に、この節で説明した手順を示します。
package weblogic.logging.examples;
import java.util.Enumeration;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import weblogic.logging.LoggerNotAvailableException;
import weblogic.logging.NonCatalogLogger;
import weblogic.logging.Severities;
import weblogic.logging.log4j.AppenderNames;
import weblogic.logging.log4j.Log4jLoggingHelper;
import weblogic.logging.log4j.WLLog4jLevel;
import weblogic.logging.log4j.WLLog4jLogEvent;
import org.apache.log4j.jdbc.JDBCAppender;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.InitialContext;
import weblogic.logging.log4j.WLLog4jLogEvent;
import weblogic.logging.Severities;
/**
* このクラスは、ログ イベントに対するサーバ ロガーのリスナとして
* Log4j アペンダを設定する
*/
public class Log4jAppenderExampleStartup {
public static void main(String[] args) {
try {
System.out.println("Invoked the appender example startup class");
Logger serverLogger = Log4jLoggingHelper.getLog4jServerLogger();
// JDBC アペンダをコンフィグレーションする
MyJDBCAppender jdbcAppender = new MyJDBCAppender();
// ここで JDBC アペンダをサーバ ロガーに追加する
serverLogger.addAppender(jdbcAppender);
// ここでフィルタをテストする
NonCatalogLogger nc = new NonCatalogLogger("MyAppenderTest");
nc.info("Test INFO message");
nc.warning("Test WARNING message");
} catch(Exception ex) {
System.err.println("Init failure " + ex.getMessage());
ex.printStackTrace();
}
}
private static class MyJDBCAppender extends AppenderSkeleton {
private Connection connection;
private java.sql.PreparedStatement stmt;
public MyJDBCAppender() throws javax.naming.NamingException, SQLException {
InitialContext ctx = new InitialContext();
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup ("MyDataSource");
connection = ds.getConnection();
// テーブル スキーマ作成 SQL コマンド
// Create table SERVER_LOG (server_name char(30),msg_id char(20), severity_level char(20),logger_name char(100),message varchar(2048),timestamp long);
stmt = connection.prepareStatement("INSERT INTO SERVER_LOG VALUES (?, ?, ?, ?, ?, ?)");
stmt.setEscapeProcessing(true);
connection.setAutoCommit(true);
}
// 実行メソッドをオーバーライドする
public void append(LoggingEvent event) {
WLLog4jLogEvent wlsEvent = (WLLog4jLogEvent) event;
try {
stmt.setString(1, wlsEvent.getServerName());
stmt.setString(2, wlsEvent.getId());
stmt.setString(3, Severities.severityNumToString(wlsEvent.getSeverity()));
stmt.setString(4, wlsEvent.getSubsystem());
stmt.setString(5, wlsEvent.getMessage().toString());
stmt.setLong(6, wlsEvent.getTimestamp());
stmt.executeUpdate();
} catch (SQLException e) {
System.err.println(e.toString());
}
}
public boolean requiresLayout() {
return false;
}
public void close() {
try {
stmt.close();
connection.close();
} catch(SQLException sqlex) {
System.err.println("Error closing JDBC appender");
sqlex.printStackTrace();
}
}
}
}
WebLogic Server 8.1 より前のリリースで、WebLogic ロギング サービスからメッセージを受信するには、Java Management Extensions (JMX) リスナを作成して、それを LogBroadcasterRuntimeMBean
に登録する方法しかありませんでした。WebLogic Server 8.1 では、Java ロギング ハンドラを使用してログ メッセージを受信 (サブスクライブ) することもできます。
Java ロギング ハンドラでも JMX リスナでも同様の結果が得られますが、Java ロギング API には Formatter
クラスがあり、Handler
オブジェクトはこのクラスを使用して受信したメッセージをフォーマットできます。JMX では、メッセージをフォーマットするこのような API は提供されません。フォーマッタの詳細については、Sun API のドキュメントの Formatter
(http://java.sun.com/j2se/1.5.0/docs/api/java/util/logging/Formatter.html) を参照してください。
さらに、Java ロギング Handler
API は JMX API よりも使いやすく、過程が直接的です。たとえば、次のコードは Java ロギング Logger
オブジェクトを取得し、ハンドラにそのオブジェクトをサブスクライブさせます。
Logger logger = LoggingHelper.getServerLogger();
Handler h = null;
h = new MyJDBCHandler();
logger.addHandler(h)
JMX リスナを登録して同様の結果を得るには、コード リスト 5-4 のようなコードを使用する必要があります。コードで MBeanHome
インタフェース、RemoteMBeanServer
インタフェース、および LogBroadcasterRuntimeMBean
をルックアップし、それからリスナを登録します。
ローカル マシンのログ メッセージのサブスクライブには Java ロギング ハンドラ、リモート マシンからのログ メッセージの受信には JMX リスナが適しています。すでにモニタに JMX を使用しており、ログ メッセージのフォーマットを変更したりログ メッセージを別の出力に転送したりせずに単純にリスンする場合は、JMX リスナを使用します。それ以外の場合は、Java ロギング ハンドラを使用します。
MBeanHome home = null;
RemoteMBeanServer rmbs = null;
//ドメイン変数
String url = "t3://localhost:7001";
String serverName = "Server1";
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 を
//作成
WebLogicObjectName logBCOname = new
WebLogicObjectName("TheLogBroadcaster",
"LogBroadcasterRuntime", domainName, serverName);
//MBean の名前とリスナ クラスを MBeanServer の
//addNotificationListener メソッドに渡す
rmbs.addNotificationListener(logBCOname, listener, filter, null);
} catch(Exception e) {
System.out.println("Exception: " + e);
}
}
![]() ![]() ![]() |