2012-04-19 10 views
2

で呼び出し元のパッケージ/プロシージャを取得:私は次のインサートを持つテーブルへの書き込みのOracle 10gのログイン手順を書いているのOracle

INSERT INTO EXEC_LOG VALUES (
    (SELECT SYS_CONTEXT('USERENV','SESSIONID') sessionid FROM dual), 
    strPackage, strProcedure, strEventType, strEventLevel, SYSDATE, strMessage 
); 

この手順は、複数の異なるパッケージ/手順で再利用されていますが、今のように、プログラマはパッケージ/プロシージャ名をロギングプロシージャ(strPackagestrProcedure)に渡さなければなりません。

このプロシージャが呼び出されたパッケージ/プロシージャの種類を教えてくれるv $ビューまたはその他のものがある場合は、プログラマがstrPackagestrProcedureを渡す必要はありません。

例:このパッケージから

BEGIN 
    log_test.testproc1; 
    log_test.testproc2; 
END; 

::私は、これら2つのプロシージャを呼び出す場合

CREATE OR REPLACE PACKAGE BODY log_test IS 
    PROCEDURE TestProc1 IS 
    BEGIN 
     write_exec_log(...);  
    END TestProc1; 
    PROCEDURE TestProc2 IS 
    BEGIN 
     write_exec_log(...);  
    END TestProc2; 
END log_test; 

私はlog_test/TestProc1log_test/TestProc2を評価できるようにしたいでしょうインサイドからwrite_exec_logメソッド。

答えて

1
+1

へのOracleのバージョンで動作しますプロシージャ名。この質問に例を追加しました。呼び出しスタックには 'log_test'が含まれていますが、' TestProc1'は含まれていません。 – Paul

+0

パッケージから回線番号を取得できます。それは十分に近いですか? –

+0

これはperformaceメトリックにも使用したいので、 'write_exec_log'が呼び出されたときにどのプロシージャが実行されているのか知りたいです。 – Paul

3

は、Oracle 12cがスタートしますが、パッケージUTL_CALL_STACK(http://docs.oracle.com/database/121/ARPLS/u_call_stack.htm)に建てられた使用することができます。

ショートたとえば、あなたが呼び出し元の手順でちょうど興味を持っている場合: DBMS_OUTPUT.PUT_LINE(UTL_Call_Stack.Concatenate_Subprogram(UTL_Call_Stack.Subprogram(2)));

または完全なコールスタック印刷するには:あなたのパッケージと

FOR j IN REVERSE 1..UTL_Call_Stack.Dynamic_Depth() LOOP 
    DBMS_OUTPUT.PUT_LINE(UTL_Call_Stack.Concatenate_Subprogram(UTL_Call_Stack.Subprogram(j))); 
END LOOP; 

例:

CREATE OR REPLACE PACKAGE log_test IS 
PROCEDURE write_exec_log(msg VARCHAR2); 
PROCEDURE TestProc1; 
PROCEDURE TestProc2; 
PROCEDURE TestProc3; 
END log_test; 
/

CREATE OR REPLACE PACKAGE BODY log_test IS 
PROCEDURE write_exec_log(msg VARCHAR2) IS 
    BEGIN 
    DBMS_OUTPUT.PUT_LINE(msg); 
    DBMS_OUTPUT.PUT_LINE('-- '); 
    DBMS_OUTPUT.PUT_LINE('calling procedure/function: ' 
         ||UTL_Call_Stack.Concatenate_Subprogram(
                   UTL_Call_Stack.Subprogram(2) 
                  ) 
         ); 
    DBMS_OUTPUT.PUT_LINE('-- '); 
    DBMS_OUTPUT.PUT_LINE('Call Stack'); 
    FOR j IN REVERSE 1..UTL_Call_Stack.Dynamic_Depth() LOOP 
    DBMS_OUTPUT.PUT_LINE(UTL_Call_Stack.Concatenate_Subprogram(
                   UTL_Call_Stack.Subprogram(j) 
                  ) 
         ); 
    END LOOP; 
    END write_exec_log; 
PROCEDURE TestProc1 IS 
    BEGIN 
    write_exec_log('msg TestProc1');  
    END TestProc1; 
PROCEDURE TestProc2 IS 
    BEGIN 
    write_exec_log('msg TestProc2');  
    END TestProc2; 
PROCEDURE TestProc3 IS 
    BEGIN 
    TestProc2; 
    END TestProc3; 
END log_test; 
/

exec log_test.TestProc1 
exec log_test.TestProc2 
exec log_test.TestProc3 

を(申し訳ありませんが、sqlfiddle、いいえ12cは書面の時点で利用可能です)

0

Hereは、Oracle 9用のutl_call_stackの実装(バックポート)です。また、Oracle 10 and 11用です。

p_stackパッケージと)別の解決策:GWu's example

dbms_output.put_line(p_stack.getConcatenatedSubprograms(p_stack.whoCalledMe)); 

、それは出力になります。

LOG_TEST.TESTPROC1 
LOG_TEST.TESTPROC2 
LOG_TEST.TESTPROC2 

これらは、最後の呼び出しです。それとも、あなたは完全なスタックを必要とする場合:

dbms_output.put_line(p_stack.getCallStack); 
dbms_output.put_line(''); 

これでしょう出力:

493: YOUR_SCHEMA.PACKAGE BODY P_STACK.FUNCTION GETCALLSTACK.FUNCTION GETCALLSTACK 
4: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE WRITE_EXEC_LOG 
9: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC1 
2: YOUR_SCHEMA.ANONYMOUS BLOCK 

493: YOUR_SCHEMA.PACKAGE BODY P_STACK.FUNCTION GETCALLSTACK.FUNCTION GETCALLSTACK 
4: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE WRITE_EXEC_LOG 
13: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC2 
3: YOUR_SCHEMA.ANONYMOUS BLOCK 

493: YOUR_SCHEMA.PACKAGE BODY P_STACK.FUNCTION GETCALLSTACK.FUNCTION GETCALLSTACK 
4: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE WRITE_EXEC_LOG 
13: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC2 
17: YOUR_SCHEMA.PACKAGE BODY LOG_TEST.PROCEDURE TESTPROC3 
4: YOUR_SCHEMA.ANONYMOUS BLOCK 

それは、これは私にパッケージ名を取得しませんが、9から12

関連する問題