Re: code to load tracefile into CLOB?
Date: Tue, 23 Aug 2011 23:40:49 -0400
Message-ID: <CADo_RaPEx059wQa7ULuYpsDxy-5gZSg6N9cbxbRrSs9zmzVJHg_at_mail.gmail.com>
Brilliant. Thanks Jeremy. This is one of my favorite topics, but I was on vacation last week and totally missed this. What makes MR Trace so great is that it is so easy to use developers have no excuse not to see how their code is being executed. Pete Finnigan has a valid point about security, but I think this kind of access should always be kept far, far away from PROD and this kind of thinking should be mandatory on DEV databases.
I used to work in a PL/SQL Developer shop and had considered building my own plugin (Allround Automations plugin documentation is pretty good), but I no longer work in that shop.
I have some PL/SQL code that I borrorred liberally from:
http://dioncho.wordpress.com/2009/03/19/another-way-to-use-trace-file/ http://www.idevelopment.info/data/Oracle/DBA_tips/LOBs/LOBS_30.shtml http://www.oracle-base.com/articles/10g/Scheduler10g.php
The code below contains two functions that return the CLOB Jermemy originally asked about. One that returns the raw trace contents and the other a tkprof'd version. I like CLOBs because most IDEs can handle them very well. They either allow you to export them to a local file or you can copy and paste somewhere else.
Note this was tested on an 11.2 database on Windows.
select value from v$parameter where name = 'user_dump_dest'; create or replace directory user_dump_dir as '&user_dump_directory';
define schema_owner=andy
grant select on v_$process to &schema_owner; grant select on v_$session to &schema_owner; grant select on v_$parameter to &schema_owner;grant create external job to &schema_owner; grant read,write on directory user_dump_dir to &schema_owner
create or replace function &schema_owner..gettraceclob(s_id number default
userenv('sid')) return clob
is
l_filename varchar2(2000); l_bfile BFILE; l_clob CLOB; l_lang_ctx NUMBER := DBMS_LOB.default_lang_ctx; l_charset_id NUMBER := 0; l_src_offset NUMBER := 1; l_dst_offset NUMBER := 1; l_warning NUMBER;
begin
select i.value||'_ora_'||p.spid||'.trc' into l_filename from v$process p, v$session s,
(select value from v$parameter where name = 'instance_name') i where p.addr = s.paddr
and s.sid = s_id;
/*
for 11g:
select substr(value,instr(value,'\',-1)+1,1000) into l_filename from v$diag_info where name = 'Default Trace File';
*/
l_bfile:= BFILENAME('USER_DUMP_DIR', l_filename);
l_clob:='init';
DBMS_LOB.fileopen(l_bfile, DBMS_LOB.file_readonly);
DBMS_LOB.loadclobfromfile (l_clob, l_bfile,DBMS_LOB.getlength (l_bfile),
l_src_offset, l_dst_offset,l_charset_id,l_lang_ctx,l_warning);
DBMS_LOB.fileclose(l_bfile);
return l_clob;
end;
/
begin
DBMS_SCHEDULER.create_program (
program_name => 'tkprof_program', program_type => 'EXECUTABLE', program_action => '?/bin/tkprof', number_of_arguments => 2, enabled => FALSE, comments => 'Runs tkprof with two arguments. Argument 1:trace file to be tkprof''d. Argument 2: output file'); DBMS_SCHEDULER.define_program_argument (
program_name => 'tkprof_program', argument_name => 'tracefile', argument_position => 1, argument_type => 'VARCHAR2', default_value => 'init'); DBMS_SCHEDULER.define_program_argument ( program_name => 'tkprof_program', argument_name => 'outputfile', argument_position => 2, argument_type => 'VARCHAR2', default_value => 'init');
DBMS_SCHEDULER.enable (name => 'tkprof_program'); DBMS_SCHEDULER.create_job (
job_name => 'run_tkprof', program_name => 'tkprof_program', enabled => TRUE, comments => 'Job defined by existing schedule and inlineprogram.');
end;
/
create or replace function &schema_owner..gettkprofclob(s_id number default
userenv('sid')) return clob
is
l_filename varchar2(2000); l_bfile BFILE; l_clob CLOB; l_lang_ctx NUMBER := DBMS_LOB.default_lang_ctx; l_charset_id NUMBER := 0; l_src_offset NUMBER := 1; l_dst_offset NUMBER := 1; l_warning NUMBER;
l_file_separator varchar2(1):='\'; -- change to '/' on unix/linux
function getdirpath return varchar2
is
l_dirpath varchar2(2000);
begin
select DIRECTORY_PATH into l_dirpath from all_directories where
directory_name = 'USER_DUMP_DIR';
return l_dirpath;
end;
function getfilebase(p_filename varchar2) return varchar2
is
begin
return substr(p_filename,0,instr(p_filename,'.',-1)-1);
end;
begin
select i.value||'_ora_'||p.spid||'.trc' into l_filename from v$process p, v$session s,
(select value from v$parameter where name = 'instance_name') i where p.addr = s.paddr
and s.sid = s_id;
/*
for 11g:
select substr(value,instr(value,'\',-1)+1,1000) into l_filename from v$diag_info where name = 'Default Trace File';
*/
execute immediate ' begin DBMS_SCHEDULER.define_program_argument ( '||
'program_name => ''tkprof_program'','||
'argument_name => ''tracefile'','||
'argument_position => 1,'||
'argument_type => ''VARCHAR2'','||
'default_value => '''||getdirpath
||l_file_separator||l_filename||'''); end;';
execute immediate ' begin DBMS_SCHEDULER.define_program_argument ( '||
'program_name => ''tkprof_program'','||
'argument_name => ''outputfile'','||
'argument_position => 2,'||
'argument_type => ''VARCHAR2'','||
'default_value =>
'''||getdirpath||l_file_separator||getfilebase(l_filename)||'.tkp''); end;';
execute immediate ' begin dbms_scheduler.run_job(''RUN_TKPROF'');end;';
--l_bfile:= BFILENAME('USER_DUMP_DIR', l_filename);
l_bfile:= BFILENAME('USER_DUMP_DIR', getfilebase(l_filename)||'.tkp');
l_clob:='init';
DBMS_LOB.fileopen(l_bfile, DBMS_LOB.file_readonly);
DBMS_LOB.loadclobfromfile (l_clob, l_bfile,DBMS_LOB.getlength (l_bfile),
l_src_offset, l_dst_offset,l_charset_id,l_lang_ctx,l_warning);
DBMS_LOB.fileclose(l_bfile);
return l_clob;
end;
/
A little demo:
SQL> alter session set events '10046 trace name context forever, level 8';
Session altered.
SQL> select count(*) from scott.emp;
COUNT(*)
14
SQL> alter session set events '10046 trace name context off';
Session altered.
SQL> var c clob
SQL> exec :c:=gettkprofclob
PL/SQL procedure successfully completed.
SQL> set long 1000
SQL> print c
C
TKPROF: Release 11.2.0.1.0 - Development on Tue Aug 23 23:16:22 2011 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
Trace file:
c:\app\oracle\diag\rdbms\sandboxdb1\sandboxdb1\trace\sandboxdb1_ora_ 6240.trc
Sort options: default
...
SQL ID: abj9tmfcs15bm
Plan Hash: 2937609675
select count(*)
from
scott.emp
call count cpu elapsed disk query current
rows
------- ------ -------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 1 0 1
------- ------ -------- ---------- ---------- ---------- ----------
total 4 0.00 0.00 0 1 0 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 112
Rows Row Source Operation
------- --------------------------------------------------- 1 SORT AGGREGATE (cr=1 pr=0 pw=0 time=0 us) 14 INDEX FULL SCAN PK_EMP (cr=1 pr=0 pw=0 time=0 us cost=1 size=0card=14
)(object id 73197)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait TotalWaited
- Waited ----------
SQL*Net message to client 2 0.00 0.00 SQL*Net message from client 2 12.24 12.25
...
On Fri, Aug 19, 2011 at 12:33 PM, Jeremy Schneider < jeremy.schneider_at_ardentperf.com> wrote:
> Here you go. I coded the whole thing up and published it... if anyone > can't use current plugins on the market but they need to give developers > access to 10046 trace data without server access, here's a simple block > of code that will do the trick. > > http://www.ardentperf.com/2011/08/19/developer-access-to-10046-trace-files/ > > -Jeremy >
-- http://www.freelists.org/webpage/oracle-lReceived on Tue Aug 23 2011 - 22:40:49 CDT