| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Object::Remote::Logging; |
|
2
|
|
|
|
|
|
|
|
|
3
|
17
|
|
|
17
|
|
122252
|
use Moo; |
|
|
17
|
|
|
|
|
127650
|
|
|
|
17
|
|
|
|
|
76
|
|
|
4
|
17
|
|
|
17
|
|
23982
|
use Object::Remote::Logging::Logger; |
|
|
17
|
|
|
|
|
45
|
|
|
|
17
|
|
|
|
|
467
|
|
|
5
|
17
|
|
|
17
|
|
7690
|
use Exporter::Declare; |
|
|
17
|
|
|
|
|
309435
|
|
|
|
17
|
|
|
|
|
64
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
extends 'Log::Contextual'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
exports(qw( ____ router arg_levels )); |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub router { |
|
12
|
568
|
|
66
|
568
|
1
|
446261
|
our $Router_Instance ||= do { |
|
13
|
17
|
|
|
|
|
7027
|
require Object::Remote::Logging::Router; |
|
14
|
17
|
|
|
|
|
82
|
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
|
6201
|
return [qw( trace debug verbose info warn error fatal )]; |
|
31
|
|
|
|
|
|
|
} |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub before_import { |
|
34
|
145
|
|
|
145
|
0
|
148444
|
my ($class, $importer, $spec) = @_; |
|
35
|
145
|
|
|
|
|
424
|
my $router = $class->router; |
|
36
|
145
|
|
|
|
|
266
|
our $DID_INIT; |
|
37
|
|
|
|
|
|
|
|
|
38
|
145
|
100
|
|
|
|
467
|
unless($DID_INIT) { |
|
39
|
17
|
|
|
|
|
36
|
$DID_INIT = 1; |
|
40
|
17
|
|
|
|
|
55
|
init_logging(); |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
145
|
|
|
|
|
783
|
$class->SUPER::before_import($importer, $spec); |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub _parse_selections { |
|
47
|
1
|
|
|
1
|
|
1158
|
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
|
|
|
|
7
|
next if $_ eq ''; |
|
54
|
3
|
100
|
|
|
|
11
|
if ($_ eq '*') { |
|
|
|
100
|
|
|
|
|
|
|
55
|
1
|
|
|
|
|
3
|
$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
|
|
|
|
|
5
|
return %log_ok; |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
#this is invoked on all nodes |
|
67
|
|
|
|
|
|
|
sub init_logging { |
|
68
|
17
|
|
|
17
|
0
|
65
|
my $level = $ENV{OBJECT_REMOTE_LOG_LEVEL}; |
|
69
|
17
|
|
|
|
|
39
|
my $format = $ENV{OBJECT_REMOTE_LOG_FORMAT}; |
|
70
|
17
|
|
|
|
|
39
|
my $selections = $ENV{OBJECT_REMOTE_LOG_SELECTIONS}; |
|
71
|
17
|
|
|
|
|
33
|
my $test_logging = $ENV{OBJECT_REMOTE_TEST_LOGGER}; |
|
72
|
17
|
|
|
|
|
26
|
my %controller_should_log; |
|
73
|
|
|
|
|
|
|
|
|
74
|
17
|
50
|
33
|
|
|
69
|
unless (defined $ENV{OBJECT_REMOTE_LOG_FORWARDING} && $ENV{OBJECT_REMOTE_LOG_FORWARDING} ne '') { |
|
75
|
17
|
|
|
|
|
127
|
$ENV{OBJECT_REMOTE_LOG_FORWARDING} = 0; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
|
|
78
|
17
|
50
|
|
|
|
56
|
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
|
|
28950
|
no warnings 'once'; |
|
|
17
|
|
|
|
|
45
|
|
|
|
17
|
|
|
|
|
4919
|
|
|
|
17
|
|
|
|
|
29
|
|
|
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
|
|
|
91
|
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 |