オラクルが公開している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;
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のアプリケーション作成の参考になれば幸いです。
完