2023年5月12日金曜日

APEX 23.1で追加されたECIDを渡すという設定について

 Oracle APEX 23.1から、アプリケーション定義詳細ECIDを渡すという設定が追加されました。

APEXのページ・リクエスト時に受け取っているHTTPヘッダーECID-Contextを、APEX_WEB_SERVICEを使ってREST APIを呼び出す際に、同じHTTPヘッダーECID-Contextとして設定する、という機能です。


アプリケーションを作成して動作を確認してみます。

最初にAPEXのアプリケーションから呼び出されるRESTサービスを作成します。

モジュールはecid、テンプレートはechoとしています。GETハンドラのソース・タイプPL/SQLソースにはHTTPヘッダーECID-Contextの値を呼び出し元に返すコードを記述します。
begin
    htp.p(owa_util.get_cgi_env('ECID-Context'));
end;
完全なURLをコピーしておきます。


APEXアプリケーションを作成し、アプリケーション定義置換に、置換文字列としてG_ECID_ECHO_URL置換値として上記の完全なURLを設定します。


APEXのページに動的コンテンツのリージョンを作成し、CLOBを返すPL/SQLファンクション本体として、以下のコードを記述します。



以上でAPEXアプケーションを実行すると、以下のような結果が得られます。


構成によっては以下のように、ECIDが表示されない場合もあり得ます。


APEXのページ・プロセスが受け取っているHTTPヘッダーECID-Contextは、リクエストの受け口であるORDSより上位のコンポーネントによって生成され、それをAPEXはORDS経由で受け取っています。そのため、上位のコンポーネントによってHTTPヘッダーECID-Contextが生成されていない場合はECID-Contextは空になります

Oracle HTTP Serverに含まれるモジュールmod_contextおよびWebLogicサーバーにはECIDを生成する機能があります。

スタンドアロンのORDSにECIDを生成する機能を見つけることはできませんでした。また、現時点ではAutonomous Databaseで動作するAPEXは、HTTPヘッダーECID-Contextを受け取っていません。

上位コンポーネントからECID-Contextが渡されていると、ビューAPEX_WORKSPACE_ACTIVITY_LOGの列ECIDに記録されます。

先ほどのページがECIDとして以下の値を返してきたと仮定します。

1.005yrKcsvJOFw0KimTpmWJ0002n900075v;kXjE : APEX page process ECID
1.005yrKcsvJOFw0KimTpmWJ0002n900075v;kXjE : REST servcie ECID

このECIDでのAPEXのページ・プロセスのログを、ビューAPEX_WORKSPACE_ACTIVITY_LOGから取り出すことができます。

select * from apex_workspace_activity_log where ecid = '1.005yrKcsvJOFw0KimTpmWJ0002n900075v;kXjE'


また、このページ・プロセス中に発行されたREST APIをビューAPEX_WEBSERVICE_LOGから取り出すことができます。

select * from apex_webservice_log where ecid = '1.005yrKcsvJOFw0KimTpmWJ0002n900075v;kXjE'


RESTサービス側でHTTPヘッダーECID-Contextの値を取り出し、ログに残すといった処理を含めることで、APEXのページ・プロセスから呼び出されたRESTサービスまで、エンドツーエンドで処理状況を確認することが可能になります。

APEXのページ・プロセスがHTTPヘッダーECID-Contextを受け取っていない、または、自動化などのバックグランド処理からREST APIを呼び出しているためECIDが割り当たらないといった場合は、APEX 23.1で追加されたプロシージャAPEX_WEB_SERVICE.SET_REQUEST_ECID_CONTEXTを呼び出します。このプロシージャは以下のように定義されています。REST APIに割り当てるECIDが生成されますが、このSET_REQUEST_ECID_CONTEXTを呼び出しているプロセス(APEX_WORKSPACE_ACTIVITY_LOGのECID)は更新されません。つまり、このプロシージャを呼び出してECIDを割り当てた場合は、APEX_WORKSPACE_ACTIVITY_LOGとAPEX_WEBSERVICE_LOGをECIDで突合させることはできません。
--======================================================================================
-- Adds an execution context ID (ECID) HTTP request header to g_request_headers. 
-- This will override the application level security setting "Pass ECID".
--
-- PARAMETERS
-- * p_ecid    the identifier for the execution context
--             if set to null, no ECID header will be added
--             if set to AUTO_ECID (the default) an automatic determined 
--             ECID header will be added
--             if set to something else, substrb(p_ecid, 1, 64) will be
--             used as the ECID header
--
-- EXAMPLE 1:
-- On application level sending of ECID header is switched off. By 
-- calling set_request_ecid_context without parameter the following 
-- call to make_rest_request will have an "ECID-Context" request 
-- header with an automatic determined ECID.
--
-- begin
--     apex_web_service.set_request_ecid_context;
-- end;
--
-- EXAMPLE 2:
-- On application level sending of ECID header is switched off. By providing a
-- ECID value the following call to make_rest_request will have an "ECID-Context"
-- request header.
--
-- begin
--     apex_web_service.set_request_ecid_context(
--         p_ecid => 'my-123456' );
-- end;
--
-- EXAMPLE 3:
-- On application level sending of ECID header is switched on. By providing a
-- ECID value of null the following call to make_rest_request will not have an 
-- "ECID-Context" request header.
--
-- begin
--     apex_web_service.set_request_ecid_context(
--         p_ecid => null );
-- end;
--
-- EXAMPLE 4:
-- On application level sending of ECID header is switched on. By providing a
-- ECID value, the following call to make_rest_request will use that instead
-- of an automatic determined ECID.
--
-- begin
--     apex_web_service.set_request_ecid_context(
--         p_ecid => 'my-123456' );
-- end;
--
--======================================================================================
procedure set_request_ecid_context (
    p_ecid in varchar2 default AUTO_ECID);

この設定に関連して、RESTデータ・ソース詳細ECIDを渡すという属性が追加されています。

アプリケーション設定の使用はいいいえのどれかを、RESTデータ・ソースごとに設定することができます。


Oracle APEXとしてのECIDの扱いは以上です。

以下、オラクル・データベースのV$SESSIONの列ECIDとの関連について、確認したことを記述します。

主にWebLogicやFusion Middlewareの説明になりますが、ECIDがV$SESSIONの列ECIDに設定され、V$ACTIVE_SESSION_HISTORYなどから参照できるとの記述を見かけます。

HTTPヘッダーECID-Contextの値をV$SESSIONの列ECIDに設定するには、Oracle REST Data Servicesの属性request.traceHeaderNameECID-Contextを設定する必要があります。デフォルトでは、ECID-Contextヘッダーの値がV$SESSIONのECIDに設定されません。

またOracle CloudのAutonomous DatabaseではV$SESSIONのECIDに値が設定されていますが、これはECID-Contextの値とは別の仕組みにより設定されています。

先ほど作成したRESTサービスのコードを以下に変更します。
declare
    l_ecid varchar2(80);
begin
    select ecid into l_ecid from v$session where sid = sys_context('USERENV','SID');
    htp.p(owa_util.get_cgi_env('ECID-Context') || ':' || l_ecid);
end;
Autonomous Database上で実行する場合は、ビューV$SESSIONのSELECT権限をワークスペース・スキーマに与えておきます。

先ほどのAPEXアプリケーションを実行すると、HTTPヘッダーのECID-Contextの値とV$SESSIONの列ECIDの値が異なることが確認できます。


オラクルのサポートよりノートが出ています。

DBMS_SESSION.SET_CONTEXTを呼び出してHTTPヘッダーのECID-Contextの値をV$SESSIONのECIDに割り当てています。

How to test if ECID is being set in session state in the Database (v$session) (Doc ID 2151716.1)

この中で使用されているコンテキストE2E_CONTEXTは、すでに使用不可になっています。そのため、上記のドキュメントによる手順は無効だと考えた方がよいでしょう。

ORDSの属性request.traceHeaderNameの使用が、サポートされるV$SESSIONの列ECIDにECIDを設定する手順です。

最後に、apex.oracle.comで作成したAPEXアプリケーションとRESTサービスの間でECIDを渡すと、以下のようにECIDが変わります。


これはapex.oracle.comの環境固有の問題で、他の環境では発生していません。

ECIDについての説明は以上になります。