File Coverage

blib/lib/Log/Any/Adapter/Multiplex.pm
Criterion Covered Total %
statement 66 66 100.0
branch 12 14 85.7
condition 4 6 66.6
subroutine 14 14 100.0
pod 0 2 0.0
total 96 102 94.1


line stmt bran cond sub pod time code
1             package Log::Any::Adapter::Multiplex;
2             # ABSTRACT: Adapter to use allow structured logging across other adapters
3             our $VERSION = '1.717';
4              
5 1     1   660 use Log::Any;
  1         2  
  1         5  
6 1     1   7 use Log::Any::Adapter;
  1         2  
  1         5  
7 1     1   4 use Log::Any::Adapter::Util qw(make_method);
  1         2  
  1         66  
8 1     1   7 use Log::Any::Manager;
  1         5  
  1         35  
9 1     1   6 use Log::Any::Proxy;
  1         2  
  1         19  
10 1     1   5 use Carp;
  1         2  
  1         73  
11 1     1   7 use strict;
  1         1  
  1         28  
12 1     1   5 use warnings;
  1         2  
  1         27  
13 1     1   6 use base qw(Log::Any::Adapter::Base);
  1         1  
  1         683  
14              
15             sub init {
16 6     6 0 9 my $self = shift;
17              
18 6         13 my $adapters = $self->{adapters};
19 6 100 100     33 if ( ( ref($adapters) ne 'HASH' ) ||
20 5         20 ( grep { ref($_) ne 'ARRAY' } values %$adapters ) ) {
21 4         743 Carp::croak("A list of adapters and their arguments must be provided");
22             }
23             }
24              
25             sub structured {
26 3     3 0 9 my ($self, $level, $category, @structured_log_args) = @_;
27 3         4 my %adapters = %{ $self->{adapters} };
  3         9  
28 3         5 my $unstructured_msg;
29              
30 3         5 for my $adapter ( $self->_get_adapters($category) ) {
31 6         32 my $is_level = "is_$level";
32              
33 6 100       12 if ($adapter->$is_level) {
34             # Very simple mimicry of Log::Any::Proxy
35             # We don't have to handle anything but the difference in
36             # non-structured interfaces
37 4 100       24 if ($adapter->can('structured')) {
38 2         6 $adapter->structured($level, $category, @structured_log_args)
39             }
40             else {
41 2 50       5 if (!$unstructured_msg) {
42 2         4 $unstructured_msg = _unstructured_msg(@structured_log_args);
43             }
44 2         8 $adapter->$level($unstructured_msg);
45             }
46             }
47             }
48             }
49              
50             sub _unstructured_msg {
51 2     2   4 my @structured = @_;
52 2         3 my @unstructured = @structured;
53              
54 2 50 33     10 if ( @structured && ( ( ref $structured[-1] ) eq ref {} ) ) {
55 2         12 @unstructured = (
56             @structured[ 0 .. $#structured - 1 ],
57             Log::Any::Proxy::_stringify_params( $structured[-1] ),
58             )
59             }
60              
61 2         77 return join(' ' => @unstructured);
62             }
63              
64             # Delegate detection methods to other adapters
65             #
66             foreach my $method ( Log::Any->detection_methods() ) {
67             make_method(
68             $method,
69             sub {
70 7     7   17 my ($self) = @_;
71             # Not using List::Util::any because it could break older perl builds
72 7         15 my @logging_adaptors = grep { $_->$method } $self->_get_adapters();
  14         43  
73 7 100       46 return @logging_adaptors ? 1 : 0;
74             }
75             );
76             }
77              
78             sub _get_adapters {
79 10     10   17 my ($self) = @_;
80 10         13 my $category = $self->{category};
81             # Log::Any::Manager#get_adapter has similar code
82             # But has to handle rejiggering the stack
83             # And works with one adapter at a time (instead of a list, as below)
84             # Keeping track of multiple categories here is just future-proofing.
85             #
86 10         60 my $category_cache = $self->{category_cache};
87 10 100       23 if ( !defined( $category_cache->{$category} ) ) {
88 1         2 my $new_cache = [];
89 1         2 my %adapters = %{ $self->{adapters} };
  1         5  
90 1         5 while ( my ($adapter_name, $adapter_args) = each %adapters ) {
91 2         10 my $adapter_class = Log::Any::Manager->_get_adapter_class($adapter_name);
92 2         24 push @$new_cache, $adapter_class->new(
93             @$adapter_args,
94             category => $category
95             );
96             }
97              
98 1         5 $self->{category_cache}{$category} = $new_cache;
99             }
100              
101 10         11 return @{ $self->{category_cache}{$category} };
  10         29  
102             }
103              
104             1;
105              
106             __END__