line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Object::Remote::Logging; |
2
|
|
|
|
|
|
|
|
3
|
17
|
|
|
17
|
|
40090
|
use Moo; |
|
17
|
|
|
|
|
164507
|
|
|
17
|
|
|
|
|
89
|
|
4
|
17
|
|
|
17
|
|
23755
|
use Object::Remote::Logging::Logger; |
|
17
|
|
|
|
|
129
|
|
|
17
|
|
|
|
|
505
|
|
5
|
17
|
|
|
17
|
|
8590
|
use Exporter::Declare; |
|
17
|
|
|
|
|
279850
|
|
|
17
|
|
|
|
|
62
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
extends 'Log::Contextual'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
exports(qw( ____ router arg_levels )); |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub router { |
12
|
568
|
|
66
|
568
|
1
|
159105
|
our $Router_Instance ||= do { |
13
|
17
|
|
|
|
|
6921
|
require Object::Remote::Logging::Router; |
14
|
17
|
|
|
|
|
81
|
Object::Remote::Logging::Router->new; |
15
|
|
|
|
|
|
|
} |
16
|
|
|
|
|
|
|
} |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
#log level descriptions |
19
|
|
|
|
|
|
|
#info - standard log level - normal program output for the end user |
20
|
|
|
|
|
|
|
#warn - output for program that is executing quietly |
21
|
|
|
|
|
|
|
#error - output for program that is running more quietly |
22
|
|
|
|
|
|
|
#fatal - it is not possible to continue execution; this level is as quiet as is possible |
23
|
|
|
|
|
|
|
#verbose - output for program executing verbosely (-v) |
24
|
|
|
|
|
|
|
#debug - output for program running more verbosely (-v -v) |
25
|
|
|
|
|
|
|
#trace - output for program running extremely verbosely (-v -v -v) |
26
|
|
|
|
|
|
|
sub arg_levels { |
27
|
|
|
|
|
|
|
#the order of the log levels is significant with the |
28
|
|
|
|
|
|
|
#most verbose level being first in the list and the |
29
|
|
|
|
|
|
|
#most quiet as the last item |
30
|
160
|
|
|
160
|
1
|
5028
|
return [qw( trace debug verbose info warn error fatal )]; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub before_import { |
34
|
145
|
|
|
145
|
0
|
119327
|
my ($class, $importer, $spec) = @_; |
35
|
145
|
|
|
|
|
338
|
my $router = $class->router; |
36
|
145
|
|
|
|
|
310
|
our $DID_INIT; |
37
|
|
|
|
|
|
|
|
38
|
145
|
100
|
|
|
|
353
|
unless($DID_INIT) { |
39
|
17
|
|
|
|
|
29
|
$DID_INIT = 1; |
40
|
17
|
|
|
|
|
46
|
init_logging(); |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
145
|
|
|
|
|
683
|
$class->SUPER::before_import($importer, $spec); |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub _parse_selections { |
47
|
1
|
|
|
1
|
|
822
|
my ($selections_string) = @_; |
48
|
1
|
|
|
|
|
2
|
my %log_ok; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
#example string: |
51
|
|
|
|
|
|
|
#" * -Object::Remote::Logging Foo::Bar::Baz " |
52
|
1
|
|
|
|
|
7
|
foreach(split(/\s+/, $selections_string)) { |
53
|
3
|
50
|
|
|
|
5
|
next if $_ eq ''; |
54
|
3
|
100
|
|
|
|
11
|
if ($_ eq '*') { |
|
|
100
|
|
|
|
|
|
55
|
1
|
|
|
|
|
2
|
$log_ok{$_} = 1; |
56
|
|
|
|
|
|
|
} elsif (s/^-//) { |
57
|
1
|
|
|
|
|
3
|
$log_ok{$_} = 0; |
58
|
|
|
|
|
|
|
} else { |
59
|
1
|
|
|
|
|
3
|
$log_ok{$_} = 1; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
1
|
|
|
|
|
6
|
return %log_ok; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
#this is invoked on all nodes |
67
|
|
|
|
|
|
|
sub init_logging { |
68
|
17
|
|
|
17
|
0
|
40
|
my $level = $ENV{OBJECT_REMOTE_LOG_LEVEL}; |
69
|
17
|
|
|
|
|
26
|
my $format = $ENV{OBJECT_REMOTE_LOG_FORMAT}; |
70
|
17
|
|
|
|
|
28
|
my $selections = $ENV{OBJECT_REMOTE_LOG_SELECTIONS}; |
71
|
17
|
|
|
|
|
29
|
my $test_logging = $ENV{OBJECT_REMOTE_TEST_LOGGER}; |
72
|
17
|
|
|
|
|
23
|
my %controller_should_log; |
73
|
|
|
|
|
|
|
|
74
|
17
|
50
|
33
|
|
|
83
|
unless (defined $ENV{OBJECT_REMOTE_LOG_FORWARDING} && $ENV{OBJECT_REMOTE_LOG_FORWARDING} ne '') { |
75
|
17
|
|
|
|
|
110
|
$ENV{OBJECT_REMOTE_LOG_FORWARDING} = 0; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
17
|
50
|
|
|
|
106
|
if ($test_logging) { |
79
|
0
|
|
|
|
|
0
|
require Object::Remote::Logging::TestLogger; |
80
|
0
|
|
|
|
|
0
|
router->connect(Object::Remote::Logging::TestLogger->new( |
81
|
|
|
|
|
|
|
min_level => 'trace', max_level => 'error', |
82
|
|
|
|
|
|
|
level_names => Object::Remote::Logging->arg_levels(), |
83
|
|
|
|
|
|
|
)); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
{ |
87
|
17
|
|
|
17
|
|
21183
|
no warnings 'once'; |
|
17
|
|
|
|
|
26
|
|
|
17
|
|
|
|
|
4593
|
|
|
17
|
|
|
|
|
23
|
|
88
|
17
|
50
|
|
|
|
52
|
if (defined $Object::Remote::FatNode::REMOTE_NODE) { |
89
|
|
|
|
|
|
|
#the connection id for the remote node comes in later |
90
|
|
|
|
|
|
|
#as the controlling node inits remote logging |
91
|
0
|
|
|
|
|
0
|
router()->_remote_metadata({ connection_id => undef }); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
17
|
50
|
33
|
|
|
75
|
return unless defined $level && $level ne ''; |
96
|
|
|
|
|
|
|
|
97
|
0
|
0
|
|
|
|
|
$format = "[%l %r] %s" unless defined $format; |
98
|
0
|
0
|
|
|
|
|
$selections = __PACKAGE__ unless defined $selections; |
99
|
0
|
|
|
|
|
|
%controller_should_log = _parse_selections($selections); |
100
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
my $logger = Object::Remote::Logging::Logger->new( |
102
|
|
|
|
|
|
|
min_level => lc($level), format => $format, |
103
|
|
|
|
|
|
|
level_names => Object::Remote::Logging::arg_levels(), |
104
|
|
|
|
|
|
|
); |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
router()->connect(sub { |
107
|
0
|
|
|
0
|
|
|
my $controller = $_[1]->{exporter}; |
108
|
0
|
|
|
|
|
|
my $will_log = $controller_should_log{$controller}; |
109
|
0
|
|
|
|
|
|
my $remote_info = $_[1]->{object_remote}; |
110
|
|
|
|
|
|
|
|
111
|
0
|
0
|
|
|
|
|
$will_log = $controller_should_log{'*'} unless defined $will_log; |
112
|
|
|
|
|
|
|
|
113
|
0
|
0
|
|
|
|
|
return unless $will_log; |
114
|
|
|
|
|
|
|
#skip things from remote hosts because they log to STDERR |
115
|
|
|
|
|
|
|
#when OBJECT_REMOTE_LOG_LEVEL is in effect |
116
|
0
|
0
|
|
|
|
|
return if $remote_info->{forwarded}; |
117
|
0
|
|
|
|
|
|
return $logger; |
118
|
0
|
|
|
|
|
|
}); |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
#this is invoked by the controlling node |
122
|
|
|
|
|
|
|
#on the remote nodes |
123
|
|
|
|
|
|
|
sub init_remote_logging { |
124
|
0
|
|
|
0
|
0
|
|
my ($self, %controller_info) = @_; |
125
|
|
|
|
|
|
|
|
126
|
0
|
|
|
|
|
|
router()->_remote_metadata(\%controller_info); |
127
|
0
|
0
|
|
|
|
|
router()->_forward_destination($controller_info{router}) if $ENV{OBJECT_REMOTE_LOG_FORWARDING}; |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
1; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=head1 NAME |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Object::Remote::Logging - Logging subsystem for Object::Remote |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head1 SYNOPSIS |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
use Object::Remote::Logging qw( :log :dlog arg_levels router ); |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
$levels = [qw( trace debug verbose info warn error fatal )]; |
141
|
|
|
|
|
|
|
$levels = arg_levels(); #same result |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
$ENV{OBJECT_REMOTE_LOG_LEVEL} = 'trace'; #or other level name |
144
|
|
|
|
|
|
|
$ENV{OBJECT_REMOTE_LOG_FORMAT} = '%l %t: %p::%m %s'; #and more |
145
|
|
|
|
|
|
|
#Output logs from two specific logging pacakges |
146
|
|
|
|
|
|
|
$ENV{OBJECT_REMOTE_LOG_SELECTIONS} = 'Object::Remote::Logging Some::Other::Package'; |
147
|
|
|
|
|
|
|
#Output all log messages except those generated by Object::Remote |
148
|
|
|
|
|
|
|
$ENV{OBJECT_REMOTE_LOG_SELECTIONS} = '* -Object::Remote::Logging'; |
149
|
|
|
|
|
|
|
$ENV{OBJECT_REMOTE_LOG_FORWARDING} = 1; #default 0 |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
log_info { 'Trace log event' }; |
152
|
|
|
|
|
|
|
Dlog_verbose { "Debug event with Data::Dumper::Concise: $_" } { foo => 'bar' }; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=head1 DESCRIPTION |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
This is the logging framework for Object::Remote implemented as an extension of |
157
|
|
|
|
|
|
|
L with a slightly incompatible API. This system allows |
158
|
|
|
|
|
|
|
developers using Object::Remote and end users of that software to control |
159
|
|
|
|
|
|
|
Object::Remote logging so operation can be tracked if needed. This is also |
160
|
|
|
|
|
|
|
the API used to generate log messages inside the Object::Remote source code. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
The rest of the logging system comes from L |
163
|
|
|
|
|
|
|
which implements log rendering and output and Object::Remote::Logging::Router |
164
|
|
|
|
|
|
|
which delivers log events to the loggers. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=head1 USAGE |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Object::Remote logging output is not enabled by default. If you need to immediately start |
169
|
|
|
|
|
|
|
debugging set the OBJECT_REMOTE_LOG_LEVEL environment variable to either 'trace' |
170
|
|
|
|
|
|
|
or 'debug'. This will enable logging to STDERR on the local and all remote Perl |
171
|
|
|
|
|
|
|
interpreters. By default STDERR for all remote interpreters is passed through |
172
|
|
|
|
|
|
|
unmodified so this is sufficient to receive logs generated anywhere Object::Remote |
173
|
|
|
|
|
|
|
is running. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Every time the local interpreter creates a new Object::Remote::Connection the connection |
176
|
|
|
|
|
|
|
is given an id that is unique to that connection on the local interpreter. The connection |
177
|
|
|
|
|
|
|
id and other metadata is available in the log output via a log format string that can |
178
|
|
|
|
|
|
|
be set via the OBJECT_REMOTE_LOG_FORMAT environment variable. The format string and |
179
|
|
|
|
|
|
|
available metadata is documented in L. Setting this |
180
|
|
|
|
|
|
|
environment variable on the local interpreter will cause it to be propagated to the |
181
|
|
|
|
|
|
|
remote interpreter so all logs will be formated the same way. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
This system is designed so any module can create their own logging packages using it. |
184
|
|
|
|
|
|
|
With out any additional configuration the consumers of this logging system will |
185
|
|
|
|
|
|
|
automatically be enabled via OBJECT_REMOTE_LOG_LEVEL and formated with |
186
|
|
|
|
|
|
|
OBJECT_REMOTE_LOG_FORMAT but those additional log messages are not sent to STDERR. |
187
|
|
|
|
|
|
|
By setting the OBJECT_REMOTE_LOG_SELECTIONS environment variable to a list of logging |
188
|
|
|
|
|
|
|
package names seperated by spaces then logs generated using those packages |
189
|
|
|
|
|
|
|
will be sent to STDERR. If the asterisk character (*) is used in the place of a package |
190
|
|
|
|
|
|
|
name then all package names will be selected by default instead of ignored. An individual |
191
|
|
|
|
|
|
|
package name can be turned off by prefixing the name with a hypen character (-). This is |
192
|
|
|
|
|
|
|
also a configuration item that is forwarded to the remote interpreters so all logging |
193
|
|
|
|
|
|
|
is consistent. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
Regardless of OBJECT_REMOTE_LOG_LEVEL the logging system is still active and loggers |
196
|
|
|
|
|
|
|
can access the stream of log messages to format and output them. Internally |
197
|
|
|
|
|
|
|
OBJECT_REMOTE_LOG_LEVEL causes an L to be built |
198
|
|
|
|
|
|
|
and connected to the Object::Remote::Logging::Router instance. It is also possible |
199
|
|
|
|
|
|
|
to manually build a logger instance and connect it to the router. See the |
200
|
|
|
|
|
|
|
Object::Remote::Logging documentation for more information. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
The logging system also supports a method of forwarding log messages from remote |
203
|
|
|
|
|
|
|
interpreters to the local interpreter. Forwarded log messages are generated in the |
204
|
|
|
|
|
|
|
remote interpreter and the logger for the message is invoked in the local interpreter. |
205
|
|
|
|
|
|
|
Packages using or extending Object::Remote::Logging will have log messages forwarded automatically. |
206
|
|
|
|
|
|
|
Loggers receive forwarded log messages exactly the same way as non-forwarded messages |
207
|
|
|
|
|
|
|
except a forwarded message includes extra metadata about the remote connection. Log |
208
|
|
|
|
|
|
|
forwarding is disabled by default because it comes with a performance hit; to enable |
209
|
|
|
|
|
|
|
it set the OBJECT_REMOTE_LOG_FORWARDING environment variable to 1. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=head1 EXPORTABLE SUBROUTINES |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=over 4 |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=item arg_levels |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
Returns an array reference that contains the ordered list of level names |
218
|
|
|
|
|
|
|
with the lowest log level first and the highest log level last. |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=item router |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Returns the instance of L that is in use. The router |
223
|
|
|
|
|
|
|
instance is used in combination with L objects to |
224
|
|
|
|
|
|
|
select then render and output log messages. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item log_ and Dlog_ |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
These methods come direct from L; see that documentation for a |
229
|
|
|
|
|
|
|
complete reference. For each of the log level names there are subroutines with the log_ |
230
|
|
|
|
|
|
|
and Dlog_ prefix that will generate the log message. The first argument is a code block |
231
|
|
|
|
|
|
|
that returns the log message contents and the optional further arguments are both passed |
232
|
|
|
|
|
|
|
to the block as the argument list and returned from the log method as a list. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
log_trace { "A fine log message $_[0] " } 'if I do say so myself'; |
235
|
|
|
|
|
|
|
%hash = Dlog_trace { "Very handy: $_" } ( foo => 'bar' ); |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=item logS_ and DlogS_ |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Works just like log_ and Dlog_ except returns only the first argument as a scalar value. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
my $beverage = logS_info { "Customer ordered $_[0]" } 'Coffee'; |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=back |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=head1 LEVEL NAMES |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
Object::Remote uses an ordered list of log level names with the lowest level |
248
|
|
|
|
|
|
|
first and the highest level last. The list of level names can be accessed via |
249
|
|
|
|
|
|
|
the arg_levels method which is exportable to the consumer of this class. The log |
250
|
|
|
|
|
|
|
level names are: |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=over 4 |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item trace |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
As much information about operation as possible including multiple line dumps of |
257
|
|
|
|
|
|
|
large content. Tripple verbose operation (-v -v -v). |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=item debug |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Messages about operations that could hang as well as internal state changes, |
262
|
|
|
|
|
|
|
results from method invocations, and information useful when looking for faults. |
263
|
|
|
|
|
|
|
Double verbose operation (-v -v). |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=item verbose |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
Additional optional messages to the user that can be enabled at their will. Single |
268
|
|
|
|
|
|
|
verbose operation (-v). |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item info |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Messages from normal operation that are intended to be displayed to the end |
273
|
|
|
|
|
|
|
user if quiet operation is not indicated and more verbose operation is not |
274
|
|
|
|
|
|
|
in effect. |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=item warn |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Something wasn't supposed to happen but did. Operation was not impacted but |
279
|
|
|
|
|
|
|
otherwise the event is noteworthy. Single quiet operation (-q). |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=item error |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Something went wrong. Operation of the system may continue but some operation |
284
|
|
|
|
|
|
|
has most definitely failed. Double quiet operation (-q -q). |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=item fatal |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Something went wrong and recovery is not possible. The system should stop operating |
289
|
|
|
|
|
|
|
as soon as possible. Tripple quiet operation (-q -q -q). |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=back |