File Coverage

blib/lib/Log/ger/App.pm
Criterion Covered Total %
statement 68 94 72.3
branch 32 78 41.0
condition 2 5 40.0
subroutine 6 7 85.7
pod n/a
total 108 184 58.7


line stmt bran cond sub pod time code
1             package Log::ger::App;
2              
3 1     1   404 use strict;
  1         2  
  1         22  
4 1     1   3 use warnings;
  1         2  
  1         339  
5              
6             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
7             our $DATE = '2022-01-16'; # DATE
8             our $DIST = 'Log-ger-App'; # DIST
9             our $VERSION = '0.022'; # VERSION
10              
11             our $DEBUG = defined($ENV{LOG_GER_APP_DEBUG}) ? $ENV{LOG_GER_APP_DEBUG} : 0;
12              
13             # last import args
14             our @IMPORT_ARGS;
15              
16             sub _set_level {
17 3     3   5 my $name = shift;
18              
19 3         10 while (my ($source, $param, $note) = splice @_, 0, 3) {
20 8 100       15 if ($source eq 'val') {
    50          
21 5 100       10 if (defined $param) {
22 3 50       5 warn "[lga] Setting $name to $param (from $note)\n" if $DEBUG;
23 3         6 return $param;
24             }
25             } elsif ($source eq 'envset') {
26 3         3 my $prefix = $param;
27 3 50       10 if (defined $ENV{"${prefix}LOG_LEVEL"}) {
28 0         0 my $val = $ENV{"${prefix}LOG_LEVEL"};
29 0 0       0 warn "[lga] Setting $name to $val (from environment ${prefix}LOG_LEVEL)\n" if $DEBUG;
30 0         0 return $val;
31             }
32 3 50       7 if ($ENV{"${prefix}TRACE"}) {
33 0 0       0 warn "[lga] Setting $name to trace (from environment ${prefix}TRACE)\n" if $DEBUG;
34 0         0 return 'trace';
35             }
36 3 50       6 if ($ENV{"${prefix}DEBUG"}) {
37 0 0       0 warn "[lga] Setting $name to debug (from environment ${prefix}DEBUG)\n" if $DEBUG;
38 0         0 return 'debug';
39             }
40 3 50       6 if ($ENV{"${prefix}VERBOSE"}) {
41 0 0       0 warn "[lga] Setting $name to info (from environment ${prefix}VERBOSE)\n" if $DEBUG;
42 0         0 return 'info';
43             }
44 3 50       11 if ($ENV{"${prefix}QUIET"}) {
45 0 0       0 warn "[lga] Setting $name to trace (from environment ${prefix}QUIET)\n" if $DEBUG;
46 0         0 return 'error';
47             }
48             } else {
49 0         0 die "BUG: Unknown level source '$source'";
50             }
51             }
52 0         0 'warn';
53             }
54              
55             sub _is_daemon {
56 1 50   1   2 return $main::IS_DAEMON if defined $main::IS_DAEMON;
57 1         3 for (
58             "App/Daemon.pm",
59             "Daemon/Easy.pm",
60             "Daemon/Daemonize.pm",
61             "Daemon/Generic.pm",
62             "Daemonise.pm",
63             "Daemon/Simple.pm",
64             "HTTP/Daemon.pm",
65             "IO/Socket/INET/Daemon.pm",
66             #"Mojo/Server/Daemon.pm", # simply loading Mojo::UserAgent will load this too
67             "MooseX/Daemonize.pm",
68             "Net/Daemon.pm",
69             "Net/Server.pm",
70             "Proc/Daemon.pm",
71             "Proc/PID/File.pm",
72             "Win32/Daemon/Simple.pm") {
73 14 50       20 return 1 if $INC{$_};
74             }
75 1         1 0;
76             }
77              
78             sub import {
79 1     1   5 no warnings 'once'; # $Log::ger::Current_Level
  1         2  
  1         597  
80              
81 1     1   848 my ($pkg, %args) = @_;
82              
83 1         1355 require Log::ger;
84 1         390 require Log::ger::Util;
85              
86 1         4254 my $extra_conf = delete $args{extra_conf};
87 1         1 my $level_arg = delete $args{level};
88 1         2 my $default_level_arg = delete $args{default_level};
89              
90 1         3 my $level = _set_level(
91             "general log level",
92             val => $level_arg, "import argument 'level'",
93             envset => "", "",
94             val => $default_level_arg, "import argument 'default_level'",
95             val => 'warn', "fallback value",
96             );
97 1         2 $Log::ger::Current_Level = Log::ger::Util::numeric_level($level);
98              
99 1         7 my $is_daemon = delete $args{daemon};
100 1 50       13 $is_daemon = _is_daemon() if !defined($is_daemon);
101              
102 1         3 my $is_oneliner = $0 eq '-e';
103              
104 1         1 my $progname = delete $args{name};
105 1 50       2 unless (defined $progname) {
106 1         6 ($progname = $0) =~ s!.+/!!;
107 1         2 $progname =~ s/\.pl$//;
108             }
109 1 50       2 unless (length $progname) {
110 0         0 $progname = "prog";
111             }
112              
113             # configuration for Log::ger::Output::Composite
114             my %conf = (
115             outputs => {},
116 1   50     1 %{ $extra_conf // {} },
  1         6  
117             );
118              
119 1         2 my %off_categories = (
120             # some known categories that are not normally logged to screen or
121             # (error) file log
122             #'_dumps' => 'off', # e.g. in download-bca, download-mandiri
123             '_access' => 'off', # e.g. in WWW::PAUSE::Simple
124             );
125              
126             # add Screen
127             {
128 1 50       2 last if $is_daemon;
129 1         2 my $olevel = _set_level(
130             "screen log level",
131             envset => "SCREEN_", "",
132             val => $level, "general log level",
133             );
134 1 50       3 last if $olevel eq 'off';
135             my $fmt =
136             ($ENV{LOG_ADD_STACK_TRACE} ? '[stack %T] ': '').
137             ($ENV{LOG_ADD_LOCATION} ? '[location %l] ': '').
138             ($ENV{LOG_ADD_TIMESTAMP} ? '[%d] ': '').
139 1 50       6 ($ENV{LOG_ADD_MEMORY_INFO} ? '[vmsize %_{vmsize}K] ': '').
    50          
    50          
    50          
140             '%m';
141             $conf{outputs}{Screen} = {
142 1     0   8 conf => { formatter => sub { "$progname: $_[0]" }, colorize_tags => 1 },
  0         0  
143             level => $olevel,
144             category_level => \%off_categories,
145             layout => [Pattern => {format => $fmt}],
146             };
147             }
148              
149             # add File
150             {
151 1         2 my $file_name = delete $args{file_name};
  1         1  
152 1 50       2 unless (defined $file_name) {
153 1         2 $file_name = "$progname.log";
154             }
155              
156 1         1 my $file_dir = delete $args{file_dir};
157 1 50       2 unless (defined $file_dir) {
158 1         348 require PERLANCAR::File::HomeDir;
159 1 50 33     4424 $file_dir = $> || $^O eq 'MSWin32' ?
    50          
160             PERLANCAR::File::HomeDir::get_my_home_dir() :
161             (-d "/var/log" ? "/var/log" : "/");
162             }
163              
164 1 50       7 last if $0 eq '-';
165              
166 1         3 my $file_path = "$file_dir/$file_name";
167 1         7 my $olevel = _set_level(
168             "file ($file_path) log level",
169             envset => "FILE_", "",
170             val => $level, "general log level",
171             );
172 1 50       3 last if $olevel eq 'off';
173             my $fmt =
174             '[pid %P] [%d] '.
175 1 50       4 ($ENV{LOG_ADD_MEMORY_INFO} ? '[vmsize %_{vmsize}K] ': '').
176             '%m';
177             $conf{outputs}{File} = {
178 1         7 conf => { path => $file_path },
179             level => $olevel,
180             category_level => \%off_categories,
181             layout => [Pattern => {format => $fmt}],
182             };
183             }
184              
185             # add Syslog
186             {
187 1 50       2 last unless $is_daemon;
  1         1  
  1         3  
188 0         0 my $olevel = _set_level(
189             "syslog log level",
190             envset => "SYSLOG_", "",
191             val => $level, "general log level",
192             );
193 0 0       0 last if $olevel eq 'off';
194             $conf{outputs}{Syslog} = {
195 0         0 conf => { ident => $progname, facility => 'daemon' },
196             level => $olevel,
197             category_level => \%off_categories,
198             };
199             }
200              
201 1 50       5 if (my $outputs = delete $args{outputs}) {
202 0         0 for my $o (sort keys %$outputs) {
203 0 0       0 if ($conf{outputs}{$o}) {
204 0 0       0 warn "[lga] OVERWRITING output '$o' using output from 'outputs' argument\n" if $DEBUG;
205             } else {
206 0 0       0 warn "[lga] Adding output '$o' from 'outputs' argument\n" if $DEBUG;
207             }
208 0         0 $conf{outputs}{$o} = $outputs->{$o};
209             }
210             }
211              
212 1 50       23 die "Unknown argument(s): ".join(", ", sort keys %args)
213             if keys %args;
214              
215             # save, for those who want to check or modify
216 0           @IMPORT_ARGS = @_;
217              
218 0           require Log::ger::Output;
219 0           Log::ger::Output->set('Composite', %conf);
220             }
221              
222             1;
223             # ABSTRACT: An easy way to use Log::ger in applications
224              
225             __END__