ナビゲーションをスキップ

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 の詳細については、「メッセージの配信とフィルタ処理の概要」を参照してください。

図 5-1 ハンドラのサブスクライブ

ハンドラのサブスクライブ


 

 


ハンドラの作成とサブスクライブ : 主な手順

作成し、Logger オブジェクトをサブスクライブさせたハンドラは、その Logger のレベルとフィルタ基準を満たすすべてのメッセージを受信します。ハンドラでは、Logger がパブリッシュする特定のメッセージだけに応答するように追加のレベルとフィルタ基準を指定することもできます。

ハンドラを作成してサブスクライブさせるには、次の手順に従います。

  1. 以下の最小限のインポート文が含まれるハンドラ クラスを作成します。
  2. 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;

  3. ハンドラ クラスで、java.util.logging.Handler を拡張します。
  4. ハンドラ クラスで、Handler.publish(LogRecord record) メソッドを実装します。
  5. このメソッドは次のように機能します。

    1. 受信した LogRecord オブジェクトを WLLogRecord オブジェクトとしてキャストします。
    2. ハンドラで設定されているフィルタを適用します。
    3. WLLogRecord オブジェクトがフィルタの基準を満たしている場合は、WLLogRecord のメソッドを使用してメッセージからデータを取得します。
    4. 必要に応じて、メッセージのデータを 1 つまたは複数のリソースに書き込みます。
  6. ハンドラ クラスで、Handler.flush メソッドと Handler.close メソッドを実装します。
  7. リソースと連係して機能するハンドラはすべて、flush メソッド (バッファされた出力をフラッシュするため) および close メソッド (開いているリソースを閉じるため) を実装する必要があります。

    Logger オブジェクトが閉じると、すべてのハンドラで Handler.close メソッドが呼び出されます。close メソッドは、flush メソッドを呼び出してからそれ独自のロジックを実行します。

  8. Handler オブジェクトが受信するメッセージのタイプを指定するフィルタ クラスを作成します。詳細については、「Logger と Handler のフィルタの設定」を参照してください。
  9. Logger オブジェクトが動作している JVM のクラスパスにハンドラ オブジェクトとフィルタ オブジェクトを配置します。
  10. 以下の LoggingHelper メソッドのいずれかを呼び出すクラスを作成します。
  11. このクラスで、Logger.addHandler(Handler myHandler) メソッドを呼び出します。次に、Logger.setFilter(Filter myFilter) メソッドを呼び出します。

 


例 : サーバ JVM でのメッセージのサブスクライブ

この例では、JDBC データ ソースに接続し、メッセージをデータベース テーブルに挿入する SQL 文を発行するハンドラを作成します。この例では、以下のクラスを実装します。

例 : Handler クラスの実装

コード リスト 5-1Handler クラス例は、次のようにしてデータベースにメッセージを書き込みます:

  1. java.util.logging.Handler を拡張します。
  2. javax.naming.InitialContext オブジェクトを作成し、Context.lookup メソッドを呼び出して myPoolDataSource というデータ ソースをルックアップします。
  3. javax.sql.DataSource.getConnection メソッドを呼び出して、データ ソースとの接続を確立します。
  4. setErrorManager メソッドを実装します。このメソッドは、このハンドラの java.util.logging.ErrorManager オブジェクトを作成します。
  5. このハンドラでエラーが生じると、エラー マネージャの error メソッドが呼び出されます。この例の error メソッドは次のように機能します。

    1. エラー メッセージを標準エラーに出力します。
    2. LoggingHelper.getServerLogger().removeHandler(MyJDBCHandler.this) を呼び出してハンドラを無効にします。
    3. 注意 : 独立したクラス ファイルで ErrorManager クラスを定義する代わりに、この例では ErrorManager が無名内部クラスとして内包されています。

    エラー マネージャの詳細については、Sun API のドキュメントで java.util.logging.ErrorManager を参照してください。

  6. Handler.publish(LogRecord record) メソッドを実装します。このメソッドは、次のことを実行します。
    1. 受信した各 LogRecord オブジェクトを WLLogRecord オブジェクトとしてキャストします。
    2. isLoggable メソッドを呼び出して、ハンドラに設定されているフィルタを適用します。isLoggable メソッドは、このハンドラ クラスの最後に定義されています。
    3. WLLogRecord のメソッドを使用して、メッセージからデータを取得します。
    4. WLLogRecord メソッドの詳細については、WLLogRecord の「Javadoc」を参照してください。

    5. メッセージのデータを SQL prepareStatement としてフォーマットし、データベースの更新を実行します。
    6. 例で使用されるテーブルのスキーマは次のとおりです。

      表 5-1 Handler 例のデータベース テーブルのスキーマ

      名前

      Null 可/不可

      MSGID


      CHAR(25)

      LOGLEVEL


      CHAR(25)

      SUBSYSTEM


      CHAR(50)

      MESSAGE


      CHAR(1024)


       
    7. flush メソッドを呼び出して、接続をフラッシュします。
  7. Handler.close メソッドを実装して、データ ソースとの接続を閉じます。
  8. Logger オブジェクトが閉じると、Handler.close メソッドが呼び出されます。このメソッドは、Handler.flush メソッドを呼び出してからそれ独自のロジックを実行します。

コード リスト 5-1例 : Handler クラスの実装

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);
      }
   }
}

例 : Logger クラスのサブスクライブ

コード リスト 5-2 のクラス例は次のように機能します:

  1. LoggingHelper.getServerLogger メソッドを呼び出して、Logger オブジェクトを取得します。
  2. Logger.addHandler(Handler myHandler) メソッドを呼び出します。
  3. Logger.getHandlers メソッドを呼び出して、Logger オブジェクトのすべてのハンドラを取得します。
  4. myHandler が見つかるまで配列を検索します。
  5. Handler.setFilter(Filter myFilter) メソッドを呼び出します。

サーバが起動するたびにハンドラとフィルタがサーバの 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();
    }
}

 


JDK 1.4 ハンドラと JMX リスナの比較

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 の通知とモニタの使い方」を参照してください。

コード リスト 5-3JMX リスナの登録

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 を作成
    
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);
    }
}

 

ページの先頭 前 次