2021年11月22日月曜日

Oracle APEX 21.2新機能(17) - 追加されたAPEX_DEBUGのAPI

 オラクルが公開しているOracle APEX 21.2の新機能のページ追加機能のセクションにて、新規PL/SQL APIとして以下の2つが追加されたことが紹介されています。

apex_debug.get_page_view_id

apex_debug.get_last_message_id

以下の説明がされています。

LOGGERによって作成されたメッセージをAPEXデバッグ・セッションにリンクし、LOGGERメッセージを正しい順序で表示するためのapex_debug.get_page_view_idおよびapex_debug.get_last_message_idが追加されました。

LOGGERを知らない方には理解が難しい気がします。LOGGERとは、オープンソースで提供されているPL/SQLのロギング・パッケージです。

http://www.oraopensource.com/logger

Oracle APEXはパッケージAPEX_DEBUGおよびビューAPEX_DEBUG_MESSAGESとして、ログの出力と参照を行う機能を提供しています。APEX_DEBUG.INFO、WARN、ERRORといったプロシージャを呼び出して記録したメッセージはビューAPEX_DEBUG_MESSAGESより参照することができます。LOGGERのような別の仕組みで記録されたログより、APEX側のログを参照するため、今回追加されたAPIを使用します。

これらのAPIの使い方を、実装を行なって確認してみます。

ページのヘッダーの前に、エラー・メッセージを出力する以下のプロセスを作成します。
begin
    apex_debug.enable;
    apex_debug.error('この位置でエラーが発生しました。');
    apex_debug.disable;
end;

出力されたメッセージをビューAPEX_DEBUG_MESSAGESより探します。以下のSQLによる対話モード・レポートを作成します。識別タイトルAPEX_DEBUG確認とします。

select * from apex_debug_messages
where workspace_id = :WORKSPACE_ID
  and application_id = :APP_ID
  and page_id = :APP_PAGE_ID
  and session_id = :APP_SESSION

ビューAPEX_DEBUG_MESSAGESの絞り込みに、WORKSPACE_ID、APPLICATION_ID、PAGE_ID、SESSION_IDを使っています。しかし、これだけでは書き込んだメッセージを一意に特定することができません。

以下のように同一セッションでページが表示された回数分、メッセージが書き込まれます。


新しく追加されたAPIを使うと、いつ書き込まれたメッセージなのか特定できます。先ほど作成したヘッダーの前のプロセスのコードを以下に変更します。

Page View Idとしてapex_debug.get_page_view_idに一致する行、および、列Idとしてapex_debug.get_last_message_idに一致する行だけを表示するよう、フィルタをかけています。(実際に利用する局面では、IdまたはPage View Idのどちらかがあれば十分でしょう)。
declare
    l_region_id apex_application_page_ir.region_id%type;
begin
    apex_debug.enable;
    apex_debug.error('この位置でエラーが発生しました。');
    apex_debug.disable;
    -- 対話モード・レポートにフィルタを設定する。
    select region_id into l_region_id from apex_application_page_ir
    where application_id = :APP_ID and page_id = :APP_PAGE_ID;
    -- and region_name = 'APEX_DEBUG確認';
    -- 対話モード・レポートのリセット
    apex_ir.reset_report(
        p_page_id => :APP_PAGE_ID
        , p_region_id => l_region_id
        , p_report_id => null
    );
    apex_ir.add_filter(
        p_page_id => :APP_PAGE_ID
        , p_region_id => l_region_id
        , p_report_column => 'PAGE_VIEW_ID'
        , p_filter_value => apex_debug.get_page_view_id
        , p_operator_abbr => 'EQ'
        , p_report_id => null
    );
    apex_ir.add_filter(
        p_page_id => :APP_PAGE_ID
        , p_region_id => l_region_id
        , p_report_column => 'ID'
        , p_filter_value => apex_debug.get_last_message_id
        , p_operator_abbr => 'EQ'
        , p_report_id => null
    );
end;
レポートに表示されるメッセージが、このページを表示したときに出力された1行のログだけになります。


ヘッダーの前のページ・プロセスで設定した対話モード・レポートのフィルタを有効にするには、Attributes遅延ロードONにする必要があります。


出力するメッセージにメッセージID(apex_debug.get_last_message_idの値)、またはページ・ビューID(apex_debug.get_page_view_idの値)を含むことにより、出力されたメッセージからビューAPEX_DEBUG_MESSAGES内のメッセージを特定することができます。

ページ・アイテムP1_MESSAGEを作成し、追加のメッセージを出力します。
declare
    l_region_id apex_application_page_ir.region_id%type;
begin
    apex_debug.enable;
    apex_debug.error('この位置でエラーが発生しました。');
    :P1_MESSAGE := 'この位置でエラーが発生しました。 Id = ' || apex_debug.get_last_message_id || 
        ', Page View Id = ' || apex_debug.get_page_view_id;
    apex_debug.disable;
end;

メッセージにIdおよびPage View Idが含まれているため、そのどちらかを使ってメッセージを特定することができます。


他のロギング・システム(例えばLOGGER)に書き込むメッセージに、これらの識別子を含めることにより、容易にAPEXのログとの突き合わせができるようになります。

簡単なアプリケーションですが、以下にエクスポートを置きました。
https://github.com/ujnak/apexapps/blob/master/exports/new212-apex-debug-new-api.sql

Oracle APEXのアプリケーション作成の参考になれば幸いです。