Makes a lot of use of caller. This makes it pretty hard for somebody else to wrap your code if they want an extra layer of abstraction.
A better way of doing it is something like this:
sub import {
my $me = shift;
my $opts = ref($_[0]) ? shift : { for => scalar caller };
my %wanted = map { $_ => 1 } @_;
*{ $opts->{for} . "::logf" } = $me->_generate_logf($opts) if $wanted
+{logf};
*{ $opts->{for} . "::logw" } = $me->_generate_logw($opts) if $wanted
+{logw};
...;
}
sub _generate_logf {
shift;
my $opts = shift;
return sub {
my $msg = shift;
my $log = _get_logger($opts->{for}, shift);
return unless $log->is_fatal;
$log->fatal($msg);
die "\n";
}
}
...;
Exporters like Exporter::Tiny and Sub::Exporter support this kind of pattern — generating subs to export which have been specialized for whatever class is importing them — more easily than Exporter.pm. This technique will not only help avoid reliance on caller, making it easier for people to wrap your module, but will also help you further down the line when you are looking at making it more configurable.
Also, you didn't use strict or use warnings in your module. (And there's at least one part which would fail under use strict and currently could cause an issue under very contrived circumstances.)