line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#----------------------------------------------------------------- |
2
|
|
|
|
|
|
|
package DeltaX::Trace; |
3
|
|
|
|
|
|
|
#----------------------------------------------------------------- |
4
|
|
|
|
|
|
|
# $Id: Trace.pm,v 1.5 2004/10/20 10:04:35 martin Exp $ |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# (c) DELTA E.S., 2002 - 2003 |
7
|
|
|
|
|
|
|
# This package is free software; you can use it under "Artistic License" from |
8
|
|
|
|
|
|
|
# Perl. |
9
|
|
|
|
|
|
|
#----------------------------------------------------------------- |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
$DeltaX::Trace::VERSION = '1.1'; |
12
|
|
|
|
|
|
|
|
13
|
4
|
|
|
4
|
|
308
|
use Exporter; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
179
|
|
14
|
4
|
|
|
4
|
|
18
|
use Carp; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
214
|
|
15
|
|
|
|
|
|
|
|
16
|
4
|
|
|
4
|
|
14
|
use vars qw(@ISA @EXPORT @EXPORT_OK %options); |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
7335
|
|
17
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
18
|
|
|
|
|
|
|
@EXPORT = qw(trace_set trace); |
19
|
|
|
|
|
|
|
@EXPORT_OK = qw(error warn info debug _tspecial); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
%$options = ( |
22
|
|
|
|
|
|
|
trace_file => '/var/tmp/trace.log', |
23
|
|
|
|
|
|
|
trace_error_file => 1, |
24
|
|
|
|
|
|
|
trace_error_std => 0, |
25
|
|
|
|
|
|
|
trace_warn_file => 1, |
26
|
|
|
|
|
|
|
trace_warn_std => 0, |
27
|
|
|
|
|
|
|
trace_info_file => 1, |
28
|
|
|
|
|
|
|
trace_info_std => 0, |
29
|
|
|
|
|
|
|
trace_debug_file => 1, |
30
|
|
|
|
|
|
|
trace_debug_std => 0, |
31
|
|
|
|
|
|
|
_special => '', |
32
|
|
|
|
|
|
|
trace_pid => 0, |
33
|
|
|
|
|
|
|
trace_stack => 0, |
34
|
|
|
|
|
|
|
); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub trace_set { |
37
|
|
|
|
|
|
|
|
38
|
0
|
0
|
|
0
|
1
|
|
croak ("trace_set() called with odd number of parameters - should be of the form field => value") |
39
|
|
|
|
|
|
|
if (@_ % 2); |
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
for (my $x = 0; $x <= $#_; $x += 2) { |
42
|
|
|
|
|
|
|
croak ("Unkown parameter $_[$x] in trace_set()") |
43
|
0
|
0
|
|
|
|
|
unless exists $options->{lc($_[$x])}; |
44
|
0
|
|
|
|
|
|
$options->{lc($_[$x])} = $_[$x+1]; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub trace { |
50
|
|
|
|
|
|
|
|
51
|
0
|
|
|
0
|
1
|
|
my $mtype = uc(shift); |
52
|
|
|
|
|
|
|
|
53
|
0
|
|
|
|
|
|
my $pos = 0; |
54
|
0
|
|
|
|
|
|
my (undef, $mfile, $mline) = caller($pos); |
55
|
0
|
|
|
|
|
|
my (undef, undef, undef, $msub) = caller($pos+1); |
56
|
0
|
|
|
|
|
|
my ($l_mfile, $l_mline, $l_msub) = ($mfile, $mline, $msub); |
57
|
0
|
0
|
|
|
|
|
$msub = 'main' if ! $msub; |
58
|
0
|
|
|
|
|
|
while ($l_msub =~ /^DeltaX::Trace/) { |
59
|
0
|
|
|
|
|
|
$pos++; |
60
|
0
|
|
|
|
|
|
($l_mfile, $l_mline, $l_msub) = ($mfile, $mline, $msub); |
61
|
0
|
|
|
|
|
|
(undef, $mfile, $mline) = caller($pos); |
62
|
0
|
|
|
|
|
|
(undef, undef, undef, $msub) = caller($pos+1); |
63
|
0
|
0
|
|
|
|
|
$msub = 'main' if ! $msub; |
64
|
|
|
|
|
|
|
} |
65
|
0
|
0
|
|
|
|
|
if ($l_msub eq 'main') { |
66
|
0
|
|
|
|
|
|
($mfile,$mline,$msub) = ($l_mfile,$l_mline,$l_msub); |
67
|
0
|
|
|
|
|
|
$l_msub = ''; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
0
|
0
|
|
|
|
|
if ($options->{_special}) { |
71
|
0
|
|
|
|
|
|
$mfile = $options->{_special}; |
72
|
0
|
|
|
|
|
|
$msub = ''; |
73
|
|
|
|
|
|
|
} |
74
|
0
|
0
|
|
|
|
|
if ($options->{trace_pid}) { |
75
|
0
|
|
|
|
|
|
$mfile .= " ($$)"; |
76
|
0
|
|
|
|
|
|
$l_mfile .= " ($$)"; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
0
|
|
|
|
|
|
my $to_file = 0; |
80
|
0
|
|
|
|
|
|
my $to_std = 0; |
81
|
0
|
|
|
|
|
|
my $title = ''; |
82
|
0
|
|
|
|
|
|
for ($mtype) { |
83
|
0
|
0
|
|
|
|
|
/^E/ && do { |
84
|
0
|
|
|
|
|
|
$to_file = $options->{trace_error_file}; |
85
|
0
|
|
|
|
|
|
$to_std = $options->{trace_error_std}; |
86
|
0
|
|
|
|
|
|
$title = 'ERROR'; |
87
|
0
|
|
|
|
|
|
last; |
88
|
|
|
|
|
|
|
}; |
89
|
0
|
0
|
|
|
|
|
/^W/ && do { |
90
|
0
|
|
|
|
|
|
$to_file = $options->{trace_warn_file}; |
91
|
0
|
|
|
|
|
|
$to_std = $options->{trace_warn_std}; |
92
|
0
|
|
|
|
|
|
$title = 'WARN'; |
93
|
0
|
|
|
|
|
|
last; |
94
|
|
|
|
|
|
|
}; |
95
|
0
|
0
|
|
|
|
|
/^I/ && do { |
96
|
0
|
|
|
|
|
|
$to_file = $options->{trace_info_file}; |
97
|
0
|
|
|
|
|
|
$to_std = $options->{trace_info_std}; |
98
|
0
|
|
|
|
|
|
$title = 'INFO'; |
99
|
0
|
|
|
|
|
|
last; |
100
|
|
|
|
|
|
|
}; |
101
|
0
|
0
|
|
|
|
|
/^D/ && do { |
102
|
0
|
|
|
|
|
|
$to_file = $options->{trace_debug_file}; |
103
|
0
|
|
|
|
|
|
$to_std = $options->{trace_debug_std}; |
104
|
0
|
|
|
|
|
|
$title = 'DEBUG'; |
105
|
0
|
|
|
|
|
|
last; |
106
|
|
|
|
|
|
|
}; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
0
|
|
|
|
|
|
my $msg = ''; |
110
|
0
|
|
|
|
|
|
while (@_) { $msg = $msg . ' ' . shift; } |
|
0
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
my $called = ''; |
112
|
0
|
0
|
0
|
|
|
|
if ($l_msub and ($msub ne $l_msub)) { |
113
|
0
|
|
|
|
|
|
$msg = "$title at $l_msub ($l_mfile) [$l_mline]: $msg (... called from $msub [$mline])"; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
else { |
116
|
0
|
|
|
|
|
|
$msg = "$title at $msub ($mfile) [$mline]: $msg"; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# get the stack for error |
120
|
0
|
0
|
|
|
|
|
my @stack = get_stack() if $options->{trace_stack}; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# stderr output |
123
|
0
|
0
|
|
|
|
|
if ($to_std) { print STDERR "$msg\n"; } |
|
0
|
|
|
|
|
|
|
124
|
0
|
0
|
|
|
|
|
if ($to_file) { |
125
|
0
|
0
|
|
|
|
|
if (open OUT, ">>".$options->{trace_file} ) { |
126
|
0
|
|
|
|
|
|
print OUT scalar localtime, " $msg\n"; |
127
|
0
|
0
|
0
|
|
|
|
if ($options->{trace_stack} && $mtype eq 'E' || |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
128
|
|
|
|
|
|
|
$options->{trace_stack} > 1 && $mtype eq 'W' || |
129
|
|
|
|
|
|
|
$options->{trace_stack} > 2 && $mtype eq 'I' || |
130
|
|
|
|
|
|
|
$options->{trace_stack} > 3 && $mtype eq 'D') { # print the stack |
131
|
0
|
|
|
|
|
|
print OUT " *".join("\n *", @stack)."\n"; |
132
|
|
|
|
|
|
|
} |
133
|
0
|
|
|
|
|
|
close OUT; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
0
|
|
|
0
|
1
|
|
sub error { trace('E', @_); } |
139
|
0
|
|
|
0
|
1
|
|
sub warn { trace('W', @_); } |
140
|
0
|
|
|
0
|
1
|
|
sub info { trace('I', @_); } |
141
|
0
|
|
|
0
|
1
|
|
sub debug { trace('D', @_); } |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub _tspecial { |
144
|
0
|
|
|
0
|
|
|
$options->{_special} = shift; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# get the stack - based on Carp::Heavy |
148
|
|
|
|
|
|
|
sub get_stack { |
149
|
0
|
|
|
0
|
1
|
|
my @stack; |
150
|
|
|
|
|
|
|
|
151
|
0
|
|
|
|
|
|
my ($pack, $file, $line, $sub, $hargs, $eval, $require); |
152
|
0
|
|
|
|
|
|
my (@a); |
153
|
0
|
|
|
|
|
|
my $i = 2; |
154
|
|
|
|
|
|
|
# let's go |
155
|
0
|
|
|
|
|
|
while (do { { package DB; @a = caller($i++) } } ) { |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# local copies |
157
|
0
|
|
|
|
|
|
($pack, $file, $line, $sub, $hargs, undef, $eval, $require) = @a; |
158
|
|
|
|
|
|
|
# subroutine name |
159
|
0
|
0
|
|
|
|
|
if (defined $eval) { |
|
|
0
|
|
|
|
|
|
160
|
0
|
0
|
|
|
|
|
if ($require) { |
161
|
0
|
|
|
|
|
|
$sub = "require $eval"; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
else { |
164
|
0
|
|
|
|
|
|
$eval =~ s/([\\\'])/\\$1/g; |
165
|
0
|
0
|
0
|
|
|
|
if ($MAX_EVAL and length($eval) > $MAX_EVAL) { |
166
|
0
|
|
|
|
|
|
substr($eval, $MAX_EVAL) = '...'; |
167
|
|
|
|
|
|
|
} |
168
|
0
|
|
|
|
|
|
$sub = "eval '$eval'"; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
elsif ($sub eq '(eval)') { |
172
|
0
|
|
|
|
|
|
$sub = "eval {...}"; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
# arguments |
175
|
0
|
0
|
|
|
|
|
if ($hargs) { |
176
|
|
|
|
|
|
|
# local copy |
177
|
0
|
|
|
|
|
|
@a = @DB::args; |
178
|
|
|
|
|
|
|
# check the number of arguments |
179
|
0
|
0
|
0
|
|
|
|
if ($MAX_ARGS and @a > $MAX_ARGS) { |
180
|
0
|
|
|
|
|
|
$#a = $MAX_ARGS; |
181
|
0
|
|
|
|
|
|
$a[$#a] = '...'; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
# get them all |
184
|
0
|
|
|
|
|
|
for (@a) { |
185
|
0
|
0
|
|
|
|
|
$_ = 'undef', next unless defined $_; |
186
|
0
|
0
|
|
|
|
|
if (ref $_) { |
187
|
|
|
|
|
|
|
# force string representation... |
188
|
0
|
|
|
|
|
|
$_ .= ''; |
189
|
|
|
|
|
|
|
} |
190
|
0
|
|
|
|
|
|
s/'/\\'/g; |
191
|
|
|
|
|
|
|
# check the length |
192
|
0
|
0
|
0
|
|
|
|
if ($MAX_ARG_LEN and length > $MAX_ARG_LEN) { |
193
|
0
|
|
|
|
|
|
substr($_, $MAX_ARG_LEN) = '...'; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
# quote (not for numbers) |
196
|
0
|
0
|
|
|
|
|
$_ = "'$_'" unless /^-?[\d.]+$/; |
197
|
|
|
|
|
|
|
} |
198
|
0
|
|
|
|
|
|
$sub .= '(' . join(', ', @a) . ')'; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
0
|
|
|
|
|
|
push @stack, "$sub at $file:$line"; |
202
|
|
|
|
|
|
|
} |
203
|
0
|
|
|
|
|
|
return @stack; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
1; |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=head1 NAME |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
DeltaX::Trace - Perl module for writing log messages |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
_____ |
213
|
|
|
|
|
|
|
/ \ _____ ______ ______ ___________ |
214
|
|
|
|
|
|
|
/ \ / \\__ \ / ___// ___// __ \_ __ \ |
215
|
|
|
|
|
|
|
/ Y \/ __ \_\___ \ \___ \\ ___/| | \/ |
216
|
|
|
|
|
|
|
\____|__ (____ /____ >____ >\___ >__| |
217
|
|
|
|
|
|
|
\/ \/ \/ \/ \/ project |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=head1 SYNOPSIS |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
use DeltaX::Trace; # exports only trace() and trace_set() |
223
|
|
|
|
|
|
|
use DeltaX::Trace qw/error warn info debug/; |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
trace_set(trace_file=>'my_log_file.log'); |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
trace('D', "This is", "message"); |
228
|
|
|
|
|
|
|
warn("This is warning"); |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=head1 FUNCTIONS |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=head2 trace_set() |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
Used to set tracing options (parameters are in key => value form): |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=over |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item trace_file |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
File to write trace messages (default is /var/tmp/trace.log). |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item trace_error_file |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
If set, error messages will be written to file (default is true). |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=item trace_error_std |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
If set, error messages will be written to stderr (default is false). |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=item trace_warn_file |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
If set, warning messages will be written to file (default is true). |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item trace_warn_std |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
If set, warning messages will be written to stderr (default is false). |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=item trace_info_file |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
If set, info messages will be written to file (default is true). |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=item trace_info_std |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
If set, info messages will be written to stderr (default is false). |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=item trace_debug_file |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
If set, debug messages will be written to file (default is true). |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item trace_debug_std |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
If set, debug messages will be written to stderr (default is false). |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item trace_pid |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
Is set, process ID will be attached to every message. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=item trace_stack |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
Is set, stack will be printed: |
281
|
|
|
|
|
|
|
1 with ERROR's |
282
|
|
|
|
|
|
|
2 with E and W |
283
|
|
|
|
|
|
|
3 with E, W and I |
284
|
|
|
|
|
|
|
4 with E, W, I and D |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
0 stack won't be printed. |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=back |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
=head2 trace() |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
This function actually creates and writes a message. First argument is a type of |
293
|
|
|
|
|
|
|
a message (E, W, I, D), other parameters are joined together into one line (with |
294
|
|
|
|
|
|
|
spaces). |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head2 error() |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Works as trace('E', ...). |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=head2 warn() |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Works as trace('W', ...). |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=head2 info() |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
Works as trace('I', ...). |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head2 debug() |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Works as trace('D', ...). |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head2 _tspecial() |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
Function for masser.fcgi - this value is printed instead of file name (if set). |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=head2 get_stack() |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
Returns stack (as an array) - based on Carp::Heavy code. |