hierarchical log routing is now implemented in object-remote instead of log-contextual
[scpubgit/Object-Remote.git] / lib / Object / Remote / LogRouter.pm
CommitLineData
f7ea4120 1package Object::Remote::LogRouter;
2
3use Moo;
4use Scalar::Util qw(blessed);
5
6with 'Object::Remote::Role::LogForwarder';
7
8has subscriptions => ( is => 'ro', required => 1, default => sub { [] } );
9
10sub before_import { }
11sub after_import {
12 my ($self, $controller, $importer, $config) = @_;
13 my $logger = $controller->arg_logger($config->{logger});
14
15# TODO need to review this concept, ignore these configuration values for now
16# my $package_logger = $controller->arg_package_logger($config->{package_logger});
17# my $default_logger = $config->{default_logger};
18#
19# #when installing a new selector this will be the default
20# #logger invoked unless otherwise specified
21# $self->{default_logger} = $default_logger;
22#
23# #if the logger configuration value is specified
24# #then all logs given to the router will also be
25# #delivered to that logger
26# if (defined($logger)) {
27# $self->add_selector(sub { 1 }, $logger);
28# }
29#
30# #if the configuration specifies a package logger
31# #build a selector that matches the package and
32# #install it
33# if (defined($package_logger)) {
34# $self->add_selector( sub { $_->{package} eq $importer }, $package_logger );
35# }
36}
37
38sub subscribe {
39 my ($self, $logger, $selector, $is_temp) = @_;
40 my $subscription_list = $self->subscriptions;
41
42 if(ref $logger ne 'CODE') {
43 die 'logger was not a CodeRef or a logger object. Please try again.'
44 unless blessed($logger);
45 $logger = do { my $l = $logger; sub { $l } }
46 }
47
48 my $subscription = [ $logger, $selector ];
49
50 $is_temp = 0 unless defined $is_temp;
51 push(@$subscription_list, $subscription);
52 if ($is_temp) {
53 #weaken($subscription->[-1]);
54 }
55 return $subscription;
56}
57
58#TODO turn this logic into a role
59sub handle_log_message {
60 my ($self, $caller, $level, $log_meth, @values) = @_;
61 my $should_clean = 0;
62
63 foreach(@{ $self->subscriptions }) {
64 unless(defined($_)) {
65 $should_clean = 1;
66 next;
67 }
68 my ($logger, $selector) = @$_;
69 #TODO this is not a firm part of the api but providing
70 #this info to the selector is a good feature
71 local($_) = { level => $level, package => $caller };
72 if ($selector->(@values)) {
73 #TODO resolve caller_level issues with routing
74 #idea: the caller level will differ in distance from the
75 #start of the call stack but it's a constant distance from
76 #the end of the call stack - can that be exploited to calculate
77 #the distance from the start right before it's used?
78 #
79 #newer idea: in order for log4perl to work right the logger
80 #must be invoked in the exported log_* method directly
81 #so by passing the logger down the chain of routers
82 #it can be invoked in that location and the caller level
83 #problem doesn't exist anymore
84 $logger = $logger->($caller, { caller_level => -1 });
85
86 $logger->$level($log_meth->(@values))
87 if $logger->${\"is_$level"};
88 }
89 }
90
91 if ($should_clean) {
92 $self->_remove_dead_subscriptions;
93 }
94
95 return;
96}
97
98sub _remove_dead_subscriptions {
99 my ($self) = @_;
100 my @ok = grep { defined $_ } @{$self->subscriptions};
101 @{$self->subscriptions} = @ok;
102 return;
103}
104
105
1061;
107