Log-Fast-v2.0.1/0000755000175000017500000000000013260730541013557 5ustar powermanpowermanLog-Fast-v2.0.1/Changes0000644000175000017500000000137713260730541015062 0ustar powermanpowermanRevision history for Log-Fast v2.0.1 2018-04-03 19:52:46 EEST - Reformat doc. v2.0.0 2016-02-17 22:34:31 EET - Switch to Dist::Milla. 1.0.6 2013-10-03 17:06:57 EEST - Remove MYMETA.* 1.0.5 2012-05-22 04:50:09 EEST [INCOMPATIBLE] - fixed: level() and ident() now return previous value instead of current. 1.0.4 2012-05-13 06:01:33 EEST - Fix requirements. 1.0.3 2010-12-03 14:39:54 EET - fixed t/raise.t on platforms without AF_UNIX - fixed t/syslog.t for mday < 10 1.0.2 2010-11-18 21:38:24 EET - use Sys::Syslog::_PATH_LOG() for default {path} - fixed t/raise.t on platforms without /dev/log - fixed t/syslog.t on Win 1.0.1 2010-11-18 07:46:54 EET - require perl 5.8 - added t/syslog.t 1.0.0 2010-11-17 22:36:01 EET - Initial release. Log-Fast-v2.0.1/Build.PL0000644000175000017500000000025613260730541015056 0ustar powermanpowerman# This Build.PL for Log-Fast was generated by Dist::Zilla::Plugin::ModuleBuildTiny 0.015. use strict; use warnings; use 5.010001; use Module::Build::Tiny 0.034; Build_PL(); Log-Fast-v2.0.1/lib/0000755000175000017500000000000013260730541014325 5ustar powermanpowermanLog-Fast-v2.0.1/lib/Log/0000755000175000017500000000000013260730541015046 5ustar powermanpowermanLog-Fast-v2.0.1/lib/Log/Fast.pm0000644000175000017500000004637213260730541016315 0ustar powermanpowerman# Implemented optimizations: # * log-method's (ERR(), WARN(), etc.) implementation generated # individually for each log-object (depending on it configuration) # to include only minimum necessary code to do it work # - each time log-object configuration changes (by calling config()) # log-method's implementation re-generated to comply new configuration # - different log-objects may have different configuration and so will # need different implementation for same log-methods - so we have to # use unique package/class for each log-object (with class names looks # like 'Log::Fast::_12345678') - these classes will implement only # log-methods and inherit everything else from parent class (Log::Fast) # * implementation for log-methods inactive on current log level replaced # by empty 'sub{}' # - each time log level changes (by calling config() or level()) # implementation of all log-methods updated according to current # log level and set either to real implementation or empty 'sub{}' # * if prefixes %D and/or %T are used, then cache will be used to store # formatted date/time to avoid calculating it often than once per second # * when logging to syslog, packet header (which may contain: # log level, facility, timestamp, hostname, ident and pid) will be cached # (one cached header per each log level) # - if {add_timestamp} is true, then cached header will be used only for # one second and then recalculated # - if user change {ident} (by calling config() or ident()) cached # headers will be recalculated # * if log-methods will be called with single param sprintf() won't be used package Log::Fast; use 5.010001; use warnings; use strict; use utf8; use Carp; our $VERSION = 'v2.0.1'; use Scalar::Util qw( refaddr ); use Socket; use Sys::Hostname (); use Time::HiRes (); use Sys::Syslog (); # for _PATH_LOG() # from RFC3164 use constant LOG_USER => 1*8; use constant LOG_ERR => 3; use constant LOG_WARNING => 4; use constant LOG_NOTICE => 5; use constant LOG_INFO => 6; use constant LOG_DEBUG => 7; use constant PRI => { ERR => LOG_ERR, WARN => LOG_WARNING, NOTICE => LOG_NOTICE, INFO => LOG_INFO, DEBUG => LOG_DEBUG, }; use constant DEFAULTS => { level => 'DEBUG', prefix => q{}, type => 'fh', # used only when {type}='fh': fh => \*STDERR, # used only when {type}='unix': path => Sys::Syslog::_PATH_LOG() || '/dev/log', ## no critic(ProtectPrivateSubs) facility => LOG_USER, add_timestamp => 1, add_hostname => 0, hostname => Sys::Hostname::hostname(), ident => do { my $s = $0; utf8::decode($s); $s =~ s{\A.*/(?=.)}{}xms; $s }, add_pid => 1, pid => $$, }; my $GLOBAL; sub new { my ($class, $opt) = @_; $opt ||= {}; croak 'options must be HASHREF' if ref $opt ne 'HASH'; my $self = { # will also contain all keys defined in DEFAULTS constant # used only when {type}='unix': _sock => undef, # socket to {path} _header_ERR => q{}, # cached "TIMESTAMP IDENT[PID]: " _header_WARN => q{}, # --"-- _header_NOTICE => q{}, # --"-- _header_INFO => q{}, # --"-- _header_DEBUG => q{}, # --"-- _header_time => 0, # last update time for {_header_*} # used only if {prefix} contain %D or %T: _date => q{}, # cached "YYYY-MM-DD" _time => q{}, # cached "HH:MM:SS" _dt_time => 0, # last update time for {_date} and {_time} }; my $sub_class = $class . '::_' . refaddr($self); { no strict 'refs'; @{$sub_class.'::ISA'} = ( $class ); } bless $self, $sub_class; $self->config({ %{ DEFAULTS() }, %{ $opt } }); ## no critic (ProhibitCommaSeparatedStatements) return $self; } sub global { my $class = shift; $GLOBAL ||= $class->new(); return $GLOBAL; } sub config { my ($self, $opt) = @_; croak 'options must be HASHREF' if ref $opt ne 'HASH'; for my $key (keys %{ $opt }) { if (!exists DEFAULTS->{ $key }) { croak 'unknown option: '.$key; } $self->{ $key } = $opt->{ $key }; } $self->_generate_methods(); if ($self->{type} eq 'unix') { $self->_connect_unix(); $self->ident($self->{ident}); } $self->level($self->{level}); return; } sub level { my ($self, $level) = @_; my $prev_level = $self->{level}; if (defined $level) { if (!exists PRI->{$level}) { croak '{level} must be one of: '.join ', ', keys %{ PRI() }; } $self->{level} = $level; $self->_setup_level(); } return $prev_level; } sub ident { my ($self, $ident) = @_; my $prev_ident = $self->{ident}; if (defined $ident) { $self->{ident} = $ident; $self->_update_header(); } return $prev_ident; } ### Internal sub _connect_unix { my ($self) = @_; socket $self->{_sock}, AF_UNIX, SOCK_DGRAM, 0 or croak "socket: $!"; connect $self->{_sock}, sockaddr_un($self->{path}) or croak "connect: $!"; return; } sub _update_header { my ($self) = @_; my $h = q{}; if ($self->{add_timestamp}) { $self->{_header_time} = time; $h .= substr localtime $self->{_header_time}, 4, 16; ## no critic(ProhibitMagicNumbers) } if ($self->{add_hostname}) { $h .= $self->{hostname} . q{ }; } my $ident_utf8 = $self->{ident}; utf8::encode($ident_utf8); $h .= $ident_utf8; if ($self->{add_pid}) { $h .= '[' . $self->{pid} . ']'; } $h .= ': '; for my $level (keys %{ PRI() }) { $self->{'_header_'.$level} = '<' . ($self->{facility} + PRI->{$level}) . '>' . $h; } return; } sub _setup_level { my ($self) = @_; my $pkg = ref $self; for my $level (keys %{ PRI() }) { my $is_active = PRI->{$level} <= PRI->{$self->{level}}; no strict 'refs'; no warnings 'redefine'; *{$pkg.q{::}.$level} = $is_active ? \&{$pkg.q{::_}.$level} : sub {}; } return; } sub _generate_methods { ## no critic(ProhibitExcessComplexity) my ($self) = @_; my $pkg = ref $self; my %feature = map {$_=>1} $self->{prefix} =~ /%(.)/xmsg; $feature{timestamp} = $self->{type} eq 'unix' && $self->{add_timestamp}; my @pfx = split /(%.)/xms, $self->{prefix}; for (0 .. $#pfx) { utf8::encode($pfx[$_]); } for my $level (keys %{ PRI() }) { # ... begin my $code = <<'EOCODE'; sub { my $self = shift; my $msg = @_==1 ? $_[0] : sprintf shift, map {ref eq 'CODE' ? $_->() : $_} @_; utf8::encode($msg); EOCODE # ... if needed, get current time if ($feature{S}) { $code .= <<'EOCODE'; my $msec = sprintf '%.05f', Time::HiRes::time(); my $time = int $msec; EOCODE } elsif ($feature{D} || $feature{T} || $feature{timestamp}) { $code .= <<'EOCODE'; my $time = time; EOCODE } # ... if needed, update caches if ($feature{D} || $feature{T}) { $code .= <<'EOCODE'; if ($self->{_dt_time} != $time) { $self->{_dt_time} = $time; my ($sec,$min,$hour,$mday,$mon,$year) = localtime $time; $self->{_date} = sprintf '%04d-%02d-%02d', $year+1900, $mon+1, $mday; $self->{_time} = sprintf '%02d:%02d:%02d', $hour, $min, $sec; } EOCODE } if ($feature{timestamp}) { $code .= <<'EOCODE'; if ($self->{_header_time} != $time) { $self->_update_header(); } EOCODE } # ... calculate prefix $code .= <<'EOCODE'; my $prefix = q{} EOCODE for my $pfx (@pfx) { if ($pfx eq q{%L}) { ## no critic(ProhibitCascadingIfElse) $code .= <<"EOCODE" . "\Q$level\E" EOCODE } elsif ($pfx eq q{%S}) { $code .= <<'EOCODE' . $msec EOCODE } elsif ($pfx eq q{%D}) { $code .= <<'EOCODE' . $self->{_date} EOCODE } elsif ($pfx eq q{%T}) { $code .= <<'EOCODE' . $self->{_time} EOCODE } elsif ($pfx eq q{%P}) { $code .= <<'EOCODE' . caller(0) EOCODE } elsif ($pfx eq q{%F}) { $code .= <<'EOCODE' . do { my $s = (caller(1))[3] || q{}; substr $s, 1+rindex $s, ':' } EOCODE } elsif ($pfx eq q{%_}) { $code .= <<'EOCODE' . do { my $n=0; 1 while caller(2 + $n++); ' ' x $n } EOCODE } elsif ($pfx eq q{%%}) { $code .= <<'EOCODE' . '%' EOCODE } else { $code .= <<"EOCODE" . "\Q$pfx\E" EOCODE } } $code .= <<'EOCODE'; ; EOCODE # ... output if ($self->{type} eq 'fh') { $code .= <<'EOCODE'; print { $self->{fh} } $prefix, $msg, "\n" or die "print() to log: $!"; EOCODE } elsif ($self->{type} eq 'unix') { $code .= <<"EOCODE"; my \$header = \$self->{_header_$level}; EOCODE $code .= <<'EOCODE'; send $self->{_sock}, $header.$prefix.$msg, 0 or do { $self->_connect_unix(); send $self->{_sock}, $header.$prefix.$msg, 0 or die "send() to syslog: $!"; }; EOCODE } else { croak '{type} should be "fh" or "unix"'; } # ... end $code .= <<'EOCODE'; } EOCODE # install generated method no strict 'refs'; no warnings 'redefine'; *{$pkg.'::_'.$level} = eval $code; ## no critic (ProhibitStringyEval) } return; } 1; # Magic true value required at end of module __END__ =encoding utf8 =head1 NAME Log::Fast - Fast and flexible logger =head1 VERSION This document describes Log::Fast version v2.0.1 =head1 SYNOPSIS use Log::Fast; $LOG = Log::Fast->global(); $LOG = Log::Fast->new({ level => 'WARN', prefix => '%D %T [%L] ', type => 'fh', fh => \*STDOUT, }); use Sys::Syslog qw( LOG_DAEMON ); $LOG->config({ prefix => '', type => 'unix', path => '/dev/log', facility => LOG_DAEMON, add_timestamp => 1, add_hostname => 1, hostname => 'somehost', ident => 'someapp', add_pid => 1, pid => $$, }); $LOG->ident('anotherapp'); $LOG->level('INFO'); $LOG->ERR('Some error'); $LOG->WARN('Some warning'); $LOG->NOTICE('user %s logged in', $user); $LOG->INFO('data loaded'); $LOG->DEBUG('user %s have %d things', $user, sub { return SlowOperation_GetAmountOfThingsFor($user); }); =head1 DESCRIPTION This is very fast logger, designed for use in applications with thousands high-level events/operations per second (like network servers with thousands clients or web spiders which download hundreds url per second). For example, on Core2Duo sending about 5000 messages to log on enabled log levels or 20000 messages on disabled log levels in I will slow down your application only by 2-3%. Comparing to some other CPAN modules, this one (in average): faster than L in about 45 times, faster than L in about 15 times, faster than L in about 7 times, and slower than L in about 2 times. =head2 FEATURES =over =item * Global and local logger objects =item * Output to any open filehandle or local syslog =item * 5 log levels: ERR, WARN, NOTICE, INFO, DEBUG =item * Configurable prefix (log level, date/time, caller function name) =item * sprintf() support =item * Unicode support (UTF8) =item * Can avoid calculating log message content on disabled log levels =back =head1 INTERFACE =head2 global $LOG = Log::Fast->global(); When called first time will create global log object using L (you can reconfigure it using C later). Global log object is useful if your application consists of several independent modules which should share same logging options configured outside of these modules. In this case all these modules should use same C log object instead of creating C independent log objects in each module. Return global log object. =head2 new $LOG = Log::Fast->new(); $LOG = Log::Fast->new( \%opt ); Create new log object, configured using L and user-provided options, if any. Return created log object. =head2 config $LOG->config( \%opt ); Reconfigure log object. Any options (see L) can be changed at any time, including changing output B<{type}> or setting options useless with current output type (new values for these options will be used later, if output type will be changed). If you need to change only log B<{level}> or syslog's B<{ident}> you should use C or C methods because they are much faster than more general C. Return nothing. Throw exception if unable to connect to syslog. =head2 level $level = $LOG->level(); $level = $LOG->level( $new_level ); If B<$new_level> given will change current log level. This is same as call C<< config({ level=>$new_level }) >> but much faster. Return previous log level. =head2 ident $ident = $LOG->ident(); $ident = $LOG->ident( $new_ident ); If B<$new_ident> given will change current syslog's ident. This is same as call C<< config({ ident=>$new_ident }) >> but much faster. Return previous syslog's ident. =head2 ERR =head2 WARN =head2 NOTICE =head2 INFO =head2 DEBUG $LOG->ERR( $message ) $LOG->ERR( $format, @list ) $LOG->WARN( $message ) $LOG->WARN( $format, @list ) $LOG->NOTICE( $message ) $LOG->NOTICE( $format, @list ) $LOG->INFO( $message ) $LOG->INFO( $format, @list ) $LOG->DEBUG( $message ) $LOG->DEBUG( $format, @list ) Output B<$message> to log using different log levels. If B<$format, @list> used instead of B<$message>, then use C to calculate log message. If B<@list> will contain CODEREF, they will be called (in LIST context) and returned values will be placed inside B<@list> inplace of CODEREF. This can be used to avoid calculating log message (or it part) on disabled log levels - these CODEREF will be executed only on enabled log levels. Example available in L. If B<$message> or items in B<@list> will be Unicode strings, they will be converted to UTF8 before sending to log. Return nothing. Throw exception if fail to write message to log. =head1 OPTIONS Defaults for all options are: level => 'DEBUG', prefix => q{}, type => 'fh', fh => \*STDERR, # these will be used if you will call config({ type=>'unix' }) path => Sys::Syslog::_PATH_LOG() || '/dev/log', facility => LOG_USER, add_timestamp => 1, add_hostname => 0, hostname => Sys::Hostname::hostname(), ident => ..., # calculated from $0 add_pid => 1, pid => $$, =over =item level Current log level. Possible values are: C<'ERR'>, C<'WARN'>, C<'NOTICE'>, C<'INFO'>, C<'DEBUG'>. Only messages on current or higher levels will be sent to log. =item prefix String, which will be output at beginning of each log message. May contain these placeholders: %L - log level of current message %S - hi-resolution time (seconds.microseconds) %D - current date in format YYYY-MM-DD %T - current time in format HH:MM:SS %P - caller's function package ('main' or 'My::Module') %F - caller's function name %_ - X spaces, where X is current stack depth %% - % character Example output with prefix C<'%D %T [%L]%_%P::%F() '>: 2010-11-17 18:06:20 [INFO] main::() something from main script 2010-11-17 18:06:53 [INFO] main::a() something from a 2010-11-17 18:09:09 [INFO] main::b2() something from b1->b2 2010-11-17 18:06:56 [INFO] main::c() something from c If it will be Unicode string, it will be converted to UTF8. =item type Output type. Possible values are: C<'fh'> (output to any already open filehandle) and C<'unix'> (output to syslog using UNIX socket). When B<{type}> set to C<'fh'> you have to also set B<{fh}> to any open filehandle (like C<\*STDERR>). When B<{type}> set to C<'unix'> you have to also set B<{path}> to path to existing UNIX socket (typically it's C<'/dev/log'>). Luckily, default values for both B<{fh}> and B<{path}> are already provided, so usually it's enough to just set B<{type}>. =item fh File handle to write log messages if B<{type}> set to C<'fh'>. =item path Syslog's UNIX socket path to write log messages if B<{type}> set to C<'unix'>. =item facility Syslog's facility (see L for a list of well-known facilities). This module doesn't export any constants, so if you wanna change it from default LOG_USER value, you should import facility constants from L module. Example available in L. =item add_timestamp If TRUE will include timestamp in syslog messages. =item add_hostname If TRUE will include hostname in syslog messages. =item hostname Host name which will be included in syslog messages if B<{add_hostname}> is TRUE. =item ident Syslog's ident (application name) field. If it will be Unicode string, it will be converted to UTF8. Using non-ASCII ALPHANUMERIC ident isn't allowed by RFC, but usually works. =item add_pid If TRUE will include PID in syslog messages. =item pid PID which will be included in syslog messages if B<{add_pid}> is TRUE. =back =head1 SPEED HINTS Empty prefix is fastest. Prefixes C<%L>, C<%P> and C<%%> are fast enough, C<%D> and C<%T> has average speed, C<%S>, C<%F> and C<%_> are slowest. Output to file is about 4 times faster than to syslog. Calling log with single parameter is faster than with many parameters (because in second case sprintf() have to be used). =head1 SUPPORT =head2 Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at L. You will be notified automatically of any progress on your issue. =head2 Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. Feel free to fork the repository and submit pull requests. L git clone https://github.com/powerman/perl-Log-Fast.git =head2 Resources =over =item * MetaCPAN Search L =item * CPAN Ratings L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Testers Matrix L =item * CPANTS: A CPAN Testing Service (Kwalitee) L =back =head1 AUTHOR Alex Efros Epowerman@cpan.orgE =head1 COPYRIGHT AND LICENSE This software is Copyright (c) 2010- by Alex Efros Epowerman@cpan.orgE. This is free software, licensed under: The MIT (X11) License =cut Log-Fast-v2.0.1/t/0000755000175000017500000000000013260730541014022 5ustar powermanpowermanLog-Fast-v2.0.1/t/author-perlcritic.t0000644000175000017500000000063313260730541017651 0ustar powermanpowerman#!/usr/bin/perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } use strict; use warnings; use Test::More; eval { require Test::Perl::Critic; }; plan(skip_all=>'Test::Perl::Critic required to criticise code') if $@; Test::Perl::Critic->import( -verbose => 9, # verbose 6 will hide rule name ); all_critic_ok(); Log-Fast-v2.0.1/t/raise.t0000644000175000017500000000304213260730541015311 0ustar powermanpowermanuse warnings; use strict; use Test::More; use Test::Exception; use Log::Fast; plan tests => 17; my $LOG = Log::Fast->global(); lives_ok { Log::Fast->new({}) }; lives_ok { Log::Fast->new() }; throws_ok { Log::Fast->new([]) } qr/HASHREF/; lives_ok { $LOG->config({}) }; throws_ok { $LOG->config() } qr/HASHREF/; throws_ok { $LOG->config([]) } qr/HASHREF/; lives_ok { $LOG->config({prefix=>q{}}) }; throws_ok { $LOG->config({preFix=>q{}}) } qr/unknown option/; throws_ok { $LOG->config({level=>'InFo'}) } qr/{level}/; lives_ok { $LOG->config({level=>'INFO'}) }; throws_ok { $LOG->level('InFo') } qr/{level}/; lives_ok { $LOG->level('INFO') }; SKIP: { eval { use File::Temp qw( tempfile ); use Socket; (undef, my $tempfile) = tempfile(); unlink $tempfile; socket my $sock, AF_UNIX, SOCK_DGRAM, 0 or die "socket: $!"; connect $sock, sockaddr_un($tempfile) or die "connect: $!"; unlink $tempfile; }; skip 'no UNIX sockets available', 2 if $@; SKIP: { use Sys::Syslog (); my $path = Sys::Syslog::_PATH_LOG() || '/dev/log'; skip 'unable to detect syslog socket', 1 if !-S $path; lives_ok { $LOG->config({type=>'unix',path=>$path}) }; } throws_ok { $LOG->config({type=>'unix',path=>'nosuch'}) } qr/connect:/; } throws_ok { $LOG->config({type=>'Fh',fh=>\*NOSUCH}) } qr/{type}/; lives_ok { $LOG->config({type=>'fh',fh=>\*NOSUCH}) }; throws_ok { $SIG{__WARN__}=sub{}; $LOG->ERR('test') } qr/print/; Log-Fast-v2.0.1/t/00.load.t0000644000175000017500000000027313260730541015346 0ustar powermanpowermanuse warnings; use strict; use Test::More tests => 1; BEGIN { use_ok( 'Log::Fast' ) or BAIL_OUT('unable to load module') } diag( "Testing Log::Fast $Log::Fast::VERSION, Perl $], $^X" ); Log-Fast-v2.0.1/t/a.pm0000644000175000017500000000027313260730541014602 0ustar powermanpowermanpackage a; use warnings; use strict; my $LOG = Log::Fast->global(); sub A { $LOG->ERR('in a::A'); } sub call { my $func = shift; no strict 'refs'; $func->(@_); } 1; Log-Fast-v2.0.1/t/unicode.t0000644000175000017500000000150213260730541015633 0ustar powermanpowermanuse warnings; use strict; use Test::More; use Test::Exception; use Log::Fast; plan tests => 5; my $LOG = Log::Fast->new(); my $BUF = q{}; open my $fh, '>', \$BUF; $LOG->config({ fh=>$fh }); sub _log() { seek $fh, 0, 0; substr $BUF, 0, length $BUF, q{} } use utf8; $SIG{__WARN__} = sub { die $_[0] if $_[0] =~ /Wide char/ }; $LOG->config({ prefix => 'Уровень %L: ' }); lives_ok { $LOG->ERR('This is a сообщение') } 'Unicode message processed'; my $utf8 = _log(); ok !utf8::is_utf8($utf8), 'log contain bytes'; ok utf8::valid($utf8), 'the bytes form valid UTF8'; my $unicode = $utf8; ok utf8::decode($unicode), 'decoded to Unicode'; is $unicode, "Уровень ERR: This is a сообщение\n", 'message content match'; Log-Fast-v2.0.1/t/syslog.t0000644000175000017500000000701213260730541015527 0ustar powermanpowermanuse warnings; use strict; use Test::More; use Socket; use Log::Fast; if ($^O =~ /Win/xms) { plan skip_all => 'not availaible on Windows'; } else { plan tests => 19; } use constant PATH => "/tmp/log.$$.sock"; socket my $Srv, AF_UNIX, SOCK_DGRAM, 0 or die "socket: $!"; bind $Srv, sockaddr_un(PATH) or die "bind: $!"; END { unlink PATH } sub _log() { sysread $Srv, my $buf, 8192 or die "sysread: $!"; return $buf } our $LOG = Log::Fast->new({ type => 'unix', path => PATH, }); my $H = qr/\A<11>\w\w\w [ \d]\d \d\d:\d\d:\d\d syslog\.t\[$$\]:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'defaults'; $LOG->config({ add_timestamp => 0, add_hostname => 0, add_pid => 0, }); $H = qr/\A<11>syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'minimum features'; $H = qr/\A<12>syslog\.t:/ms; $LOG->WARN('msg'); like _log, qr/$H msg\z/ms, 'levels: WARN'; $H = qr/\A<13>syslog\.t:/ms; $LOG->NOTICE('msg'); like _log, qr/$H msg\z/ms, 'levels: NOTICE'; $H = qr/\A<14>syslog\.t:/ms; $LOG->INFO('msg'); like _log, qr/$H msg\z/ms, 'levels: INFO'; $H = qr/\A<15>syslog\.t:/ms; $LOG->DEBUG('msg'); like _log, qr/$H msg\z/ms, 'levels: DEBUG'; use Sys::Syslog qw( LOG_DAEMON LOG_AUTH LOG_USER ); $LOG->config({ facility => LOG_DAEMON }); $H = qr/\A<27>syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'facilities: daemon'; $LOG->config({ facility => LOG_AUTH }); $H = qr/\A<35>syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'facilities: auth'; $LOG->config({ facility => LOG_USER }); $H = qr/\A<11>syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'facilities: user'; $LOG->config({ add_timestamp => 1 }); $H = qr/\A<11>\w\w\w [ \d]\d \d\d:\d\d:\d\d syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'feature: timestamp'; $LOG->config({ add_timestamp => 0 }); use Sys::Hostname; $LOG->config({ add_hostname => 1 }); $H = qr/\A<11>\Q${\ hostname }\E syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'feature: hostname (default)'; $LOG->config({ hostname => 'myhost' }); $H = qr/\A<11>myhost syslog\.t:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'feature: hostname (user-defined)'; $LOG->config({ add_hostname => 0 }); $LOG->ident('myapp'); $H = qr/\A<11>myapp:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'ident'; is $LOG->ident(), 'myapp', 'current ident without change'; is $LOG->ident('myapp2'), 'myapp', 'previous ident on change'; is $LOG->ident('myapp'), 'myapp2', 'previous ident on change'; $LOG->config({ add_pid => 1 }); $H = qr/\A<11>myapp\[$$\]:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'feature: pid (default)'; $LOG->config({ pid => 31337 }); $H = qr/\A<11>myapp\[31337\]:/ms; $LOG->ERR('msg'); like _log, qr/$H msg\z/ms, 'feature: pid (user-defined)'; $LOG->config({ add_pid => 0 }); $LOG->config({ prefix => '%S %D %T [%L]%_%P->%F %%', facility => LOG_DAEMON, add_timestamp => 1, add_hostname => 1, hostname => 'somehost', ident => 'тест', add_pid => 1, pid => 65535, }); $H = qr/\A<31>\w\w\w [ \d]\d \d\d:\d\d:\d\d somehost тест\[65535\]:/ms; my $P = qr/\d+\.\d{5} 20\d\d-\d\d-\d\d \d\d:\d\d:\d\d \[DEBUG\] main-> %/ms; $LOG->DEBUG('сообщение'); my $msg = _log; utf8::decode($msg); like $msg, qr/$H ${P}сообщение\z/ms, 'everything (prefix, features, unicode)'; Log-Fast-v2.0.1/t/release-distribution.t0000644000175000017500000000065613260730541020353 0ustar powermanpowerman BEGIN { unless ($ENV{RELEASE_TESTING}) { print qq{1..0 # SKIP these tests are for release candidate testing\n}; exit } } use Test::More; eval { require Test::Distribution }; plan( skip_all => 'Test::Distribution not installed' ) if $@; Test::Distribution->import( podcoveropts => { # also_private => [ # qr/^(?:IMPORT)$/, # ], # pod_from => 'MAIN PM FILE HERE', } ); Log-Fast-v2.0.1/t/prefix.t0000644000175000017500000001063613260730541015512 0ustar powermanpowermanuse warnings; use strict; use Test::More; use Log::Fast; plan tests => 40; our $LOG = Log::Fast->global(); my $BUF = q{}; open my $fh, '>', \$BUF; $LOG->config({ fh=>$fh }); sub _log() { seek $fh, 0, 0; substr $BUF, 0, length $BUF, q{} } # empty prefix $LOG->ERR('msg'); is _log, "msg\n", $LOG->{prefix}; # static prefix $LOG->config({ prefix=>'pre' }); $LOG->ERR('msg'); is _log, "premsg\n", $LOG->{prefix}; # %L - log level of current message $LOG->config({ prefix=>'%L' }); $LOG->ERR('msg'); is _log, "ERRmsg\n", $LOG->{prefix}; $LOG->WARN('msg'); is _log, "WARNmsg\n", $LOG->{prefix}; # %S - hi-resolution time (seconds.microseconds) $LOG->config({ prefix=>'%S' }); $LOG->ERR('msg'); like _log, qr/\A\d+\.\d{5}msg\n\z/xms, $LOG->{prefix}; # %D - current date in format YYYY-MM-DD $LOG->config({ prefix=>'%D' }); $LOG->ERR('msg'); like _log, qr/\A20\d\d-\d\d-\d\dmsg\n\z/xms, $LOG->{prefix}; # %T - current time in format HH:MM:SS $LOG->config({ prefix=>'%T' }); $LOG->ERR('msg'); like _log, qr/\A\d\d:\d\d:\d\dmsg\n\z/xms, $LOG->{prefix}; # %P - caller's function package ('main' or 'My::Module') $LOG->config({ prefix=>'%P' }); $LOG->ERR('msg'); is _log, "mainmsg\n", $LOG->{prefix}; # %F - caller's function name $LOG->config({ prefix=>'%F' }); $LOG->ERR('msg'); is _log, "msg\n", $LOG->{prefix}; # %_ - X spaces, where X is current stack depth $LOG->config({ prefix=>'%_' }); $LOG->ERR('msg'); is _log, " msg\n", $LOG->{prefix}; # %% - % character $LOG->config({ prefix=>'%%' }); $LOG->ERR('msg'); is _log, "%msg\n", $LOG->{prefix}; # all prefixes $LOG->config({ prefix=>'%S %D %T [%L]%_%P::%F %% ' }); $LOG->ERR('msg'); like _log, qr/\A\d+\.\d{5} 20\d\d-\d\d-\d\d \d\d:\d\d:\d\d \[ERR\] main:: % msg\n\z/ms, $LOG->{prefix}; # all prefixes, twice $LOG->config({ prefix=>'%S %D %T [%L]%_%P::%F %% 'x2 }); $LOG->ERR('msg'); like _log, qr/\A(\d+\.\d{5} 20\d\d-\d\d-\d\d \d\d:\d\d:\d\d \[ERR\] main:: % ){2}msg\n\z/ms, $LOG->{prefix}; ### # stack/package/function ### $LOG->config({ prefix=>'%_%P->%F ' }); # from main script $LOG->ERR('in script'); is _log, " main-> in script\n", 'script'; eval { $LOG->ERR('in script') }; is _log, " main->(eval) in script\n", 'script eval {}'; eval '$LOG->ERR("in script");'; is _log, " main->(eval) in script\n", 'script eval ""'; # from main::sub sub M { $LOG->ERR('in M') } M(); is _log, " main->M in M\n", 'M'; eval { M() }; is _log, " main->M in M\n", 'eval {M}'; eval 'M()'; is _log, " main->M in M\n", 'eval "M"'; sub MEB { eval { $LOG->ERR('in MEB') } }; sub MES { eval ' $LOG->ERR("in MES") ' }; MEB(); is _log, " main->(eval) in MEB\n", 'MEB'; MES(); is _log, " main->(eval) in MES\n", 'MES'; # from a::A use lib 't'; use a; a::A(); is _log, " a->A in a::A\n", 'a::A'; a::call('a::A'); is _log, " a->A in a::A\n", 'a::call->a::A'; a::call('a::call', 'a::A'); is _log, " a->A in a::A\n", 'a::call->a::call->a::A'; # from a::b::B use a::b; a::b::B(); is _log, " a::b->B in a::b::B\n", 'a::b::B'; a::b::call('a::b::B'); is _log, " a::b->B in a::b::B\n", 'a::b::call->a::b::B'; a::call('a::b::B'); is _log, " a::b->B in a::b::B\n", 'a::call->a::b::B'; a::b::call('a::call', 'a::b::B'); is _log, " a::b->B in a::b::B\n", 'a::b::call->a::call->a::b::B'; # from injected a::b::Fx sub a::b::F1 { $LOG->ERR('in a::b::F1') } *a::b::F2 = sub { $LOG->ERR('in a::b::F2') }; *a::b::F3 = eval 'sub { $LOG->ERR("in a::b::F3") };'; eval 'sub a::b::F4 { $LOG->ERR("in a::b::F4") };'; eval 'package a::b; sub F5 { $LOG->ERR("in a::b::F5") };'; package a::b; sub F6 { $LOG->ERR("in a::b::F6") }; package main; a::b::F1(); is _log, " main->F1 in a::b::F1\n", 'a::b::F1'; a::b::F2(); is _log, " main->__ANON__ in a::b::F2\n", 'a::b::F2'; a::b::F3(); is _log, " main->__ANON__ in a::b::F3\n", 'a::b::F3'; a::b::F4(); is _log, " main->F4 in a::b::F4\n", 'a::b::F4'; a::b::F5(); is _log, " a::b->F5 in a::b::F5\n", 'a::b::F5'; a::b::F6(); is _log, " a::b->F6 in a::b::F6\n", 'a::b::F6'; # from injected a::b::Fx with 1 additional stack a::call('a::b::F1'); is _log, " main->F1 in a::b::F1\n", 'a::b::F1 plus 1 stack'; a::call('a::b::F2'); is _log, " main->__ANON__ in a::b::F2\n", 'a::b::F2 plus 1 stack'; a::call('a::b::F3'); is _log, " main->__ANON__ in a::b::F3\n", 'a::b::F3 plus 1 stack'; a::call('a::b::F4'); is _log, " main->F4 in a::b::F4\n", 'a::b::F4 plus 1 stack'; a::call('a::b::F5'); is _log, " a::b->F5 in a::b::F5\n", 'a::b::F5 plus 1 stack'; a::call('a::b::F6'); is _log, " a::b->F6 in a::b::F6\n", 'a::b::F6 plus 1 stack'; Log-Fast-v2.0.1/t/level.t0000644000175000017500000000155413260730541015323 0ustar powermanpowermanuse warnings; use strict; use Test::More; use Log::Fast; plan tests => 9; my $LOG = Log::Fast->new(); my $BUF = q{}; open my $fh, '>', \$BUF; $LOG->config({ fh=>$fh }); sub _log() { seek $fh, 0, 0; substr $BUF, 0, length $BUF, q{} } sub logall { $LOG->ERR('E'); $LOG->WARN('W'); $LOG->NOTICE('N'); $LOG->INFO('I'); $LOG->DEBUG('D'); } logall(); is _log(), "E\nW\nN\nI\nD\n", '(default) DEBUG'; $LOG->level('INFO'); is $LOG->level(), 'INFO'; logall(); is _log(), "E\nW\nN\nI\n", 'INFO'; $LOG->config({ level=>'NOTICE' }); is $LOG->level(), 'NOTICE'; logall(); is _log(), "E\nW\nN\n", 'NOTICE'; $LOG->level('WARN'); logall(); is _log(), "E\nW\n", 'WARN'; $LOG->level('ERR'); logall(); is _log(), "E\n", 'ERR'; $LOG->level('DEBUG'); logall(); is _log(), "E\nW\nN\nI\nD\n", 'DEBUG'; is $LOG->level('INFO'), 'DEBUG', 'previous level on change'; Log-Fast-v2.0.1/t/author-pod-syntax.t0000644000175000017500000000045413260730541017620 0ustar powermanpowerman#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); Log-Fast-v2.0.1/t/a/0000755000175000017500000000000013260730541014242 5ustar powermanpowermanLog-Fast-v2.0.1/t/a/b.pm0000644000175000017500000000030113260730541015013 0ustar powermanpowermanpackage a::b; use warnings; use strict; my $LOG = Log::Fast->global(); sub B { $LOG->ERR('in a::b::B'); } sub call { my $func = shift; no strict 'refs'; $func->(@_); } 1; Log-Fast-v2.0.1/t/global.t0000644000175000017500000000062013260730541015445 0ustar powermanpowermanuse warnings; use strict; use Test::More; use Log::Fast; plan tests => 4; my $LOG = Log::Fast->global(); like ref $LOG, qr/\ALog::Fast::_\d+\z/, 'global created'; is $LOG, Log::Fast->global(), 'global is same'; like ref Log::Fast->new(), qr/\ALog::Fast::_\d+\z/, 'local created'; isnt $LOG, Log::Fast->new(), 'global differ from local'; Log-Fast-v2.0.1/README0000644000175000017500000002341013260730541014437 0ustar powermanpowermanNAME Log::Fast - Fast and flexible logger VERSION This document describes Log::Fast version v2.0.1 SYNOPSIS use Log::Fast; $LOG = Log::Fast->global(); $LOG = Log::Fast->new({ level => 'WARN', prefix => '%D %T [%L] ', type => 'fh', fh => \*STDOUT, }); use Sys::Syslog qw( LOG_DAEMON ); $LOG->config({ prefix => '', type => 'unix', path => '/dev/log', facility => LOG_DAEMON, add_timestamp => 1, add_hostname => 1, hostname => 'somehost', ident => 'someapp', add_pid => 1, pid => $$, }); $LOG->ident('anotherapp'); $LOG->level('INFO'); $LOG->ERR('Some error'); $LOG->WARN('Some warning'); $LOG->NOTICE('user %s logged in', $user); $LOG->INFO('data loaded'); $LOG->DEBUG('user %s have %d things', $user, sub { return SlowOperation_GetAmountOfThingsFor($user); }); DESCRIPTION This is very fast logger, designed for use in applications with thousands high-level events/operations per second (like network servers with thousands clients or web spiders which download hundreds url per second). For example, on Core2Duo sending about 5000 messages to log on enabled log levels or 20000 messages on disabled log levels in one second will slow down your application only by 2-3%. Comparing to some other CPAN modules, this one (in average): faster than Log::Dispatch in about 45 times, faster than Log::Handler in about 15 times, faster than Sys::Syslog in about 7 times, and slower than Log::Syslog::Fast in about 2 times. FEATURES * Global and local logger objects * Output to any open filehandle or local syslog * 5 log levels: ERR, WARN, NOTICE, INFO, DEBUG * Configurable prefix (log level, date/time, caller function name) * sprintf() support * Unicode support (UTF8) * Can avoid calculating log message content on disabled log levels INTERFACE global $LOG = Log::Fast->global(); When called first time will create global log object using default options (you can reconfigure it using config() later). Global log object is useful if your application consists of several independent modules which should share same logging options configured outside of these modules. In this case all these modules should use same global() log object instead of creating new() independent log objects in each module. Return global log object. new $LOG = Log::Fast->new(); $LOG = Log::Fast->new( \%opt ); Create new log object, configured using defaults and user-provided options, if any. Return created log object. config $LOG->config( \%opt ); Reconfigure log object. Any options (see "OPTIONS") can be changed at any time, including changing output {type} or setting options useless with current output type (new values for these options will be used later, if output type will be changed). If you need to change only log {level} or syslog's {ident} you should use level() or ident() methods because they are much faster than more general config(). Return nothing. Throw exception if unable to connect to syslog. level $level = $LOG->level(); $level = $LOG->level( $new_level ); If $new_level given will change current log level. This is same as call config({ level=>$new_level }) but much faster. Return previous log level. ident $ident = $LOG->ident(); $ident = $LOG->ident( $new_ident ); If $new_ident given will change current syslog's ident. This is same as call config({ ident=>$new_ident }) but much faster. Return previous syslog's ident. ERR WARN NOTICE INFO DEBUG $LOG->ERR( $message ) $LOG->ERR( $format, @list ) $LOG->WARN( $message ) $LOG->WARN( $format, @list ) $LOG->NOTICE( $message ) $LOG->NOTICE( $format, @list ) $LOG->INFO( $message ) $LOG->INFO( $format, @list ) $LOG->DEBUG( $message ) $LOG->DEBUG( $format, @list ) Output $message to log using different log levels. If $format, @list used instead of $message, then use sprintf($format, @list) to calculate log message. If @list will contain CODEREF, they will be called (in LIST context) and returned values will be placed inside @list inplace of CODEREF. This can be used to avoid calculating log message (or it part) on disabled log levels - these CODEREF will be executed only on enabled log levels. Example available in "SYNOPSIS". If $message or items in @list will be Unicode strings, they will be converted to UTF8 before sending to log. Return nothing. Throw exception if fail to write message to log. OPTIONS Defaults for all options are: level => 'DEBUG', prefix => q{}, type => 'fh', fh => \*STDERR, # these will be used if you will call config({ type=>'unix' }) path => Sys::Syslog::_PATH_LOG() || '/dev/log', facility => LOG_USER, add_timestamp => 1, add_hostname => 0, hostname => Sys::Hostname::hostname(), ident => ..., # calculated from $0 add_pid => 1, pid => $$, level Current log level. Possible values are: 'ERR', 'WARN', 'NOTICE', 'INFO', 'DEBUG'. Only messages on current or higher levels will be sent to log. prefix String, which will be output at beginning of each log message. May contain these placeholders: %L - log level of current message %S - hi-resolution time (seconds.microseconds) %D - current date in format YYYY-MM-DD %T - current time in format HH:MM:SS %P - caller's function package ('main' or 'My::Module') %F - caller's function name %_ - X spaces, where X is current stack depth %% - % character Example output with prefix '%D %T [%L]%_%P::%F() ': 2010-11-17 18:06:20 [INFO] main::() something from main script 2010-11-17 18:06:53 [INFO] main::a() something from a 2010-11-17 18:09:09 [INFO] main::b2() something from b1->b2 2010-11-17 18:06:56 [INFO] main::c() something from c If it will be Unicode string, it will be converted to UTF8. type Output type. Possible values are: 'fh' (output to any already open filehandle) and 'unix' (output to syslog using UNIX socket). When {type} set to 'fh' you have to also set {fh} to any open filehandle (like \*STDERR). When {type} set to 'unix' you have to also set {path} to path to existing UNIX socket (typically it's '/dev/log'). Luckily, default values for both {fh} and {path} are already provided, so usually it's enough to just set {type}. fh File handle to write log messages if {type} set to 'fh'. path Syslog's UNIX socket path to write log messages if {type} set to 'unix'. facility Syslog's facility (see "Facilities" in Sys::Syslog for a list of well-known facilities). This module doesn't export any constants, so if you wanna change it from default LOG_USER value, you should import facility constants from Sys::Syslog module. Example available in "SYNOPSIS". add_timestamp If TRUE will include timestamp in syslog messages. add_hostname If TRUE will include hostname in syslog messages. hostname Host name which will be included in syslog messages if {add_hostname} is TRUE. ident Syslog's ident (application name) field. If it will be Unicode string, it will be converted to UTF8. Using non-ASCII ALPHANUMERIC ident isn't allowed by RFC, but usually works. add_pid If TRUE will include PID in syslog messages. pid PID which will be included in syslog messages if {add_pid} is TRUE. SPEED HINTS Empty prefix is fastest. Prefixes %L, %P and %% are fast enough, %D and %T has average speed, %S, %F and %_ are slowest. Output to file is about 4 times faster than to syslog. Calling log with single parameter is faster than with many parameters (because in second case sprintf() have to be used). SUPPORT Bugs / Feature Requests Please report any bugs or feature requests through the issue tracker at https://github.com/powerman/perl-Log-Fast/issues. You will be notified automatically of any progress on your issue. Source Code This is open source software. The code repository is available for public review and contribution under the terms of the license. Feel free to fork the repository and submit pull requests. https://github.com/powerman/perl-Log-Fast git clone https://github.com/powerman/perl-Log-Fast.git Resources * MetaCPAN Search https://metacpan.org/search?q=Log-Fast * CPAN Ratings http://cpanratings.perl.org/dist/Log-Fast * AnnoCPAN: Annotated CPAN documentation http://annocpan.org/dist/Log-Fast * CPAN Testers Matrix http://matrix.cpantesters.org/?dist=Log-Fast * CPANTS: A CPAN Testing Service (Kwalitee) http://cpants.cpanauthors.org/dist/Log-Fast AUTHOR Alex Efros COPYRIGHT AND LICENSE This software is Copyright (c) 2010- by Alex Efros . This is free software, licensed under: The MIT (X11) License Log-Fast-v2.0.1/cpanfile0000644000175000017500000000062213260730541015263 0ustar powermanpowermanrequires 'perl', '5.010001'; requires 'Scalar::Util'; requires 'Socket'; requires 'Sys::Syslog', '0.29'; requires 'Time::HiRes'; on configure => sub { requires 'Module::Build::Tiny', '0.034'; }; on test => sub { requires 'File::Temp'; requires 'Test::Exception'; requires 'Test::More'; }; on develop => sub { requires 'Test::Distribution'; requires 'Test::Perl::Critic'; }; Log-Fast-v2.0.1/LICENSE0000644000175000017500000000223213260730541014563 0ustar powermanpowermanThis software is Copyright (c) 2010- by Alex Efros . This is free software, licensed under: The MIT (X11) License The MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Log-Fast-v2.0.1/dist.ini0000644000175000017500000000045513260730541015227 0ustar powermanpowerman[@Milla] [MetaProvides::Package] [Substitute] code = s/^(This document describes \S+ version |VERSION=['"])([^'"\r\n]*)/my($s,$v)=($1,$2);my%h=%Term::ReadLine::Gnu::Attribs;$s.($h{prompt}?($h{line_buffer}||$h{prompt}=~m{ \[(.*)\]})[0]:$v)/e [GitHubREADME::Badge] badges = travis badges = coveralls Log-Fast-v2.0.1/META.json0000644000175000017500000000357513260730541015212 0ustar powermanpowerman{ "abstract" : "Fast and flexible logger", "author" : [ "Alex Efros " ], "dynamic_config" : 0, "generated_by" : "Dist::Milla version v1.0.18, Dist::Zilla version 6.011, CPAN::Meta::Converter version 2.150010", "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Log-Fast", "no_index" : { "directory" : [ "eg", "examples", "inc", "share", "t", "xt" ] }, "prereqs" : { "configure" : { "requires" : { "Module::Build::Tiny" : "0.034" } }, "develop" : { "requires" : { "Dist::Milla" : "v1.0.18", "Test::Distribution" : "0", "Test::Perl::Critic" : "0", "Test::Pod" : "1.41" } }, "runtime" : { "requires" : { "Scalar::Util" : "0", "Socket" : "0", "Sys::Syslog" : "0.29", "Time::HiRes" : "0", "perl" : "5.010001" } }, "test" : { "requires" : { "File::Temp" : "0", "Test::Exception" : "0", "Test::More" : "0" } } }, "provides" : { "Log::Fast" : { "file" : "lib/Log/Fast.pm", "version" : "v2.0.1" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/powerman/perl-Log-Fast/issues" }, "homepage" : "https://github.com/powerman/perl-Log-Fast", "repository" : { "type" : "git", "url" : "https://github.com/powerman/perl-Log-Fast.git", "web" : "https://github.com/powerman/perl-Log-Fast" } }, "version" : "v2.0.1", "x_serialization_backend" : "JSON::XS version 3.04" } Log-Fast-v2.0.1/MANIFEST0000644000175000017500000000052113260730541014706 0ustar powermanpowerman# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.011. Build.PL Changes LICENSE MANIFEST META.json META.yml README cpanfile dist.ini lib/Log/Fast.pm t/00.load.t t/a.pm t/a/b.pm t/author-perlcritic.t t/author-pod-syntax.t t/global.t t/level.t t/prefix.t t/raise.t t/release-distribution.t t/syslog.t t/unicode.t Log-Fast-v2.0.1/META.yml0000644000175000017500000000171613260730541015035 0ustar powermanpowerman--- abstract: 'Fast and flexible logger' author: - 'Alex Efros ' build_requires: File::Temp: '0' Test::Exception: '0' Test::More: '0' configure_requires: Module::Build::Tiny: '0.034' dynamic_config: 0 generated_by: 'Dist::Milla version v1.0.18, Dist::Zilla version 6.011, CPAN::Meta::Converter version 2.150010' license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Log-Fast no_index: directory: - eg - examples - inc - share - t - xt provides: Log::Fast: file: lib/Log/Fast.pm version: v2.0.1 requires: Scalar::Util: '0' Socket: '0' Sys::Syslog: '0.29' Time::HiRes: '0' perl: '5.010001' resources: bugtracker: https://github.com/powerman/perl-Log-Fast/issues homepage: https://github.com/powerman/perl-Log-Fast repository: https://github.com/powerman/perl-Log-Fast.git version: v2.0.1 x_serialization_backend: 'YAML::Tiny version 1.73'