The document describes using Log::Minimal to log messages with timestamps, severity levels, and stack traces. Log::Minimal provides functions like debugf(), infof(), warnf() that log messages, and configuration options like AUTODUMP and PRINT to customize the output format. It can be used to log messages from multi-threaded or distributed applications.
21. sub logf {
my ($level,$message) = @_;
my ($pkg,$file,$line) = caller;
my @time = localtime;
warn sprintf "%04d-%02d-%02dT%02d:%02d:%02d
[%s] %s at %s line %d.n",
$time[5]+1900, $time[4]+1, @time[3,2,1,0],
$level, $message,
$file, $line;
}
logf(“WARN”,”timeout”);
logf(“INFO”,”foo bar”);
2011-10-05T09:41:30 [WARN] timeout at test.pl line 10.
2011-10-05T09:41:30 [INFO] foo bar at test.pl line 11.
29. use Log::Minimal;
debugf(‘blah blah blah’); #
local $ENV{LM_DEBUG} = 1;
debugf(‘blah blah blah’); #
2011-10-05T09:41:30 [DEBUG] blah.. at test.pl line 11.
30. #
local $Log::Minimal::PRINT = sub {
my ( $time, $type, $message, $trace) = @_;
warn(“$time [$type] $message $tracen”);
};
#
open( my $fh, ">>", "app.log");
local $Log::Minimal::PRINT = sub {
my ( $time, $type, $msg, $tr, $r_msg ) = @_;
print $fh “$time [$type] $r_msg $trn”;
};
31. #
local $Log::Minimal::AUTODUMP = 1;
warnf(“response => %s”,$res);
2011-05-11T15:56:14 [WARN] response => [200,
['Content-Type','text/plain'],['OK']] at ..
#
local $Log::Minimal::COLOR = 1;
warnf(“hirose31”);
2011-05-11T15:56:14 [WARN] hirose31 at ..
32.
33.
34.
35.
36.
37. use Log::Minimal;
use Plack::Builder;
builder {
enable "Log::Minimal", autodump => 1;
sub {
my $env = shift;
warnf("warn");
debugf("debug");
...
}
};
$ plackup -a demo.psgi
2011-05-11T16:32:24 [WARN] [/foo/bar/baz] warn at /tmp/
demo.psgi line 8
2011-05-11T16:32:24 [DEBUG] [/foo/bar/baz] debug at /tmp/
demo.psgi line 9
38. use Log::Minimal;
use Parallel::Prefork;
my $pm = Parallel::Prefork->new();
while ( $pm->signal_received ne 'TERM' ) {
$pm->start(sub {
local $Log::Minimal::AUTODUMP = 1;
local $Log::Minimal::COLOR = 1;
while (1) {
my $job = $queue->dequeue;
local $Log::Minimal::PRINT = sub {
my ( $time, $type, $message, $trace) = @_;
warn(“$$ [“,$job->name,”] [$type] $message $trace”);
};
...
}
});
}
39.
40.
41.
42.
43.
44. SELECT * FROM entries
WHERE created_at >= '2011-10-05 00:00:00'
AND created_at < '2011-10-06 00:00:00'
AND status != 0;
Data::Entry->search({
-and => [
created_at => {'>=','2011-10-05 00:00:00' },
created_at => {'<','2011-10-06 00:00:00' },
],
status => { '!=', 0 }
});
45. SELECT * FROM entries
WHERE created_at >= '2011-10-05 00:00:00'
AND created_at < '2011-10-06 00:00:00'
AND status != 0;
Data::Entry->search({
-and => [
created_at => {'>=','2011-10-05 00:00:00' },
created_at => {'<','2011-10-06 00:00:00' },
],
status => { '!=', 0 }
});
46. SELECT * FROM entries
WHERE created_at >= '2011-10-05 00:00:00'
AND created_at < '2011-10-06 00:00:00'
AND status != 0;
Data::Entry->search({
-and => [
created_at => {'>=','2011-10-05 00:00:00' },
created_at => {'<','2011-10-06 00:00:00' },
],
status => { '!=', 0 }
});
53. my $builder = SQL::Maker->new(
driver => 'mysql',
);
my $dbh = DBIx::Sunny->connect(...);
my ($sql, @binds) = $builder->select(
'user',
['*'],
{name => 'john'},
{order_by => 'user_id DESC'}
);
my $rows = $dbh->select_row($sql,@binds);
54.
55. my $dbh = DBI->connect($dsn,$user,$pass,{...});
while ( my $job = $queue->dequeue ) {
....
}
my $DBH;
sub get_dbh {
$DBH ||= DBI->connect($dsn,$user,$pass,{...});
$DBH;
}
while ( my $job = $queue->dequeue ) {
my $dbh = get_dbh();
....
}
sub get_dbh {
DBI->connect_cached($dsn,$user,$pass,{...});
}
while ( my $job = $queue->dequeue ) {
my $dbh = get_dbh();
....
}
56. my $dbh = DBI->connect($dsn,$user,$pass,{...});
while ( my $job = $queue->dequeue ) {
....
}
my $DBH;
sub get_dbh {
$DBH ||= DBI->connect($dsn,$user,$pass,{...});
$DBH;
}
while ( my $job = $queue->dequeue ) {
my $dbh = get_dbh();
....
}
sub get_dbh {
DBI->connect_cached($dsn,$user,$pass,{...});
}
while ( my $job = $queue->dequeue ) {
my $dbh = get_dbh();
....
}
62. sub get_dbh {
my $dsn = shift
my $cache = scope_container($dsn);
reutrn $cache if $cache;
my $dbh = DBIx:Sunny->connect($dsn,$user,$pass);
scope_container($dsn, $dbh);
return $dbh;
}
while ( my $job = $queue->dequeue ) {
my $sc = start_scope_container();
my $dbh = get_dbh(); #new connection
my $dbh2 = get_dbh(); #cached
..
# disconnect
}
63. use Scope::Container;
use Scope::Container::DBI;
sub get_dbh {
Scope::Container::DBI->connect($dsn,$user,$pass,{}):
}
for my $id (1..$max) {
my $sc = start_scope_container();
get_dbh()->do(...); #new connection
get_dbh()->select_row(...); #cache
undef $sc; #
}
64. # DBI
local $Scope::Container::DBI::DBI_CLASS = “Amon2::DBI”;
my $dbh = Scope::Container::DBI->connect(
$dsn,$user,$pass,{});
# slave 1
my $dbh = Scope::Container::DBI->connect(
[$dsn1,$user,$pass,{}],
[$dsn2,$user,$pass,{}],
[$dsn3,$user,$pass,{}],
);
65.
66.
67.
68.
69.
70. use Plack::Builder;
builder {
enable “Scope::Container”;
$app;
};
# Plack::Middleware::Scope::Container
sub call {
my ( $self, $env) = @_;
my $container = start_scope_container();
$self->app->($env);
}
105. $ curl http://localhost:5000/___server-status
Uptime: 1318372692
BusyWorkers: 3
IdleWorkers: 27
--
pid status remote_addr host method uri protocol
1522 A 127.0.0.1 localhost:5000 GET /___server-status HTTP/1.1
1523 _ 192.168.67.3 192.168.67.4:5000 GET /foo/bar HTTP/1.0
1526 _ 192.168.67.5 192.168.67.4:5000 GET /foo/bar HTTP/1.0
...
106. use Parallel::Prefork;
use Parallel::Scoreboard;
my $sb = Parallel::Scoreboard->new(
base_dir => ‘/var/run/example_worker’ );
my $pm = Parallel::Prefork->new({...});
while ( $pm->signal_received !~ m!^(?:TERM|INT)$! ) {
$pm->start(sub{
$sb->update('.');
while(1) {
my $job = $queue->dequeue;
$sb->update('A');
#work work work
$sb->update('.');
}
});
}
107. use Parallel::Prefork;
use Parallel::Scoreboard;
my $sb = Parallel::Scoreboard->new(
base_dir => ‘/var/run/example_worker’ );
my $pm = Parallel::Prefork->new({...});
while ( $pm->signal_received !~ m!^(?:TERM|INT)$! ) {
$pm->start(sub{ idle
$sb->update('.');
while(1) {
my $job = $queue->dequeue;
$sb->update('A');
#work work work busy
$sb->update('.');
}
}); idle
}
108. # scoreboard.psgi
my $sb = Parallel::Scoreboard->new(
base_dir => ‘/var/run/example_worker’ );
sub {
my $env = shift;
my $stats = $scoreboard->read_all();
my $busy = 0;
my $idle = 0;
for my $pid ( sort { $a <=> $b } keys %$stats) {
if ( $stats->{$pid} =~ m!^A! ) {
$busy++;
} else { busy
$idle++;
}
}
return [200,['Content-Type'=>'plain/text'],
["BusyWorkers: $busynIdleWorkers: $idle"]];
};