Das Common Logging Package bietet eine Möglichkeit zur Ausgabe von Log-Informationen aus PL/Sql in autonomen Transaktionen. Es unterstützt Loglevels Debug, Info und Error.
Das Script erstellt die Notwendigen Objekte für ein Package pkg_common_logging. Hiermit können Loginformationen aus PL/SQL-Programmen in einer Tabelle gespeichert weden. Die Loglevel (Debug, Info, Error) werden durch Sessionvariable gesetzt und können somit nach Bedarf angepasst werden.
CREATE TABLE COMLOG_APP_LOG ( SESSION_ID NUMBER, LOG_LEVEL VARCHAR2(32), ACTION_ORDER_ID NUMBER, SESSION_MODULE VARCHAR2(64), SESSION_ACTION VARCHAR2(128), SESSION_CLIENT_INFO VARCHAR2(512), ERROR_NO NUMBER, ERROR_TEXT VARCHAR2(512), NO_OF_RECORDS NUMBER, SESSION_START DATE, LOG_DT_START DATE, LOG_DT_END DATE, ACTION_SEC NUMBER, SESSION_SEC NUMBER ) LOGGING NOCOMPRESS NOCACHE NOPARALLEL MONITORING / CREATE SEQUENCE S_COMLOG_APP_LOG_ID START WITH 1 MAXVALUE 999999999999999999999999999 MINVALUE 1 NOCYCLE CACHE 200 NOORDER / CREATE OR REPLACE package pkg_common_logging as -- pkg_common_logging -- 2009; Ingo Voland -- -- Package enthaelt Funktionalitaeten fuer common logging -- benoetigt: Tabelle COMLOG_APP_LOG -- Sequence s_COMLOG_APP_LOG_id -- -- -- -- folgende loglevel koennen definiert werden: debug / info / error -- es werden nur logeintraege geschrieben, wenn der in der -- session ein höherer oder gleicher loglevel gesetzte ist als der -- für den logeintrag definierte. Somit kann eine 'debug' funktionalitaet -- implementiert werden, ohne das diese debug Eintraege permanent die Logtabelle -- fuellen -- -- matrix: logeintrage werden geschrieben wenn: -- -- Log Eintrag Loglevel Session Log Level -- error info debug -- error x x x -- info x x -- debug x -- -- der default loglevel ist 'ERROR' -- set_debug constant pls_integer := 3; set_info constant pls_integer := 2; set_error constant pls_integer := 1; -- -- diese prozeduren setzen den loglevel fuer eine session -- der wert bleibt aktiv solange die session offen ist -- oder bis ein andere wert gesetzt wird -- -- der loglevel kann in der session variable oder fix im package gesezt werden. -- vorzugsweise soll der loglevel aber in der session gesetzt werden -- um hardcodierte loglevel zu verhindern -- procedure set_log_level(loglevel in pls_integer default set_error); procedure set_log_level(loglevel in COMLOG_APP_LOG.log_level%type default 'ERROR'); -- -- diese prozeduren setzen die loginformationen fuer eine session -- der wert bleibt aktiv bis: -- * ein neuer wert gesetzte wird -- * ein reset_log aufruf erfolgt -- -- die gesetzte werte werden ebenfalls in v$session angezeigt -- -- Das setzten eines wertes schreibt noch keine Eintraege in die Logtabellen -- mit hilfe der gesezten werte fuer Modul und Action sind die Logeintraege -- zu spaeteren Zeiten sortier- und gruppierbar -- -- -- Modul: ist typischer weise der Name der ausführenden Procedure -- Action: ist ein Subprozess in einer Procedure, z.b. 'fuellen der tabelle xyz' -- client_info: ist eine beliebige information für die aktuelle ausgeführte operatiom -- procedure set_module(module_name varchar2, action_name varchar2); procedure set_action(action_name varchar2); procedure set_client_info(client_info varchar2); -- init_log: immer der erste Aufruf, das Loging wird initialisert -- der eintrag wird immer im loglevel 'error' geschrieben -- procedure init_log(module_name varchar2, action_name varchar2,client_info varchar2); -- write_log -- setzt 'cleint_info' und schreibt einen eintrag mit dem angegebenen loglevel. -- wird kein loglevel angegeben wird der eintrag unter dem aktuell in der session -- gesetzten loglevel geschrieben, default ist 'error' -- zu beachten ist, das die logeintraege nur geschrieben werden wenn -- der in der procedure angegebenen loglevel kleiner oder gleich -- dem in der session gesetzten loglevel ist procedure write_log(client_info varchar2, loglevel pls_integer default null ); -- write_log_ins -- diese procedure schreibt die anzahl der in der vorherigen aktion durch insert eingefügten records -- in die logtabelle. Fuer den Loglevel gilt das unter 'write_log' gesagte -- -- beispiel: -- insert into TEST values (1,'testlog'); -- pkg_common_logging.write_log_ins(loglevel => pkg_common_logging.set_info); -- -- oder ohne spezifizierten loglevel, dann wird der session-loglevel genommen -- und ein insert in die logtabelle findet immer statt -- pkg_common_logging.write_log_ins; -- procedure write_log_ins(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null); -- write_log_del -- diese procedure schreibt die anzahl der in der vorherigen aktion durch delete geloeschten records -- in die logtabelle. Fuer den Loglevel gilt das unter 'write_log' gesagte -- -- beispiel: -- delete from test; -- pkg_common_logging.write_log_del(loglevel => pkg_common_logging.set_info); -- -- -- oder ohne spezifizierten loglevel, dann wird der session-loglevel genommen -- und ein insert in die logtabelle findet immer statt -- pkg_common_logging.write_log_del; -- procedure write_log_del(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null); -- write_log_upd -- diese procedure schreibt die anzahl der in der vorherigen aktion durch insert eingefügten records -- in die logtabelle. Fuer den Loglevel gilt das unter 'write_log' gesagte -- -- beispiel: -- update test set id = 3; -- pkg_common_logging.write_log_upd(loglevel => pkg_common_logging.set_info); -- -- oder ohne spezifizierten loglevel, dann wird der session-loglevel genommen -- und ein insert in die logtabelle findet immer statt -- pkg_common_logging.write_log_upd; -- procedure write_log_upd(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null); -- write_log_sel -- diese procedure schreibt die anzahl der in der vorherigen aktion durch insert eingefügten records -- in die logtabelle. Fuer den Loglevel gilt das unter 'write_log' gesagte -- -- beispiel: -- select count(*) into v_num from dual; -- pkg_common_logging.write_log_sel(loglevel => pkg_common_logging.set_info); -- -- oder ohne spezifizierten loglevel, dann wird der session-loglevel genommen -- und ein insert in die logtabelle findet immer statt -- pkg_common_logging.write_log_sel; -- procedure write_log_sel(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null); -- write_log_error -- diese procedure schreibt die fehlernumer und fehlercode in die logtabelle , -- wenn in einer procedure eine exception aufgetreten ist. der Loglevel ist immer 'ERROR' -- diese Procedure muss mit in das excaption handling der aufrufenden instanz eingebunden sein -- -- beispiel: -- -- declare -- v_num number; -- begin -- select 1 / 0 ito v_num from dual; -- -- exception -- when others then -- pkg_common_logging.write_log_error; -- raise; -- end; -- -- procedure write_log_error(client_info varchar2 default null, error_no varchar2 default SQLCODE, error_info varchar2 default SQLERRM); -- -- diese procedure wird üblicher weise am ende der abarbeitung einer procedure -- oder eines subprozesses aufgerufen und erhoeht die SESSION_ID . -- weiterhin werden alle anderen zaehler und timestamps -- neu initialisiert. -- procedure reset_log; -- -- interne vars -- r_comlog_app_log comlog_app_log%rowtype; gv_log_level pls_integer; function show_version return varchar2; end pkg_common_logging; / CREATE OR REPLACE package body pkg_common_logging as c_version constant varchar2(32) := '01.00 / 20090802'; c_curr_ACTION_ORDER_ID COMLOG_APP_LOG.ACTION_ORDER_ID%type ; type r_log_level is table of COMLOG_APP_LOG.LOG_LEVEL%type ; l_log_level r_log_level := r_log_level('ERROR','INFO','DEBUG'); procedure reset_init is begin select s_COMLOG_APP_LOG_id.nextval into pkg_common_logging.r_comlog_app_log.SESSION_ID from dual; pkg_common_logging.r_comlog_app_log.SESSION_START := sysdate; pkg_common_logging.r_comlog_app_log.LOG_DT_START := sysdate; c_curr_ACTION_ORDER_ID := 0; pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := 0; end reset_init; procedure write(write_loglevel in pls_integer default set_error) is PRAGMA AUTONOMOUS_TRANSACTION; begin pkg_common_logging.r_comlog_app_log.LOG_DT_END := sysdate; pkg_common_logging.r_comlog_app_log.ACTION_SEC := round((pkg_common_logging.r_comlog_app_log.LOG_DT_END - pkg_common_logging.r_comlog_app_log.LOG_DT_START) *24*3600); pkg_common_logging.r_comlog_app_log.SESSION_SEC := round((pkg_common_logging.r_comlog_app_log.LOG_DT_END - pkg_common_logging.r_comlog_app_log.SESSION_START) *24*3600); if write_loglevel <= pkg_common_logging.gv_log_level then pkg_common_logging.r_comlog_app_log.LOG_LEVEL := l_log_level(write_loglevel); c_curr_ACTION_ORDER_ID := nvl( c_curr_ACTION_ORDER_ID,0) + 1; pkg_common_logging.r_comlog_app_log.ACTION_ORDER_ID := c_curr_ACTION_ORDER_ID; insert into COMLOG_APP_LOG values pkg_common_logging.r_comlog_app_log; end if; pkg_common_logging.r_comlog_app_log.LOG_DT_START := sysdate; pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := 0; commit; end write; procedure set_log_level(loglevel in pls_integer default set_error) is begin pkg_common_logging.gv_log_level := loglevel; if nvl(pkg_common_logging.gv_log_level,0) not in (set_debug,set_info,set_error) then pkg_common_logging.gv_log_level := set_error; end if; pkg_common_logging.r_comlog_app_log.LOG_LEVEL := l_log_level(pkg_common_logging.gv_log_level); end set_log_level; procedure set_log_level(loglevel in COMLOG_APP_LOG.log_level%type default 'ERROR') is begin if upper(loglevel) in ('DEBUG','INFO','ERROR') then pkg_common_logging.r_comlog_app_log.LOG_LEVEL := loglevel; else pkg_common_logging.r_comlog_app_log.LOG_LEVEL := 'ERROR' ; end if; pkg_common_logging.gv_log_level := case upper(loglevel) when 'DEBUG' then set_debug when 'INFO' then set_info when 'ERROR' then set_error else set_error end ; end set_log_level; procedure set_module(module_name varchar2, action_name varchar2) is begin dbms_application_info.set_module(substr(module_name,1,32) ,substr(action_name,1,32)); pkg_common_logging.r_comlog_app_log.SESSION_MODULE := substr(module_name,1,64); pkg_common_logging.r_comlog_app_log.SESSION_ACTION := substr(action_name,1,128); end set_module; procedure set_action(action_name varchar2) is begin dbms_application_info.set_action(substr(action_name,1,32) ); pkg_common_logging.r_comlog_app_log.SESSION_ACTION := substr(action_name,1,128); end set_action; procedure set_client_info(client_info varchar2) is begin dbms_application_info.set_client_info( substr(client_info,1,32) ); pkg_common_logging.r_comlog_app_log.SESSION_CLIENT_INFO := substr(client_info,1,512); end set_client_info; procedure init_log(module_name varchar2, action_name varchar2,client_info varchar2 ) is begin reset_init; pkg_common_logging.r_comlog_app_log.SESSION_START := sysdate; pkg_common_logging.r_comlog_app_log.LOG_DT_START := sysdate; set_module(module_name,action_name); set_client_info(client_info); pkg_common_logging.r_comlog_app_log.SESSION_CLIENT_INFO := 'INIT: '||client_info; write(set_error); end init_log; procedure write_log(client_info varchar2, loglevel pls_integer default null ) is begin set_client_info(client_info); write(nvl(loglevel,pkg_common_logging.gv_log_level)); end write_log; procedure write_log_ins(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null) is begin pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := NO_OF_RECORDS; set_client_info('INS: '||to_char(NO_OF_RECORDS)||' Records'); write(nvl(loglevel,pkg_common_logging.gv_log_level)); end write_log_ins; procedure write_log_sel(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null) is begin pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := NO_OF_RECORDS; set_client_info('SEL: '||to_char(NO_OF_RECORDS)||' Records'); write(nvl(loglevel,pkg_common_logging.gv_log_level)); end write_log_sel; procedure write_log_del(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null) is begin set_client_info('DEL: '||to_char(NO_OF_RECORDS)||' Records'); pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := NO_OF_RECORDS; write(nvl(loglevel,pkg_common_logging.gv_log_level)); end write_log_del; procedure write_log_upd(NO_OF_RECORDS in COMLOG_APP_LOG.NO_OF_RECORDS%type default sql%rowcount, loglevel pls_integer default null) is begin pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := NO_OF_RECORDS; set_client_info('UPD: '||to_char(NO_OF_RECORDS)||' Records'); write(nvl(loglevel,pkg_common_logging.gv_log_level)); end write_log_upd; procedure write_log_error(client_info varchar2 default null, error_no varchar2 default SQLCODE, error_info varchar2 default SQLERRM ) is begin if client_info is null then set_client_info('ERR: '||pkg_common_logging.r_comlog_app_log.SESSION_CLIENT_INFO ); else set_client_info(client_info); end if; pkg_common_logging.r_comlog_app_log.ERROR_NO := error_no; pkg_common_logging.r_comlog_app_log.ERROR_TEXT := SUBSTR (error_info, 1, 512); write(set_error); pkg_common_logging.r_comlog_app_log.ERROR_NO := null; pkg_common_logging.r_comlog_app_log.ERROR_TEXT := null; end write_log_error; procedure reset_log is begin -- write ende pkg_common_logging.r_comlog_app_log.LOG_DT_END := sysdate; set_client_info('End'); set_action('End'); write; -- reset reset_init; end reset_log; procedure reset_log_soft is begin if pkg_common_logging.r_comlog_app_log.SESSION_ID is null then select s_COMLOG_APP_LOG_id.nextval into pkg_common_logging.r_comlog_app_log.SESSION_ID from dual; end if; if pkg_common_logging.r_comlog_app_log.SESSION_START is null then pkg_common_logging.r_comlog_app_log.SESSION_START := sysdate; end if; c_curr_ACTION_ORDER_ID := 0; pkg_common_logging.r_comlog_app_log.NO_OF_RECORDS := 0; end reset_log_soft; function show_version return varchar2 is begin return 'pkg_common_logging version is: '||c_version; end show_version; begin -- check for session_id reset_log_soft; set_log_level(pkg_common_logging.gv_log_level); c_curr_ACTION_ORDER_ID := 0; end pkg_common_logging; /