ensure that gross code will not creep in
[p5sagit/Log-Contextual.git] / lib / Log / Contextual.pm
CommitLineData
0daa11f3 1package Log::Contextual;
2
a2777569 3use strict;
4use warnings;
2033c911 5
f61bcdd6 6our $VERSION = '0.006000';
489f71b2 7$VERSION = eval $VERSION
8 if $VERSION =~ /_/; # numify for warning-free dev releases
2033c911 9
ae9785e2 10my @levels = qw(debug trace warn info error fatal);
11
675503c7 12use Exporter::Declare;
13use Exporter::Declare::Export::Generator;
f11f9542 14use Data::Dumper::Concise;
5b094c87 15use Scalar::Util 'blessed';
2033c911 16
249b9eb6 17my @dlog = ((map "Dlog_$_", @levels), (map "DlogS_$_", @levels));
18
19my @log = ((map "log_$_", @levels), (map "logS_$_", @levels));
20
b144ba01 21eval {
22 require Log::Log4perl;
23 die if $Log::Log4perl::VERSION < 1.29;
24 Log::Log4perl->wrapper_register(__PACKAGE__)
25};
26
5fd26f45 27# ____ is because tags must have at least one export and we don't want to
28# export anything but the levels selected
6ae293d7 29sub ____ { }
5fd26f45 30
489f71b2 31exports('____', @dlog, @log, qw( set_logger with_logger ));
f11f9542 32
5fd26f45 33export_tag dlog => ('____');
34export_tag log => ('____');
675503c7 35import_arguments qw(logger package_logger default_logger);
36
139ded54 37sub router {
0092c26a 38 our $Router_Instance ||= do {
39 require Log::Contextual::Router;
40 Log::Contextual::Router->new
6ae293d7 41 }
0092c26a 42}
43
e06303cd 44sub default_import {
45 my ($class) = shift;
46
47 die 'Log::Contextual does not have a default import list';
48
49 ()
50}
51
6ae293d7 52sub arg_logger { $_[1] }
53sub arg_levels { $_[1] || [qw(debug trace warn info error fatal)] }
8112b699 54sub arg_package_logger { $_[1] }
55sub arg_default_logger { $_[1] }
56
675503c7 57sub before_import {
58 my ($class, $importer, $spec) = @_;
6ae293d7 59 my $router = $class->router;
60 my $exports = $spec->exports;
61 my %router_args = (
62 exporter => $class,
63 target => $importer,
64 arguments => $spec->argument_info
65 );
f11f9542 66
e06303cd 67 my @tags = $class->default_import($spec)
6ae293d7 68 if $spec->config->{default};
675503c7 69
e06303cd 70 for (@tags) {
71 die "only tags are supported for defaults at this time"
72 unless $_ =~ /^:(.*)$/;
73
74 $spec->config->{$1} = 1;
75 }
76
a5454e75 77 $router->before_import(%router_args);
8112b699 78
84d7d9ee 79 if ($exports->{'&set_logger'}) {
80 die ref($router) . " does not support set_logger()"
81 unless $router->does('Log::Contextual::Role::Router::SetLogger');
4d605164 82
84d7d9ee 83 $spec->add_export('&set_logger', sub { $router->set_logger(@_) })
84 }
4d605164 85
84d7d9ee 86 if ($exports->{'&with_logger'}) {
87 die ref($router) . " does not support with_logger()"
88 unless $router->does('Log::Contextual::Role::Router::WithLogger');
4d605164 89
84d7d9ee 90 $spec->add_export('&with_logger', sub { $router->with_logger(@_) })
91 }
4d605164 92
5fd26f45 93 my @levels = @{$class->arg_levels($spec->config->{levels})};
675503c7 94 for my $level (@levels) {
249b9eb6 95 if ($spec->config->{log} || $exports->{"&log_$level"}) {
6ae293d7 96 $spec->add_export(
97 "&log_$level",
98 sub (&@) {
99 my ($code, @args) = @_;
100 $router->handle_log_request(
101 exporter => $class,
102 caller_package => scalar(caller),
103 caller_level => 1,
104 message_level => $level,
105 message_sub => $code,
106 message_args => \@args,
107 );
108 return @args;
109 });
249b9eb6 110 }
111 if ($spec->config->{log} || $exports->{"&logS_$level"}) {
6ae293d7 112 $spec->add_export(
113 "&logS_$level",
114 sub (&@) {
115 my ($code, @args) = @_;
116 $router->handle_log_request(
117 exporter => $class,
118 caller_package => scalar(caller),
119 caller_level => 1,
120 message_level => $level,
121 message_sub => $code,
122 message_args => \@args,
123 );
124 return $args[0];
125 });
675503c7 126 }
249b9eb6 127 if ($spec->config->{dlog} || $exports->{"&Dlog_$level"}) {
6ae293d7 128 $spec->add_export(
129 "&Dlog_$level",
130 sub (&@) {
131 my ($code, @args) = @_;
132 my $wrapped = sub {
133 local $_ = (@_ ? Data::Dumper::Concise::Dumper @_ : '()');
134 &$code;
135 };
136 $router->handle_log_request(
137 exporter => $class,
138 caller_package => scalar(caller),
139 caller_level => 1,
140 message_level => $level,
141 message_sub => $wrapped,
142 message_args => \@args,
143 );
144 return @args;
145 });
249b9eb6 146 }
147 if ($spec->config->{dlog} || $exports->{"&DlogS_$level"}) {
6ae293d7 148 $spec->add_export(
149 "&DlogS_$level",
150 sub (&$) {
151 my ($code, $ref) = @_;
152 my $wrapped = sub {
153 local $_ = Data::Dumper::Concise::Dumper($_[0]);
154 &$code;
155 };
156 $router->handle_log_request(
157 exporter => $class,
158 caller_package => scalar(caller),
159 caller_level => 1,
160 message_level => $level,
161 message_sub => $wrapped,
162 message_args => [$ref],
163 );
164 return $ref;
165 });
a2777569 166 }
167 }
675503c7 168}
169
a5454e75 170sub after_import {
171 my ($class, $importer, $spec) = @_;
6ae293d7 172 my %router_args = (
173 exporter => $class,
174 target => $importer,
175 arguments => $spec->argument_info
176 );
a5454e75 177 $class->router->after_import(%router_args);
178}
709d11fe 179
31285520 180for (qw(set with)) {
181 no strict 'refs';
182 my $sub = "${_}_logger";
183 *{"Log::Contextual::$sub"} = sub {
489f71b2 184 die "$sub is no longer a direct sub in Log::Contextual. "
185 . 'Note that this feature was never tested nor documented. '
186 . "Please fix your code to import $sub instead of trying to use it directly"
187 }
31285520 188}
189
0daa11f3 1901;
0a3750e2 191
192__END__
193
2daff231 194=head1 NAME
195
8bc568d2 196Log::Contextual - Simple logging interface with a contextual log
2daff231 197
198=head1 SYNOPSIS
199
9b8e24d5 200 use Log::Contextual qw( :log :dlog set_logger with_logger );
5b094c87 201 use Log::Contextual::SimpleLogger;
202 use Log::Log4perl ':easy';
203 Log::Log4perl->easy_init($DEBUG);
2daff231 204
5b094c87 205 my $logger = Log::Log4perl->get_logger;
206
207 set_logger $logger;
2daff231 208
9b8e24d5 209 log_debug { 'program started' };
2daff231 210
211 sub foo {
f9bf084b 212
213 my $minilogger = Log::Contextual::SimpleLogger->new({
214 levels => [qw( trace debug )]
215 });
216
2ae9c121 217 my @args = @_;
218
f9bf084b 219 with_logger $minilogger => sub {
21431192 220 log_trace { 'foo entered' };
2ae9c121 221 my ($foo, $bar) = Dlog_trace { "params for foo: $_" } @args;
2daff231 222 # ...
21431192 223 log_trace { 'foo left' };
f9bf084b 224 };
2daff231 225 }
226
5b094c87 227 foo();
228
9fe4eeb3 229Beginning with version 1.008 L<Log::Dispatchouli> also works out of the box
230with C<Log::Contextual>:
231
232 use Log::Contextual qw( :log :dlog set_logger );
233 use Log::Dispatchouli;
234 my $ld = Log::Dispatchouli->new({
235 ident => 'slrtbrfst',
236 to_stderr => 1,
237 debug => 1,
238 });
239
240 set_logger $ld;
241
242 log_debug { 'program started' };
243
2daff231 244=head1 DESCRIPTION
245
30d7027a 246Major benefits:
247
248=over 2
249
250=item * Efficient
251
252The logging functions take blocks, so if a log level is disabled, the
253block will not run:
254
255 # the following won't run if debug is off
256 log_debug { "the new count in the database is " . $rs->count };
257
258Similarly, the C<D> prefixed methods only C<Dumper> the input if the level is
259enabled.
260
261=item * Handy
262
263The logging functions return their arguments, so you can stick them in
264the middle of expressions:
265
266 for (log_debug { "downloading:\n" . join qq(\n), @_ } @urls) { ... }
267
268=item * Generic
269
270C<Log::Contextual> is an interface for all major loggers. If you log through
271C<Log::Contextual> you will be able to swap underlying loggers later.
272
273=item * Powerful
274
39cd2f65 275C<Log::Contextual> chooses which logger to use based on L<< user defined C<CodeRef>s|/LOGGER CODEREF >>.
30d7027a 276Normally you don't need to know this, but you can take advantage of it when you
277need to later
278
279=item * Scalable
280
281If you just want to add logging to your extremely basic application, start with
282L<Log::Contextual::SimpleLogger> and then as your needs grow you can switch to
283L<Log::Dispatchouli> or L<Log::Dispatch> or L<Log::Log4perl> or whatever else.
284
285=back
286
287This module is a simple interface to extensible logging. It exists to
288abstract your logging interface so that logging is as painless as possible,
289while still allowing you to switch from one logger to another.
3dc9bd3c 290
30d7027a 291It is bundled with a really basic logger, L<Log::Contextual::SimpleLogger>,
292but in general you should use a real logger instead of that. For something
293more serious but not overly complicated, try L<Log::Dispatchouli> (see
294L</SYNOPSIS> for example.)
a2af6976 295
e36f2183 296=head1 A WORK IN PROGRESS
297
298This module is certainly not complete, but we will not break the interface
299lightly, so I would say it's safe to use in production code. The main result
300from that at this point is that doing:
301
302 use Log::Contextual;
303
304will die as we do not yet know what the defaults should be. If it turns out
305that nearly everyone uses the C<:log> tag and C<:dlog> is really rare, we'll
306probably make C<:log> the default. But only time and usage will tell.
307
308=head1 IMPORT OPTIONS
309
310See L</SETTING DEFAULT IMPORT OPTIONS> for information on setting these project
311wide.
3dc9bd3c 312
c154d18a 313=head2 -logger
314
3dc9bd3c 315When you import this module you may use C<-logger> as a shortcut for
436c4b82 316L</set_logger>, for example:
3dc9bd3c 317
318 use Log::Contextual::SimpleLogger;
9b8e24d5 319 use Log::Contextual qw( :dlog ),
320 -logger => Log::Contextual::SimpleLogger->new({ levels => [qw( debug )] });
3dc9bd3c 321
322sometimes you might want to have the logger handy for other stuff, in which
323case you might try something like the following:
324
325 my $var_log;
326 BEGIN { $var_log = VarLogger->new }
9b8e24d5 327 use Log::Contextual qw( :dlog ), -logger => $var_log;
3dc9bd3c 328
5fd26f45 329=head2 -levels
330
331The C<-levels> import option allows you to define exactly which levels your
332logger supports. So the default,
333C<< [qw(debug trace warn info error fatal)] >>, works great for
334L<Log::Log4perl>, but it doesn't support the levels for L<Log::Dispatch>. But
335supporting those levels is as easy as doing
336
337 use Log::Contextual
338 -levels => [qw( debug info notice warning error critical alert emergency )];
339
e2b4b29c 340=head2 -package_logger
341
342The C<-package_logger> import option is similar to the C<-logger> import option
44d86a53 343except C<-package_logger> sets the logger for the current package.
e2b4b29c 344
345Unlike L</-default_logger>, C<-package_logger> cannot be overridden with
346L</set_logger>.
347
348 package My::Package;
349 use Log::Contextual::SimpleLogger;
350 use Log::Contextual qw( :log ),
351 -package_logger => Log::Contextual::WarnLogger->new({
352 env_prefix => 'MY_PACKAGE'
353 });
354
355If you are interested in using this package for a module you are putting on
356CPAN we recommend L<Log::Contextual::WarnLogger> for your package logger.
357
c154d18a 358=head2 -default_logger
359
360The C<-default_logger> import option is similar to the C<-logger> import option
44d86a53 361except C<-default_logger> sets the B<default> logger for the current package.
c154d18a 362
363Basically it sets the logger to be used if C<set_logger> is never called; so
364
365 package My::Package;
366 use Log::Contextual::SimpleLogger;
367 use Log::Contextual qw( :log ),
368 -default_logger => Log::Contextual::WarnLogger->new({
ae59bbe3 369 env_prefix => 'MY_PACKAGE'
c154d18a 370 });
371
e36f2183 372=head1 SETTING DEFAULT IMPORT OPTIONS
3dc9bd3c 373
e36f2183 374Eventually you will get tired of writing the following in every single one of
375your packages:
3dc9bd3c 376
e36f2183 377 use Log::Log4perl;
378 use Log::Log4perl ':easy';
379 BEGIN { Log::Log4perl->easy_init($DEBUG) }
3dc9bd3c 380
e36f2183 381 use Log::Contextual -logger => Log::Log4perl->get_logger;
382
383You can set any of the import options for your whole project if you define your
384own C<Log::Contextual> subclass as follows:
385
386 package MyApp::Log::Contextual;
387
388 use base 'Log::Contextual';
389
390 use Log::Log4perl ':easy';
391 Log::Log4perl->easy_init($DEBUG)
392
2b40dee5 393 sub arg_default_logger { $_[1] || Log::Log4perl->get_logger }
e36f2183 394 sub arg_levels { [qw(debug trace warn info error fatal custom_level)] }
e06303cd 395 sub default_import { ':log' }
e36f2183 396
2b40dee5 397 # or maybe instead of default_logger
e36f2183 398 sub arg_package_logger { $_[1] }
e36f2183 399
2b40dee5 400 # and almost definitely not this, which is only here for completeness
401 sub arg_logger { $_[1] }
e36f2183 402
2b40dee5 403Note the C<< $_[1] || >> in C<arg_default_logger>. All of these methods are
404passed the values passed in from the arguments to the subclass, so you can
405either throw them away, honor them, die on usage, or whatever. To be clear,
406if you define your subclass, and someone uses it as follows:
e36f2183 407
2b40dee5 408 use MyApp::Log::Contextual -default_logger => $foo,
409 -levels => [qw(bar baz biff)];
410
411Your C<arg_default_logger> method will get C<$foo> and your C<arg_levels>
e36f2183 412will get C<[qw(bar baz biff)]>;
2daff231 413
e06303cd 414Additionally, the C<default_import> method is what happens if a user tries to
415use your subclass with no arguments. The default just dies, but if you'd like
416to change the default to import a tag merely return the tags you'd like to
417import. So the following will all work:
418
419 sub default_import { ':log' }
420
421 sub default_import { ':dlog' }
422
423 sub default_import { qw(:dlog :log ) }
424
436c4b82 425See L<Log::Contextual::Easy::Default> for an example of a subclass of
426C<Log::Contextual> that makes use of default import options.
427
2daff231 428=head1 FUNCTIONS
429
430=head2 set_logger
431
432 my $logger = WarnLogger->new;
21431192 433 set_logger $logger;
434
27141a7a 435Arguments: L</LOGGER CODEREF>
2daff231 436
21431192 437C<set_logger> will just set the current logger to whatever you pass it. It
438expects a C<CodeRef>, but if you pass it something else it will wrap it in a
06e908c3 439C<CodeRef> for you. C<set_logger> is really meant only to be called from a
440top-level script. To avoid foot-shooting the function will warn if you call it
441more than once.
2daff231 442
443=head2 with_logger
444
445 my $logger = WarnLogger->new;
21431192 446 with_logger $logger => sub {
2daff231 447 if (1 == 0) {
448 log_fatal { 'Non Logical Universe Detected' };
449 } else {
450 log_info { 'All is good' };
451 }
80c3e48b 452 };
2daff231 453
27141a7a 454Arguments: L</LOGGER CODEREF>, C<CodeRef $to_execute>
2daff231 455
21431192 456C<with_logger> sets the logger for the scope of the C<CodeRef> C<$to_execute>.
0e13e261 457As with L</set_logger>, C<with_logger> will wrap C<$returning_logger> with a
21431192 458C<CodeRef> if needed.
2daff231 459
21431192 460=head2 log_$level
2daff231 461
0e13e261 462Import Tag: C<:log>
3dc9bd3c 463
0e13e261 464Arguments: C<CodeRef $returning_message, @args>
2daff231 465
a4d67519 466C<log_$level> functions all work the same except that a different method
21431192 467is called on the underlying C<$logger> object. The basic pattern is:
2daff231 468
0e13e261 469 sub log_$level (&@) {
21431192 470 if ($logger->is_$level) {
0e13e261 471 $logger->$level(shift->(@_));
21431192 472 }
0e13e261 473 @_
21431192 474 }
2daff231 475
0e13e261 476Note that the function returns it's arguments. This can be used in a number of
477ways, but often it's convenient just for partial inspection of passthrough data
478
479 my @friends = log_trace {
480 'friends list being generated, data from first friend: ' .
481 Dumper($_[0]->TO_JSON)
482 } generate_friend_list();
483
484If you want complete inspection of passthrough data, take a look at the
485L</Dlog_$level> functions.
486
a4d67519 487Which functions are exported depends on what was passed to L</-levels>. The
488default (no C<-levels> option passed) would export:
2daff231 489
a4d67519 490=over 2
2daff231 491
a4d67519 492=item log_trace
2daff231 493
a4d67519 494=item log_debug
2daff231 495
a4d67519 496=item log_info
2daff231 497
a4d67519 498=item log_warn
2daff231 499
a4d67519 500=item log_error
2daff231 501
a4d67519 502=item log_fatal
2daff231 503
a4d67519 504=back
2daff231 505
0e13e261 506=head2 logS_$level
507
508Import Tag: C<:log>
509
510Arguments: C<CodeRef $returning_message, Item $arg>
511
512This is really just a special case of the L</log_$level> functions. It forces
513scalar context when that is what you need. Other than that it works exactly
514same:
515
516 my $friend = logS_trace {
517 'I only have one friend: ' . Dumper($_[0]->TO_JSON)
518 } friend();
519
520See also: L</DlogS_$level>.
521
21431192 522=head2 Dlog_$level
523
0e13e261 524Import Tag: C<:dlog>
3dc9bd3c 525
0e13e261 526Arguments: C<CodeRef $returning_message, @args>
2daff231 527
0e13e261 528All of the following six functions work the same as their L</log_$level>
9b8e24d5 529brethren, except they return what is passed into them and put the stringified
21431192 530(with L<Data::Dumper::Concise>) version of their args into C<$_>. This means
531you can do cool things like the following:
532
533 my @nicks = Dlog_debug { "names: $_" } map $_->value, $frew->names->all;
534
535and the output might look something like:
536
537 names: "fREW"
538 "fRIOUX"
539 "fROOH"
540 "fRUE"
541 "fiSMBoC"
542
a4d67519 543Which functions are exported depends on what was passed to L</-levels>. The
544default (no C<-levels> option passed) would export:
21431192 545
a4d67519 546=over 2
21431192 547
a4d67519 548=item Dlog_trace
21431192 549
a4d67519 550=item Dlog_debug
21431192 551
a4d67519 552=item Dlog_info
21431192 553
a4d67519 554=item Dlog_warn
21431192 555
a4d67519 556=item Dlog_error
2daff231 557
a4d67519 558=item Dlog_fatal
2daff231 559
a4d67519 560=back
2daff231 561
83b33eb5 562=head2 DlogS_$level
563
0e13e261 564Import Tag: C<:dlog>
3dc9bd3c 565
0e13e261 566Arguments: C<CodeRef $returning_message, Item $arg>
83b33eb5 567
0e13e261 568Like L</logS_$level>, these functions are a special case of L</Dlog_$level>.
569They only take a single scalar after the C<$returning_message> instead of
570slurping up (and also setting C<wantarray>) all the C<@args>
83b33eb5 571
572 my $pals_rs = DlogS_debug { "pals resultset: $_" }
573 $schema->resultset('Pals')->search({ perlers => 1 });
574
27141a7a 575=head1 LOGGER CODEREF
576
577Anywhere a logger object can be passed, a coderef is accepted. This is so
578that the user can use different logger objects based on runtime information.
579The logger coderef is passed the package of the caller the caller level the
580coderef needs to use if it wants more caller information. The latter is in
581a hashref to allow for more options in the future.
582
37a8266a 583Here is a basic example of a logger that exploits C<caller> to reproduce the
584output of C<warn> with a logger:
585
586 my @caller_info;
587 my $var_log = Log::Contextual::SimpleLogger->new({
588 levels => [qw(trace debug info warn error fatal)],
589 coderef => sub { chomp($_[0]); warn "$_[0] at $caller_info[1] line $caller_info[2].\n" }
590 });
591 my $warn_faker = sub {
592 my ($package, $args) = @_;
593 @caller_info = caller($args->{caller_level});
594 $var_log
595 };
596 set_logger($warn_faker);
597 log_debug { 'test' };
598
27141a7a 599The following is an example that uses the information passed to the logger
600coderef. It sets the global logger to C<$l3>, the logger for the C<A1>
601package to C<$l1>, except the C<lol> method in C<A1> which uses the C<$l2>
602logger and lastly the logger for the C<A2> package to C<$l2>.
603
37a8266a 604Note that it increases the caller level as it dispatches based on where
605the caller of the log function, not the log function itself.
606
27141a7a 607 my $complex_dispatcher = do {
608
609 my $l1 = ...;
610 my $l2 = ...;
611 my $l3 = ...;
612
613 my %registry = (
614 -logger => $l3,
615 A1 => {
616 -logger => $l1,
617 lol => $l2,
618 },
619 A2 => { -logger => $l2 },
620 );
621
622 sub {
623 my ( $package, $info ) = @_;
624
625 my $logger = $registry{'-logger'};
626 if (my $r = $registry{$package}) {
627 $logger = $r->{'-logger'} if $r->{'-logger'};
37a8266a 628 my (undef, undef, undef, $sub) = caller($info->{caller_level} + 1);
27141a7a 629 $sub =~ s/^\Q$package\E:://g;
630 $logger = $r->{$sub} if $r->{$sub};
631 }
632 return $logger;
633 }
634 };
635
636 set_logger $complex_dispatcher;
637
3dc9bd3c 638=head1 LOGGER INTERFACE
639
640Because this module is ultimately pretty looking glue (glittery?) with the
641awesome benefit of the Contextual part, users will often want to make their
642favorite logger work with it. The following are the methods that should be
643implemented in the logger:
644
645 is_trace
646 is_debug
647 is_info
648 is_warn
649 is_error
650 is_fatal
651 trace
652 debug
653 info
654 warn
655 error
656 fatal
657
658The first six merely need to return true if that level is enabled. The latter
659six take the results of whatever the user returned from their coderef and log
660them. For a basic example see L<Log::Contextual::SimpleLogger>.
661
eab2ca3c 662=head1 LOG ROUTING
663
a5454e75 664In between the loggers and the log functions is a log router that is responsible for
eab2ca3c 665finding a logger to handle the log event and passing the log information to the
a5454e75 666logger. This relationship is described in the documentation for C<Log::Contextual::Role::Router>.
eab2ca3c 667
a5454e75 668C<Log::Contextual> and packages that extend it will by default share a router singleton that
669implements the with_logger() and set_logger() functions and also respects the -logger,
670-package_logger, and -default_logger import options with their associated default value
671functions. The router singleton is available as the return value of the router() function. Users
672of Log::Contextual may overload router() to return instances of custom log routers that
673could for example work with loggers that use a different interface.
eab2ca3c 674
a5454e75 675=head1 AUTHOR
2daff231 676
677frew - Arthur Axel "fREW" Schmidt <frioux@gmail.com>
678
a5454e75 679=head1 CONTRIBUTORS
680
436c4b82 681=encoding utf8
682
eab2ca3c 683triddle - Tyler Riddle <t.riddle@shadowcat.co.uk>
684
436c4b82 685voj - Jakob Voß <voss@gbv.de>
686
2daff231 687=head1 DESIGNER
688
689mst - Matt S. Trout <mst@shadowcat.co.uk>
690
691=head1 COPYRIGHT
692
a6e29e27 693Copyright (c) 2012 the Log::Contextual L</AUTHOR> and L</DESIGNER> as listed
2daff231 694above.
695
696=head1 LICENSE
697
698This library is free software and may be distributed under the same terms as
699Perl 5 itself.
700
701=cut
702