File Coverage

blib/lib/Mojolicious/Plugin/Logf.pm
Criterion Covered Total %
statement 22 31 70.9
branch 7 12 58.3
condition 3 4 75.0
subroutine 5 8 62.5
pod 3 3 100.0
total 40 58 68.9


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Logf;
2              
3             =head1 NAME
4              
5             Mojolicious::Plugin::Logf - Plugin for logging datastructures using sprintf
6              
7             =head1 VERSION
8              
9             0.07
10              
11             =head1 DESCRIPTION
12              
13             L is a plugin which will log complex datastructures
14             and avoid "unitialized" warnings. This plugin use L or whatever
15             L is set to, to do the actual logging.
16              
17             =head1 SYNOPSIS
18              
19             use Mojolicious::Lite;
20             plugin "Logf";
21              
22             get "/" => sub {
23             my $self = shift;
24              
25             $self->logf(info => 'request: %s', $self->req->params->to_hash);
26             };
27              
28             =head1 COPY/PASTE CODE
29              
30             If you think it's a waste to depend on this module, you can copy paste the
31             code below to get the same functionality as the L helper:
32              
33             helper logf => sub {
34             my ($c, $level, $format) = (shift, shift, shift);
35             my $log = $c->app->log;
36             return $c unless $log->${ \ "is_$level" };
37             my @args = map {ref $_ eq 'CODE' ? $_->() : $_} @_;
38             local $Data::Dumper::Indent = 0;
39             local $Data::Dumper::Maxdepth = $Data::Dumper::Maxdepth || 2;
40             local $Data::Dumper::Sortkeys = 1;
41             local $Data::Dumper::Terse = 1;
42             for (@args) {
43             $_ = !defined($_) ? "__UNDEF__" : overload::Method($_, q("")) ? "$_" : ref($_) ? Data::Dumper::Dumper($_) : $_;
44             }
45             $log->$level(sprintf $format, @args);
46             return $c;
47             };
48              
49             Note: The code above is generated and tested from the original source code,
50             but it will more difficult to get updates and bug fixes.
51              
52             =cut
53              
54 2     2   59478 use Mojo::Base 'Mojolicious::Plugin';
  2         5  
  2         16  
55 2     2   3428 use Data::Dumper ();
  2         18292  
  2         59  
56 2     2   13 use overload ();
  2         2  
  2         66  
57 2   100 2   10 use constant UNDEF => $ENV{MOJO_LOGF_UNDEF} || '__UNDEF__';
  2         4  
  2         976  
58              
59             our $VERSION = '0.07';
60              
61             =head1 HELPERS
62              
63             =head2 logf
64              
65             $self = $c->logf;
66             $c = $c->logf($level => $format, @args);
67              
68             Logs a string formatted by the usual C conventions of the C library
69             function C. C<$level> need to be a valid L level.
70             C<@args> will be converted using L.
71              
72             Calling this method without any arguments will return C<$self>
73             (an instance of this plugin), allowing you to call L:
74              
75             @args_as_strings = $c->logf->flatten(@args);
76              
77             =cut
78              
79             sub logf {
80 0     0 1 0 my ($self, $c, $level, $format, @args) = @_;
81 0         0 my $log = $c->app->log;
82              
83 0 0       0 $log->$level(sprintf $format, $self->flatten(@args)) if $log->${ \ "is_$level" };
  0         0  
84 0         0 $c;
85             }
86              
87             =head1 METHODS
88              
89             =head2 flatten
90              
91             @args_as_strings = $self->flatten(@args);
92              
93             Used to convert input C<@args> using these rules:
94              
95             =over 4
96              
97             =item * Scalar
98              
99             No rule applied.
100              
101             =item * Code ref
102              
103             A code ref will be called, and the list of return values will be flattened.
104             The code below will not calculate the request params, unless the log level
105             is "debug":
106              
107             $c->logf(debug => 'request: %s', sub {$c->req->params->to_hash});
108              
109             =item * Object with string overloading
110              
111             Will be coverted to a string using the string overloading function.
112              
113             =item * Data structure or object
114              
115             Will be serialized using L with these settings:
116              
117             $Data::Dumper::Indent = 0;
118             $Data::Dumper::Maxdepth = $Data::Dumper::Maxdepth || 2;
119             $Data::Dumper::Sortkeys = 1;
120             $Data::Dumper::Terse = 1;
121              
122             NOTE! These settings might change, but will always do its best to
123             serialize the object into one line. C<$Data::Dumper::Maxdepth> is
124             used to avoid dumping large nested objects. Set this variable
125             if you need deeper logging. Example:
126              
127             local $Data::Dumper::Maxdepth = 1000;
128             $c->logf(info => 'Deep structure: %s', $some_object);
129              
130             =item * Undefined value
131              
132             Will be logged as "__UNDEF__". This value can be changed by setting
133             the global environment variable C before loading this
134             plugin.
135              
136             =back
137              
138             =cut
139              
140             sub flatten {
141 2     2 1 349 my $self = shift;
142 2 50       7 my @args = map {ref $_ eq 'CODE' ? $_->() : $_} @_;
  6         30  
143              
144 2         8 local $Data::Dumper::Indent = 0;
145 2   50     22 local $Data::Dumper::Maxdepth = $Data::Dumper::Maxdepth || 2;
146 2         5 local $Data::Dumper::Sortkeys = 1;
147 2         5 local $Data::Dumper::Terse = 1;
148              
149 2         7 for (@args) {
150 6 100       2493 $_ = !defined($_) ? UNDEF : overload::Method($_, q("")) ? "$_" : ref($_) ? Data::Dumper::Dumper($_) : $_;
    100          
    100          
151             }
152              
153 2         127 return @args;
154             }
155              
156             =head2 register
157              
158             Will register the L helper in the application
159              
160             =cut
161              
162             sub register {
163 0     0 1   my ($self, $app, $config) = @_;
164              
165             $app->helper(logf => sub {
166 0 0   0     return $self if @_ == 1;
167 0           return $self->logf(@_);
168 0           });
169             }
170              
171             =head1 COPYRIGHT AND LICENSE
172              
173             Copyright (C) 2014, Jan Henning Thorsen
174              
175             This program is free software, you can redistribute it and/or modify it under
176             the terms of the Artistic License version 2.0.
177              
178             =head1 AUTHOR
179              
180             Jan Henning Thorsen - C
181              
182             =cut
183              
184             1;