no ident specified when using Log::Dispatchouli (MooseX::Role::Loggable)

Sometimes when working with the lovely MooseX::Role::Loggable you might encounter the following fatal error:

no ident specified when using Log::Dispatchouli at Loggable.pm line 117.

I keep running into this and resolving this each time without remembering what this means, so I keep having to debug it all over again. While I've documented this issue in the new version of MooseX::Role::Loggable, I'd like to explain it here as well.

When using lazy builders, not Moo nor Moose promise an order of attribute inflation. That means that some attributes might exist before others.

MooseX::Role::Loggable adds a lazy attribute for Log::Dispatchouli. If you don't call any logging method, you will not pay for the extra of Log::Dispatchouli (except the "use" statement for loading it). That attribute depends on other attributes which aren't lazy, but still might get inflated only after whatever attribute whose builder calls a logging method. Wait, let me rephrase!

You have a db attribute which has a builder that connects to the database. You add a log_debug method before it just so you can debug when the database is being connected. It looks like this:

has db => (
    is      => 'ro',
    builder => '_build_db',
);

sub _build_db {
my $self = shift;
$self->log_debug('Connecting to DB');
...
}

You call log_debug which calls the builder for the logger object, which now depends on the ident attribute, which... oh my, it hasn't been inflated yet. Damn!

The solution is simple: you make your attribute lazy, and then call for its inflation right after compilation phase, in the BUILD method.

has db => (
    is      => 'ro',
    lazy    => 1,
    builder => '_build_db',
);

sub BUILD {
my $self = shift;
$self->db;
}

That will make sure that all non-lazy attributes are built before your db builder is run. Viola!

Hope this helps anyone who stumbles upon this. :)

Leave a comment

About Sawyer X

user-pic Gots to do the bloggingz