views:

138

answers:

2

I use Catalyst (MVC framework for Perl), but the question probably apply to all MVC framework.

Until now, I used the Apache log files to get statistics about the visitors: user agent, URL accessed, time, etc. But now that I moved to an MVC framework, I don't think this is adequate. If a request to /1/foo and /1/bar are the same for me, I want to show /1/ in my log only, for example.

So I am wondering what is the best way to generate my own log files for statistics. Should I treat it as just another log file in my application?

These statistics can be logged at any time. Ideally they would be logged after the page is sent to the user, so it will not feel the additional time required for logging.

+4  A: 

Given that Catalyst already uses subroutine attributes liberally, one useful approach might be to use an attribute to wrap the relevant subs in a custom logging mechanism. I wrote an article about this technique which uses logging as an example. The basic idea is:

use Attribute::Handlers;

sub Log : ATTR(CODE) {
    my ($pkg, $sym, $code) = @_;


    my $name = *{ $sym }{NAME};

    no warnings 'redefine';

    *{ $sym } = sub {
        log_message("Entering sub $pkg\:\:$name");
        $code->( @_ );
    };
}

sub foo : Log { 
    # this will be logged
}
friedo
+2  A: 

friedo's answer is incredibly nifty if that degree of flexibility is required.

OTOH you can continue to use the Apache error_log to record this data just by using $c->log->info() or one of its siblings. It's fairly trivial to extend Catalyst::Log to report other sorts of messages. I use a $c->log->sql() variant that writes SQL out to the error_log that's been run through SQL::Beautify, for example.

I can imagine something along the lines of

sub auto {
    ...
    $c->log->audit(sprintf("%s called by %s", $c->action->reverse, $c->userid));
    ...
}

Putting it at the start (in auto) is not what you wanted, but it's definitely less problematic, since you know it will always get called, unlike end handlers.

RET