From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

use 5.006; use strict; use warnings; our $VERSION = '1.01';
use Fcntl qw/ :flock /; use Clone;
sub new {
my ($class, $file, $level, %jsonl_args) = @_;
bless {
_file => $file,
_jsonl => JSON::Lines->new( %jsonl_args ),
_level => defined $level ? $level : 8,
_levels => {
emerg => 1,
alert => 2,
crit => 3,
err => 4,
warning => 5,
notice => 6,
info => 7,
debug => 8,
},
}, $class;
}
sub file { $_[0]->{_file} }
sub levels { $_[0]->{_levels} }
sub level { $_[0]->{_level} }
sub jsonl {
$_[0]->{_jsonl}->clear_stream;
$_[0]->{_jsonl};
}
sub log {
my($self, $level, $msg) = @_;
die "Invalid level ${level} passed to Log::JSON::Lines->log"
unless $self->levels->{$level};
return if $self->levels->{$level} > $self->level;
$msg = ! ref $msg ? { message => $msg } : Clone::clone($msg);
$msg->{level} = $level;
my ($epoch, $microseconds) = Time::HiRes::gettimeofday;
$msg->{timestamp} = sprintf "%s.%06.0f+00:00",
POSIX::strftime("%Y-%m-%dT%H:%M:%S", gmtime($epoch)),
$microseconds;
my @caller; my $i = 0; my @stack;
while(@caller = caller($i++)){
next if $caller[0] eq 'Log::JSON::Lines';
$stack[$i+1]->{module} = $caller[0];
$stack[$i+1]->{file} = $1 if $caller[1] =~ /([^\/]+)$/;;
$stack[$i+1]->{line} = $1 if $caller[2] =~ /(\d+)/;
$stack[$i]->{sub} = $1 if $caller[3] =~ /([^:]+)$/;
}
$msg->{stacktrace} = join '->', reverse map {
my $module = $_->{module} !~ m/^main$/ ? $_->{module} : $_->{file};
$_->{sub}
? $module . '::' . $_->{sub} . ':' . $_->{line}
: $module . ':' . $_->{line}
} grep {
$_ && $_->{module} && $_->{line} && $_->{file}
} @stack;
delete $msg->{stacktrace} unless $msg->{stacktrace};
$msg = $self->jsonl->add_line($msg);
open my $fh, ">>", $self->{_file} or die "Cannot open log file $self->{_file}: $!";
flock $fh, LOCK_EX;
print $fh $msg;
close $fh;
$msg;
}
sub emerg {
my $self = shift;
$self->log('emerg', @_);
}
sub alert {
my $self = shift;
$self->log('alert', @_);
}
sub crit {
my $self = shift;
$self->log('crit', @_);
}
sub err {
my $self = shift;
$self->log('err', @_);
}
sub warning {
my $self = shift;
$self->log('warning', @_);
}
sub notice {
my $self = shift;
$self->log('notice', @_);
}
sub info {
my $self = shift;
$self->log('info', @_);
}
sub debug {
my $self = shift;
$self->log('debug', @_);
}
=head1 NAME
Log::JSON::Lines - Log in JSONLines format
=head1 VERSION
Version 1.01
=cut
=head1 SYNOPSIS
Quick summary of what the module does.
use Log::JSON::Lines;
my $logger = Log::JSON::Lines->new(
'/var/log/definition.log',
4,
pretty => 1,
canonical => 1
);
$logger->log('info', 'Lets log JSON lines.');
$logger->emerg({
message => 'emergency',
definition => [
'a serious, unexpected, and often dangerous situation requiring immediate action.'
]
});
$logger->alert({
message => 'alert',
definition => [
'quick to notice any unusual and potentially dangerous or difficult circumstances; vigilant.'
]
});
$logger->crit({
message => 'critical',
definition => [
'expressing adverse or disapproving comments or judgements.'
]
});
$logger->err({
message => 'error',
definition => [
'the state or condition of being wrong in conduct or judgement.'
]
});
# the below will not log as the severity level is set to 4 (error)
$logger->warning({
message => 'warning',
definition => [
'a statement or event that warns of something or that serves as a cautionary example.'
]
});
$logger->notice({
message => 'notice',
definition => [
'the fact of observing or paying attention to something.'
]
});
$logger->info({
message => 'information',
definition => [
'what is conveyed or represented by a particular arrangement or sequence of things.'
]
});
$logger->debug({
message => 'debug',
definition => [
'identify and remove errors from (computer hardware or software).'
]
});
=head1 DESCRIPTION
This module is a simple logger that encodes data in JSON Lines format.
JSON Lines is a convenient format for storing structured data that may be processed one record at a time. It works well with unix-style text processing tools and shell pipelines. It's a great format for log files. It's also a flexible format for passing messages between cooperating processes.
=head1 SUBROUTINES/METHODS
=head2 new
Instantiate a new Log::JSON::Lines object. This expects a filename and optionally a level which value is between 0 to 8 and params that will be passed through to instantiate the JSON::Lines object.
my $logger = Log::JSON::Lines->new($filename, $severity_level, %JSON::Lines::params);
=head2 file
Returns the current log file name.
$logger->file();
=head2 levels
Returns the severity level mapping.
$logger->levels();
=head2 level
Returns the current severity level.
$logger->level();
=head2 jsonl
Returns the JSON::Lines object used to encode the line.
$logger->jsonl();
=head2 log
Log a message to the specified log file. This expects a severity level to be passed and either a string message or hashref containing information that you would like to log.
$logger->log($severity, $message);
=head2 emerg - 1
Log a emerg line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->emerg($message);
=head2 alert - 2
Log a alert line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->alert($message);
=head2 crit - 3
Log a critical line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->crit($message);
=head2 err - 4
Log a error line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->err($message);
=head2 warning - 5
Log a warning line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->warning($message);
=head2 notice - 6
Log a notice line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->notice($message);
=head2 info - 7
Log a info line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->info($message);
=head2 debug - 8
Log a debug line to the specified log file. This expects either a string or hashref containing information that you would like to log.
$logger->debug($message);
=head1 AUTHOR
LNATION, C<< <email at lngation.org> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-log-json-lines at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Log-JSON-Lines>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Log::JSON::Lines
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
=item * Search CPAN
=back
=head1 ACKNOWLEDGEMENTS
=head1 LICENSE AND COPYRIGHT
This software is Copyright (c) 2020->2025 by LNATION.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)
=cut
1; # End of Log::JSON::Lines