[Home] [Help]
PACKAGE BODY: APPS.AP_LOGGING_PKG
Source
1 package body AP_LOGGING_PKG as
2 /* $Header: apdologb.pls 120.3 2004/10/27 23:52:36 pjena noship $ */
3 --
4 -- _______
5 -- | |
6 -- | |
7 -- | |
8 -- _________| |_________
9 -- \ /
10 -- \ AP Debugging/Logging /
11 -- \ thru pipes /
12 -- \ _____ /
13 -- \ | | /
14 -- \ | | /
15 -- \___| |___/
16 -- \ /
17 -- \ BEGIN /
18 -- \ /
19 -- \ /
20 -- \ /
21 -- \ /
22 -- v
23 --
24 --
25 -- Procedures for server side PL/SQL debugging/logging:
26 --
27 -- The following procedures enable logging through the Oracle Piping system
28 -- sending messages to the SGA that can be read by a different session.
29 -- The messages can be automatically indented respecting the nesting level
30 -- of the PL/SQL blocks from within they have been issued.
31 --
32 --
33 /*----------------------------*
34 | Private Objects Definition |
35 *----------------------------*/
36 --
37 function Adjusted_Size (MaxSize IN number)
38 return number
39 is
40 BEGIN
41 -- Opening a pipe with potential size 60% larger than needed avoids
42 -- locking issues in memory:
43 return(round(MaxSize * 1.6));
44 END Adjusted_Size;
45 --
46 --
47 function Build_Stat_String (SizeUsed IN number
48 ,MaxSize IN number
49 )
50 return varchar2
51 is
52 BEGIN
53 if (maxsize > 0) then
54 return (substr(to_char(nvl(SizeUsed,0),'09999'),2)||'/'||
55 substr(to_char(MaxSize,'09999'),2)||'='||
56 substr(to_char(100*nvl(SizeUsed,0)/MaxSize,'099'),2)||'%'
57 );
58 else
59 return ('00000/00000=000%'); -- "Null size" string
60 end if;
61 END Build_Stat_String;
62 --
63 --
64 procedure Send_Message_To_Pipe (PipeName IN varchar2
65 ,Msg IN varchar2
66 ,Result OUT NOCOPY number
67 ,StatString OUT NOCOPY varchar2
68 ,SizeUsed IN OUT NOCOPY number
69 ,LinesEntered IN OUT NOCOPY number
70 )
71 is
72 --
73 -- Sends a message to a named pipe, updating memory usage statistics
74 -- when successfully sent.
75 --
76 ctr number(1) := 2; -- Assumes not enough space in pipe
77 maxsize number(5) := Ap_Logging_Pkg.DBG_Max_Size;
78 oldsizeused number(5) := SizeUsed;
79 oldlinesentered number(5) := LinesEntered;
80 --
81 BEGIN
82 --
83 -- Possible OUT/Success values for Result parameter:
84 -- -1 (unknown error)
85 -- 0 (normal completion)
86 -- 1 (timeout error due to lock on pipe)
87 -- 2 (pipe full)
88 --
89 if (SizeUsed+length(Msg) <= maxsize) then
90 dbms_pipe.pack_message(Msg);
91 ctr := dbms_pipe.send_message(PipeName
92 ,1 /* One second timeout */
93 ,Adjusted_Size(maxsize)
94 );
95 if (ctr = 0) then
96 --
97 SizeUsed := SizeUsed + length(Msg);
98 LinesEntered := LinesEntered + 1;
99 StatString := Build_Stat_String(SizeUsed, maxsize);
100 --
101 end if;
102 --
103 end if;
104 --
105 Result := ctr;
106 --
107 EXCEPTION
108 --
109 -- In case of ANY error, stop the queue and restore settings:
110 when OTHERS then
111 Result := -1; -- Unknown error
112 LinesEntered := oldlinesentered;
113 StatString := Build_Stat_String(oldsizeused
114 ,maxsize
115 );
116 Ap_Logging_Pkg.DBG_Currently_Logging := FALSE;
117 --
118 END Send_Message_To_Pipe;
119 --
120 procedure Pop_One_Level
121 is
122 ctr number := length(Ap_Logging_Pkg.DBG_Debug_Stack);
123 BEGIN
124 if (
125 (Ap_Logging_Pkg.DBG_Message_Level > 0)
126 and
127 (instr(Ap_Logging_Pkg.DBG_Debug_Stack,'+') > 0)
128 ) then
129 while (ctr > 0) loop
130 exit when (substr(Ap_Logging_Pkg.DBG_Debug_Stack, ctr, 1) = '+');
131 ctr := ctr - 1;
132 end loop;
133 Ap_Logging_Pkg.DBG_Debug_Stack := replace(Ap_Logging_Pkg.DBG_Debug_Stack
134 ,substr
135 (Ap_Logging_Pkg.DBG_Debug_Stack
136 ,ctr
137 )
138 ,''
139 );
140 Ap_Logging_Pkg.DBG_Message_Level := Ap_Logging_Pkg.DBG_Message_Level - 1;
141 end if;
142 END Pop_One_Level;
143 --
144 procedure Push_One_Level (P_Message_Location IN varchar2)
145 is
146 BEGIN
147 Ap_Logging_Pkg.DBG_Debug_Stack := Ap_Logging_Pkg.DBG_Debug_Stack||
148 '+'||P_Message_Location;
149 Ap_Logging_Pkg.DBG_Message_Level := Ap_Logging_Pkg.DBG_Message_Level + 1;
150 END Push_One_Level;
151 --
152 function Get_Location_Level (P_Message_Location IN varchar2)
153 return number
154 is
155 ctr number;
156 lvl number := Ap_Logging_Pkg.DBG_Message_Level;
157 stk varchar2(5000) := Ap_Logging_Pkg.DBG_Debug_Stack;
158 BEGIN
159 if (
160 (lvl > 0)
161 and
162 (instr(stk, '+') > 0)
163 and
164 (instr(stk, P_Message_Location) > 0)
165 ) then
166 while (lvl > 0) loop
167 ctr := length(stk);
168 while (
169 (ctr > 0)
170 and
171 (instr(stk, '+') > 0)
172 ) loop
173 exit when (substr(stk, ctr, 1) = '+');
174 ctr := ctr - 1;
175 end loop;
176 stk := replace(stk, substr(stk,ctr), '');
177 exit when (instr(nvl(stk,'+'), P_Message_Location) = 0);
178 lvl := lvl - 1;
179 end loop;
180 else
181 lvl := 0;
182 end if;
183 --
184 return(lvl);
185 --
186 END Get_Location_Level;
187 --
188 --
189 /*---------------------------*
190 | Public Objects Definition |
191 *---------------------------*/
192 --
193 procedure Ap_Begin_Log (P_Calling_Module IN varchar2
194 ,P_Max_Size IN number
195 )
196 is
197 /*
198 Copyright (c) 1995 by Oracle Corporation
199
200 NAME
201 Ap_Begin_Log
202 DESCRIPTION
203 This opens a piping area in memory for debugging/logging purposes
204 NOTES
205 Procedure to be conditionally executed from the application firing
206 the PL/SQL object
207 HISTORY (YY/MM/DD)
208 atassoni.it 95/07/05 Creation
209 */
210 --
211 session_name varchar2(30) := dbms_pipe.unique_session_name;
212 header_message varchar2(2000) := '>> Opened '||session_name||
213 ' for '||P_Calling_Module||
214 ' on '||
215 to_char(sysdate,'Mon dd hh24:mi:ss')||
216 ' - size: '||to_char(P_Max_Size);
217 --
218 BEGIN
219 --
220 -- Start clearing old messages under the same pipe, if present
221 dbms_pipe.purge(session_name);
222 --
223 -- Set the logging packaged variables:
224 Ap_Logging_Pkg.DBG_Pipe_Name := session_name;
225 Ap_Logging_Pkg.DBG_Max_Size := P_Max_Size;
226 Ap_Logging_Pkg.DBG_Used_Size := 0;
227 Ap_Logging_Pkg.DBG_Lines_Entered := 0;
228 Ap_Logging_Pkg.DBG_Message_Level := 0;
229 Ap_Logging_Pkg.DBG_Debug_Stack := null;
230 Ap_Logging_Pkg.DBG_Currently_Logging := TRUE;
231 --
232 -- Initiates the pipe inserting the header as first message:
233 Send_Message_To_Pipe (session_name
234 ,header_message
235 ,Ap_Logging_Pkg.DBG_Log_Return_Code
236 ,Ap_Logging_Pkg.DBG_Stat
237 ,Ap_Logging_Pkg.DBG_Used_Size
238 ,Ap_Logging_Pkg.DBG_Lines_Entered
239 );
240 --
241 EXCEPTION
242 --
243 when OTHERS then
244 Ap_Logging_Pkg.DBG_Pipe_Name := session_name;
245 Ap_Logging_Pkg.DBG_Max_Size := 0;
246 Ap_Logging_Pkg.DBG_Used_Size := 0;
247 Ap_Logging_Pkg.DBG_Lines_Entered := 0;
248 Ap_Logging_Pkg.DBG_Message_Level := 0;
249 Ap_Logging_Pkg.DBG_Debug_Stack := null;
250 Ap_Logging_Pkg.DBG_Log_Return_Code := -1;
251 Ap_Logging_Pkg.DBG_Stat := Build_Stat_String(0,0);
252 Ap_Logging_Pkg.DBG_Currently_Logging := FALSE;
253 --
254 END Ap_Begin_Log;
255 --
256 --
257 procedure Ap_End_Log
258 is
259 /*
260
261 Copyright (c) 1995 by Oracle Corporation
262
263 NAME
264 Ap_End_Log
265 DESCRIPTION
266 This procedure issues the close message to the piping area in memory
267 identified by the actual value of Ap_Logging_Pkg.DBG_Pipe_Name
268 NOTES
269 Procedure to be conditionally executed from the application firing
270 the PL/SQL object
271 HISTORY (YY/MM/DD)
272 atassoni.it 95/07/05 Creation
273 */
274 --
275 footer_message varchar2(240) := '<< Closed '||
276 Ap_Logging_Pkg.DBG_Pipe_Name||
277 ' on '||
278 to_char(sysdate,'Mon dd hh24:mi:ss')||
279 ' - used: ';
280 BEGIN
281 --
282 footer_message := footer_message||Build_Stat_String
283 (Ap_Logging_Pkg.DBG_Used_Size+
284 length(footer_message)+16
285 ,Ap_Logging_Pkg.DBG_Max_Size
286 );
287 --
288 -- Terminates the pipe trying to insert the footer as last message:
289 Send_Message_To_Pipe (Ap_Logging_Pkg.DBG_Pipe_Name
290 ,footer_message
291 ,Ap_Logging_Pkg.DBG_Log_Return_Code
292 ,Ap_Logging_Pkg.DBG_Stat
293 ,Ap_Logging_Pkg.DBG_Used_Size
294 ,Ap_Logging_Pkg.DBG_Lines_Entered
295 );
296 --
297 -- Extinguish piping to this name
298 Ap_Logging_Pkg.DBG_Currently_Logging := FALSE;
299 --
300 END Ap_End_Log;
301 --
302 --
303 function Ap_Pipe_Name
304 return varchar2
305 is
306 BEGIN
307 return (Ap_Logging_Pkg.DBG_Pipe_Name);
308 END Ap_Pipe_Name;
309 --
310 --
311 procedure Ap_Pipe_Name_23 (P_Pipe_name OUT NOCOPY varchar2)
312 is
313 BEGIN
314 P_Pipe_name := Ap_Logging_Pkg.DBG_Pipe_Name;
315 END Ap_Pipe_Name_23;
316 --
317 --
318 function Ap_Log_Return_Code
319 return number
320 is
321 BEGIN
322 return (Ap_Logging_Pkg.DBG_Log_Return_Code);
323 END Ap_Log_Return_Code;
324 --
325 --
326 procedure Ap_Begin_Block (P_Message_Location IN varchar2)
327 is
328 BEGIN
329 --
330 Push_One_Level (P_Message_Location);
331 Ap_Logging_Pkg.Ap_Log ('BEGIN '||P_Message_Location, P_Message_Location);
332 --
333 END Ap_Begin_Block;
334 --
335 --
336 procedure Ap_End_Block (P_Message_Location IN varchar2)
337 is
338 BEGIN
339 --
340 Ap_Logging_Pkg.Ap_Log ('END '||P_Message_Location, P_Message_Location);
341 Pop_One_Level;
342 --
343 END Ap_End_Block;
344 --
345 --
346 procedure Ap_Indent
347 is
348 BEGIN
349 --
350 Push_One_Level (to_char(Ap_Logging_Pkg.DBG_Message_Level+1));
351 --
352 END Ap_Indent;
353 --
354 --
355 procedure Ap_Outdent
356 is
357 BEGIN
361 END Ap_Outdent;
358 --
359 Pop_One_Level;
360 --
362 --
363 --
364 procedure Ap_Log (P_Message IN varchar2
365 ,P_Message_Location IN varchar2
366 default null
367 )
368
369 is
370 /*
371 Copyright (c) 1995 by Oracle Corporation
372
373 NAME
374 Ap_Log
375 DESCRIPTION
376 This procedure sends a debug/log message to the specified pipe
377 Each message is automatically indented to the right on a
378 P_Message_Location basis through the current DBG_Debug_Stack value.
379 NOTES
380 This procedure issues the message to the piping area in memory
381 identified by the actual value of Ap_Logging_Pkg.DBG_Pipe_Name
382
383 HISTORY (YY/MM/DD)
384 atassoni.it 95/07/05 Creation
385 */
386 --
387 current_level number;
388 message varchar2(5000) := P_Message;
389 location varchar2(30) := P_Message_Location;
390 NOTHING_TO_DO exception;
391 --
392 BEGIN
393 --
394 if (NOT nvl(Ap_Logging_Pkg.DBG_Currently_Logging, FALSE)) then
395 raise NOTHING_TO_DO;
396 end if;
397 --
398 if (P_Message_Location is null) then
399 -- No location passed in: assign a default one as level#
400 if (Ap_Logging_Pkg.DBG_Debug_Stack is null) then
401 location := '1';
402 else
403 location := to_char(Ap_Logging_Pkg.DBG_Message_Level);
404 end if;
405 end if;
406 --
407 current_level := Get_Location_Level (location);
408 --
409 if (current_level = 0) then
410 -- The location is not in the stack. Create one more level:
411 Push_One_Level (location);
412 else
413 -- The location is already in the stack. Bring the stack to that level:
414 loop
415 exit when (current_level = Ap_Logging_Pkg.DBG_Message_Level);
416 Pop_One_Level;
417 end loop;
418 end if;
419 --
420 -- Insert the message at current indentation level:
421 Send_Message_To_Pipe (Ap_Logging_Pkg.DBG_Pipe_Name
422 ,lpad(message
423 ,length(message)+2*Ap_Logging_Pkg.DBG_Message_Level
424 )
425 ,Ap_Logging_Pkg.DBG_Log_Return_Code
426 ,Ap_Logging_Pkg.DBG_Stat
427 ,Ap_Logging_Pkg.DBG_Used_Size
428 ,Ap_Logging_Pkg.DBG_Lines_Entered
429 );
430 --
431 EXCEPTION
432 --
433 when NOTHING_TO_DO then null;
434 --
435 END Ap_Log;
436 --
437 -- _______
438 -- | |
439 -- | |
440 -- | |
441 -- _________| |_________
442 -- \ /
443 -- \ AP Debugging/Logging /
444 -- \ thru pipes /
445 -- \ /
446 -- ___________ ___ __ ___________
447 -- / _________/ / . \ / / / _________ \
448 -- / /______ \ / / \ \ / / / / / /
449 -- / _______/ \/ / \ \ / / / / / /
450 -- / /_________ / / \ ` / / /________/ /
451 -- /___________/ /_/ \_/ /___________,'
452 -- \ /
453 -- \ /
454 -- \ /
455 -- v
456 --
457 --
458 end AP_LOGGING_PKG;