Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 42 additions & 27 deletions lib/LANraragi/Utils/Logging.pm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use Exporter 'import';
our @EXPORT_OK = qw(get_logger get_plugin_logger get_logdir get_lines_from_file);

our %LOGGER_CACHE;
our $RLOG_UNSUPPORTED_WARNED = 0;

# Get the Log folder.
sub get_logdir {
Expand Down Expand Up @@ -71,45 +72,59 @@ sub get_logger {
undef $log;
}

# Create and cache logger with retry + backoff + jitter
# Report the first logger init failure if exists
my $tries = 0;
my $lockdir = $ENV{LRR_LOG_LOCK_DIRECTORY} // get_temp();
my $rlog_supported = LANraragi::Utils::RotatingLog::is_supported($lockdir);

my $tries = 0;
my $first_error;
while ( $tries < 3 ) {
my $retry_error;
{
local $@;
eval {
$log = LANraragi::Utils::RotatingLog->new(
path => $logpath,
level => 'info',
logfile => $logfile,
tempdir => get_temp()
);
};
$retry_error = $@;
}
if ( $rlog_supported ) {
# Create and cache RotatingLog with retry + backoff + jitter
# Report the first logger init failure if exists
while ( $tries < 3 ) {
my $retry_error;
{
local $@;
eval {
$log = LANraragi::Utils::RotatingLog->new(
path => $logpath,
level => 'info',
logfile => $logfile,
lockdir => $lockdir
);
};
$retry_error = $@;
}

unless ( $retry_error ) {
configure_logger( $log );
$LOGGER_CACHE{$cache_key} = $log;
last;
}
unless ( $retry_error ) {
configure_logger( $log );
$LOGGER_CACHE{$cache_key} = $log;
last;
}

$first_error //= $retry_error;
Time::HiRes::sleep(rand());
$tries++;
$first_error //= $retry_error;
Time::HiRes::sleep(rand());
$tries++;

}
}

# Fall back to Mojo::Log if retry doesn't work
# Fall back to Mojo::Log if RotatingLog isn't supported or failed to initialize
if ( !$log ) {
$log = Mojo::Log->new(
path => $logpath,
level => 'info'
);
configure_logger( $log );
$log->error("RotatingLog init failed, falling back to Mojo::Log. First error: $first_error");

if ( !$rlog_supported ) {
$LOGGER_CACHE{$cache_key} = $log;
unless ( $RLOG_UNSUPPORTED_WARNED ) {
$log->warn("RotatingLog not supported on $lockdir; using Mojo::Log without log rotation.");
$RLOG_UNSUPPORTED_WARNED = 1;
}
} else {
$log->error("RotatingLog init failed, falling back to Mojo::Log. First error: $first_error");
}
} elsif ( $tries > 0 ) {
$log->warn("RotatingLog initialized after $tries failures. First error: $first_error");
}
Expand Down
25 changes: 23 additions & 2 deletions lib/LANraragi/Utils/RotatingLog.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ BEGIN {
}

has 'logfile';
has 'tempdir'; # Where to store lockfiles
has 'lockdir'; # Where to store lockfiles
has 'lockpid'; # Track which PID opened the current lock file handle.

has counter => sub { 0 }; # number of logs emitted
Expand All @@ -45,7 +45,7 @@ has lockpath => sub {
my $path = $self->path;
my $mf = Mojo::File->new($path);
my $base = $mf->basename;
my $lockpath = $self->tempdir . "/$base.lock";
my $lockpath = $self->lockdir . "/$base.lock";
return $lockpath;
};

Expand Down Expand Up @@ -315,4 +315,25 @@ sub get_win32_fh {
return *FH;
}

# Check whether filesystem supports flock.
# https://github.com/Difegue/LANraragi/issues/1556
our $SUPPORTED;
sub is_supported {
return $SUPPORTED if defined $SUPPORTED;

my $lockdir = shift;
my $supported = 0;
my $probe_path = "$lockdir/.lrr-flock-probe.$$";

# do a flock hit
if ( open( my $fh, '>', $probe_path ) ) {
$supported = flock( $fh, LOCK_EX | LOCK_NB ) ? 1 : 0;
close $fh;
unlink $probe_path;
}

$SUPPORTED = $supported;
return $SUPPORTED;
}

1;
Loading