File Coverage

blib/lib/Mojo/Log/Role/Color.pm
Criterion Covered Total %
statement 37 41 90.2
branch 7 10 70.0
condition 6 10 60.0
subroutine 9 12 75.0
pod n/a
total 59 73 80.8


line stmt bran cond sub pod time code
1             package Mojo::Log::Role::Color;
2 4     4   265167 use Mojo::Base -role;
  4         20  
  4         33  
3              
4 4     4   5189 use Term::ANSIColor ();
  4         38674  
  4         2647  
5              
6             our $VERSION = '0.04';
7              
8             our %COLORS = (
9             debug => ['cyan'],
10             error => ['red'],
11             fatal => ['white on_red'],
12             info => ['green'],
13             warn => ['yellow'],
14             );
15              
16             has colored => sub { $ENV{MOJO_LOG_COLORS} // -t shift->handle };
17              
18             around format => sub {
19             my ($next, $self) = (shift, shift);
20              
21             # set
22             return $next->($self, @_) if @_;
23              
24             # get
25             my $formatter = $next->($self);
26             return $formatter unless $self->colored;
27              
28             return sub {
29             my $level = $_[1];
30             my $message = $formatter->(@_);
31             my $newline = $message =~ s!(\r?\n)$!! ? $1 : '';
32             return Term::ANSIColor::colored($COLORS{$level} || $COLORS{debug}, $message)
33             . $newline;
34             };
35             };
36              
37             sub import {
38 2     2   24 my $class = shift;
39 2 50       11 return unless my @flags = @_;
40              
41 2         6 my $caller = caller;
42 2         8 while (my $flag = shift @flags) {
43 2 50       8 if ($flag eq '-func') {
44 2         520 require Mojo::Log;
45 2   100     38253 my $fqn = shift @flags || 'l';
46 2 100       9 $fqn = "${caller}::$fqn" unless $fqn =~ m!::!;
47 4     4   53 no strict 'refs';
  4         18  
  4         2993  
48 2         2186 *$fqn = \&_l;
49             }
50             }
51             }
52              
53             sub _f {
54 1     1   3361 my $format = shift;
55              
56             state $f = {
57             ymd => sub {
58 0     0   0 my ($d, $m, $y) = (localtime $_[0])[3, 4, 5];
59 0         0 sprintf sprintf '%04d-%02d-%02d', $y + 1900, $m + 1, $d;
60             },
61             hms => sub {
62 1     1   49 my ($s, $m, $h) = localtime $_[0];
63 1   50     36 sprintf '%02d:%02d:%08.5f', $h, $m, "$s." . ((split /\./, $_[0])[1] // 0);
64             },
65 0     0   0 level => sub { $_[1] },
66 1     1   2 m => sub { join "\n", @{$_[2]}, '' },
  1         5  
67 0     0   0 pid => sub {$$},
68 1         30 };
69              
70 1         7 my $re = join '|', keys %$f;
71 1         54 $re = qr{%($re)};
72              
73             return sub {
74 1     1   3 my ($str, $time, $level) = ($format, shift, shift);
75 1         10 $str =~ s!$re!{$f->{$1}($time, $level, \@_)}!ge;
  2         6  
  2         8  
76 1         4 return $str;
77 1         42 };
78             }
79              
80             sub _l {
81 4     4   955 my ($level, $format, @args) = @_;
82             state $log
83             = Mojo::Log->with_roles('+Color')->new->colored($ENV{MOJO_LOG_COLORS} // 1)
84 4   50     25 ->format(_f($ENV{MOJO_LOG_FORMAT} || '[%hms] %m'));
      50        
85 4 100       88 return $log unless $level;
86             return $log->$level(@args
87 1 50 50     5 ? sprintf $format, map { $_ // 'undef' } @args
  1         13  
88             : $format);
89             }
90              
91             1;
92              
93             =encoding utf8
94              
95             =head1 NAME
96              
97             Mojo::Log::Role::Color - Add colors to your mojo logs
98              
99             =head1 SYNOPSIS
100              
101             use Mojo::Log;
102             my $log = Mojo::Log->with_roles("+Color")->new;
103             $log->info("FYI: it happened again");
104              
105             =head1 DESCRIPTION
106              
107             L is a role you can apply to your L to get
108             colored log messages when running your application in interactive mode.
109              
110             It is also possible to set the C environment variable to force
111             colored output.
112              
113             The coloring is based on the log level:
114              
115             debug: cyan text
116             info: green text
117             warn: yellow text
118             error: red text
119             fatal: white text on red background
120              
121             The colors can be customized by changing C<%Mojo::Log::Role::Color::COLORS>,
122             though this is not officially supported, and may break in a future release.
123              
124             =head1 EXPORTED FUNCTIONS
125              
126             use Mojo::Log::Role::Color -func;
127             l error => "too %s", "cool";
128              
129             use Mojo::Log::Role::Color -func => 'main::DEBUG';
130             main::DEBUG error => "too %s", "cool";
131              
132             $ MOJO_LOG_FORMAT="%hms %m" PERL5OPT="-MMojo::Log::Role::Color=-func" perl -le'::l error => "bad"'
133             $ MOJO_LOG_FORMAT="%ymdT%hms [%pid] [%level] %m" PERL5OPT="-MMojo::Log::Role::Color=-func" prove -vl t/test.t
134              
135             It is possible to import a logging function that provides a quick and dirty
136             logging interface.
137              
138             The C<-func> switch might change without warning. It's only supposed to be used
139             for quick debug output.
140              
141             =head1 ATTRIBUTES
142              
143             =head2 colored
144              
145             $bool = $log->colored;
146             $log = $log->colored(1);
147              
148             Check if colored output is enabled, or force it to a given state. Defaults to
149             C environment variable, or will be set to "1" if
150             L is attached to a terminal.
151              
152             =head1 AUTHOR
153              
154             Jan Henning Thorsen
155              
156             =head1 COPYRIGHT AND LICENSE
157              
158             Copyright (C) Jan Henning Thorsen
159              
160             This program is free software, you can redistribute it and/or modify it under
161             the terms of the Artistic License version 2.0.
162              
163             =head1 SEE ALSO
164              
165             L.
166              
167             =cut