Skip Menu |

This queue is for tickets about the Log-Dispatch-File-Rolling CPAN distribution.

Report information
The Basics
Id: 95900
Status: open
Priority: 0/
Queue: Log-Dispatch-File-Rolling

People
Owner: Nobody in particular
Requestors: FRACTAL [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: (no value)



Subject: Feature request: Maintain a current symlink to latest log file
First off, thanks for this module. We've used to generate many many gigs of logs. However, most of the other logging systems we've used maintain a ".current" symlink to the latest log file. This is handy because you can do "tail -F app.current" and see an uninterrupted tail of the logs without worrying about rollovers. I would really appreciate it if Log::Dispatch::File::Rolling could do something similar so I'm attaching a patch that adds this feature. If you feel that this is at the wrong layer, no worries. I'll make a module that sub-classes your module. It feels like it makes sense here though since it's related to the "rolling" aspect of the logging. Cheers, Doug
Subject: current-symlink.patch
diff --git a/lib/Log/Dispatch/File/Rolling.pm b/lib/Log/Dispatch/File/Rolling.pm index 2928c1e..957deba 100755 --- a/lib/Log/Dispatch/File/Rolling.pm +++ b/lib/Log/Dispatch/File/Rolling.pm @@ -62,6 +62,10 @@ sub new { $self->{filename} = $self->_createFilename(); } + if (exists $p{current_symlink}) { + $self->{current_symlink} = $p{current_symlink}; + } + $self->{rolling_fh_pid} = $$; $self->_make_handle(); @@ -79,7 +83,7 @@ sub log_message { # parts borrowed from Log::Dispatch::FileRotate, Thanks! } if ( $self->{close} ) { - $self->_open_file; + $self->_rolling_open_file; $self->_lock(); my $fh = $self->{fh}; print $fh $p{message}; @@ -90,7 +94,9 @@ sub log_message { # parts borrowed from Log::Dispatch::FileRotate, Thanks! my $inode = (stat($self->{fh}))[1]; # get real inode my $finode = (stat($self->{filename}))[1]; # Stat the name for comparision if(!defined($finode) || $inode != $finode) { # Oops someone moved things on us. So just reopen our log - $self->_open_file; + $self->_rolling_open_file; + } elsif (!$self->{current_symlink_inited}) { + $self->_update_current_symlink; } $self->_lock(); my $fh = $self->{fh}; @@ -98,7 +104,7 @@ sub log_message { # parts borrowed from Log::Dispatch::FileRotate, Thanks! $self->_unlock(); } else { $self->{rolling_fh_pid} = $$; - $self->_open_file; + $self->_rolling_open_file; $self->_lock(); my $fh = $self->{fh}; print $fh $p{message}; @@ -106,6 +112,37 @@ sub log_message { # parts borrowed from Log::Dispatch::FileRotate, Thanks! } } +sub _rolling_open_file { + my $self = shift; + + $self->_open_file; + + $self->_update_current_symlink; +} + +sub _update_current_symlink { + my $self = shift; + + return if !exists $self->{current_symlink}; + + my $current_symlink_value = readlink($self->{current_symlink}); + + if (!defined $current_symlink_value || $current_symlink_value ne $self->{filename}) { + my $temp_symlink_file = "$self->{current_symlink}.temp$$"; + unlink($temp_symlink_file); + + symlink($self->{filename}, $temp_symlink_file) + || die "unable to create symlink '$temp_symlink_file': $!"; + + if (!rename($temp_symlink_file, $self->{current_symlink})) { + unlink($temp_symlink_file); + die "unable to overwrite symlink '$self->{current_symlink}': $!"; + } + } + + $self->{current_symlink_inited} = 1; +} + sub _lock { # borrowed from Log::Dispatch::FileRotate, Thanks! my $self = shift; flock($self->{fh},LOCK_EX); @@ -207,6 +244,13 @@ needed regularly as this module also supports logfile sharing between processes, but if you've got a high load on your logfile or a system that doesn't support flock()... +=item current symlinks + +If you pass in C<current_symlink> to the constructor, it will create a +symlink at your provided filename. This symlink will always link to the +most recent log file. You can then use C<tail -F> to monitor an application's +logs with no interruptions even when the filename rolls over. + =back =head1 METHODS diff --git a/t/6currentsymlink.t b/t/6currentsymlink.t new file mode 100755 index 0000000..ce81c4e --- /dev/null +++ b/t/6currentsymlink.t @@ -0,0 +1,89 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl 6currentsymlink.t' + +######################### + +# change 'tests => 1' to 'tests => last_test_to_print'; + +use Test; +BEGIN { plan tests => 9 }; +use Log::Dispatch; +use Log::Dispatch::File::Rolling; +ok(1); # If we made it this far, we're ok. + +#########################1 + +my $dispatcher = Log::Dispatch->new; +ok($dispatcher); + +#########################2 + +my $curr_symlink_filename = 'currsym'; + +my %params = ( + name => 'file', + min_level => 'debug', + filename => 'logfile', + current_symlink => $curr_symlink_filename, +); + +my $Rolling = Log::Dispatch::File::Rolling->new(%params); +ok($Rolling); + +#########################3 + +$dispatcher->add($Rolling); + +ok(1); + +#########################4 + +my $message = 'logtest id ' . int(rand(9999)); + +$dispatcher->log( level => 'info', message => $message ); + +ok(1); + +#########################5 + +$dispatcher = $Rolling = undef; + +ok(1); + +#########################6 + +my @logfiles = glob("logfile.2*"); + +ok(scalar(@logfiles) == 1 or scalar(@logfiles) == 2); + +#########################7 + +my $content = ''; + +foreach my $file (@logfiles) { + open F, '<', $file; + local $/ = undef; + $content .= <F>; + close F; +} + +ok($content =~ /$message/); + +my $content2 = ''; + +{ + open F, '<', $curr_symlink_filename; + local $/ = undef; + $content2 .= <F>; + close F; +} + +ok($content2 =~ /$message/); + +foreach my $file (@logfiles) { + unlink $file; +} + +unlink $curr_symlink_filename; + +#########################8
On 2014-05-23 10:03:04, FRACTAL wrote: Show quoted text
> First off, thanks for this module. We've used to generate many many > gigs of logs.
FWIW, you might find Log-Dispatch-File-Stamped to be useful too - it takes a slightly different approach, and supports all the Log::Dispatch::File options.
Thanks for the pointer, I'll check it out. On Fri May 23 14:00:47 2014, ETHER wrote: Show quoted text
> FWIW, you might find Log-Dispatch-File-Stamped to be useful too - it > takes a slightly different approach, and supports all the > Log::Dispatch::File options.
On Fri May 23 13:03:04 2014, FRACTAL wrote: Show quoted text
> First off, thanks for this module. We've used to generate many many > gigs of logs.
Thank you for using it! I like the idea. I'll integrate your patch into the next version. However, I want to go through the patch before I do, so it'll take at least 2 weeks for me to have the time...
On Fri May 23 14:00:47 2014, ETHER wrote: Show quoted text
> FWIW, you might find Log-Dispatch-File-Stamped to be useful too - it > takes a slightly different approach, and supports all the > Log::Dispatch::File options.
Actually, if you look at the bottom if Log::Dispatch::File::Rolling's documentation you'll find "Based on: Log::Dispatch::File::Stamped [...]"... ;) I haven't check how Log::Dispatch::File::Stamped changed since 2003, but I implemented ::Rolling because ::Stamped missed some features we needed. I may be wrong, but I think it still is not fork()-safe.
No worries, thanks for looking at it when you get a chance. On Fri May 23 14:41:56 2014, JACOB wrote: Show quoted text
> On Fri May 23 13:03:04 2014, FRACTAL wrote:
> > First off, thanks for this module. We've used to generate many many > > gigs of logs.
> > Thank you for using it! > > I like the idea. I'll integrate your patch into the next version. > > However, I want to go through the patch before I do, so it'll take at > least 2 weeks for me to have the time...
I didn't really want to add yet another file logging module to CPAN so I'm sorry to say I have forked this module: https://metacpan.org/release/FRACTAL/Log-File-Rolling-0.100 My main reasons were the lack of the symlink feature I described in this ticket, the bug where an unformatted log filename (with the % characters) is created alongside your logs (which is embarrassing to explain to operations), and getting away from Log::Dispatch/Log4Perl bloat... ETHER: I checked out Log::Dispatch::File::Stamped, but I don't think it provides the symlink feature I described in this ticket. How do you handle the "I just want to tail -F this app's logs and not worry about roll-overs" issue, or does this just not come up in your workflow? I do like the filename caching in ::Stamped and I implemented similar in mine. I also like that you're using standard strftime not the zany Log4Perl format. I chose to use Time::Piece instead of POSIX for strftime since the POSIX module is pretty memory heavy. Cheers, Doug On Mon May 26 09:46:21 2014, FRACTAL wrote: Show quoted text
> No worries, thanks for looking at it when you get a chance. > > On Fri May 23 14:41:56 2014, JACOB wrote:
> > On Fri May 23 13:03:04 2014, FRACTAL wrote:
> > > First off, thanks for this module. We've used to generate many many > > > gigs of logs.
> > > > Thank you for using it! > > > > I like the idea. I'll integrate your patch into the next version. > > > > However, I want to go through the patch before I do, so it'll take at > > least 2 weeks for me to have the time...
> >