=pod =head1 NAME Log::Shiras - A Moose based logging and reporting tool =begin html perl version Build Status Coverage Status github version CPAN version kwalitee =end html =head1 SYNOPSIS #!perl use Modern::Perl; use lib 'lib', '../lib',; use Log::Shiras::Unhide qw( :debug);# use Log::Shiras::Switchboard; use Log::Shiras::Telephone; use Log::Shiras::Report::Stdout; $| = 1; sub shout_at_me{ my $telephone = Log::Shiras::Telephone->new( report => 'run' ); $telephone->talk( carp_stack => 1, level => 'info', message =>[ @_ ] ); } ###LogSD warn "lets get ready to rumble..."; my $operator = Log::Shiras::Switchboard->get_operator( name_space_bounds =>{ main =>{ UNBLOCK =>{ # UNBLOCKing the run reports (destinations) # at the 'main' caller name_space and deeper run => 'trace', }, }, }, reports =>{ run =>[ Log::Shiras::Report::Stdout->new, ], }, ); ###LogSD warn "Getting a Telephone"; my $telephone = Log::Shiras::Telephone->new( report => 'run' ); $telephone->talk( message => 'Hello World 1' ); ###LogSD warn "message was sent to the report 'run' without sufficient permissions"; $telephone->talk( level => 'info', message => 'Hello World 2' ); ###LogSD warn "message sent with sufficient permissions"; shout_at_me( 'Hello World 3' ); ##################################################################################### # Synopsis screen output # 01: Using Log::Shiras::Unhide-v0.29_1 strip_match string: (LogSD) at ../lib/Log/Shiras/Unhide.pm line 87. # 02: lets get ready to rumble... at log_shiras.pl line 15. # 03: Getting a Telephone at log_shiras.pl line 30. # 04: message was sent to the report 'run' without sufficient permissions at log_shiras.pl line 33. # 05: | level - info | name_space - main # 06: | line - 0034 | file_name - log_shiras.pl # 07: :( Hello World 2 ): # 08: message sent with sufficient permissions at log_shiras.pl line 35. # 09: | level - info | name_space - main::shout_at_me # 10: | line - 0012 | file_name - log_shiras.pl # 11: :( Hello World 3 # 12: at ..\lib\Log-Shiras\lib\Log\Shiras\Telephone.pm line 148. # 13: Log::Shiras::Telephone::talk(Log::Shiras::Telephone=HASH(0x144cc18), "carp_stack", 1, "level", "info", "message", ARRAY(0xa14cd8)) called at log_shiras.pl line 12 # 14: main::shout_at_me("Hello World 3") called at log_shiras.pl line 36 ): ##################################################################################### =head1 DESCRIPTION L - A small subspecies of Moose found in the western United States (of America). This is L you can choose from in CPAN. The ultimate goal of this package is to add name-space control to any of your programs outputs that you want name-space control of. As the package stands today there are three relevant name-spaces. First, the file name-space, file name-space is the name-space that we apply to specific files (modules or scripts). The file name-space in this package is treated as flat (no heirarchy) and is managed using L. File name-space filtering is therefore done at compile time with no run time changes available. The second name-space is a run time caller name-space that can be adjusted as the program operates. Caller name-space is applied to the source of the output. The caller namespace also allows for urgency levels to be assigend to each source of information. The caller namespace is hierarchical which allows filtering to be applied lower in the hierarchy and remain in force farther out in the branch. Caller name-space and urgency can be changed during run-time. Finally, there is a destination name-space. Not all sources will wish to call the same destination. Destination name-space is flat and less flexible but still somewhat editable at run time. Caller name-space, caller urgency levels, and desination name-space are all stiched together using permissions. Permissions can also be changed at run-time. To sort of stich these concepts together mentally I have used terminology associated with the old land line telephone system. Caller name-space is managed through a L class. Permissions are managed through a L with switchboard operators. And destinations are called L. This last term does not follow the terminology of the old land lines since communication through this package is one direction. I All in all this can create a complex name-space landscape. For this package all name-spaces in the run environment are shared and caution should be used to manage uniqueness. I would encourage starting simple and working out if you don't have a lot of logging experience. This package is most related in concept to L. =head2 Acknowledgement I was a strong user of L and L prior to writing this package. I borrowed heavily from them when writing this. =head1 Differentiation Why choose this Logger over one of the many other options? Here are some implementation decisions that I made that may or may not help that decision. Many if not all of these elements exist in other loggers. I don't think they all exist together in any other logger. =head2 Buffer behavior This package has a destination buffer in the switchboard (default off) for each report name. This allows for some messages to be discarded after they were collected based on branches in the code. A use case for this is when you are recursively parsing some logic but only want to log the actions in the path that yielded results. This is different than a print buffer that always goes to the output but the send is just delayed. =head2 A wrapper class for messages L is it's own class and can be used to customize how messages are sent as well as allowing more flexibility in the format of sent messages. =head2 L A dedicated test module for testing logged messages that will capture messages at the switchboard level rather than requiring the implementation of the final report destination to test output. Specifically, implementation of L code can be tested without also implementing L code. This is done through a hook built into the L. The test methods include several ways of checking for output existence. I =head2 Headers The 'Report' class in this package for CSV files L only adds the header to a file when it is new. If the file connection is dropped and then reconnected the header will not be added again if the file is not empty. It will also manage (or at least warn) on header drift for the first added row. =head2 Custom formatting I wanted to be able to use method calls and code references when formatting 'Report' output. The L Role for the 'Report' class does just that. This varies from Log::Log4perl's 'PatternLayout' as it operates on an array ref or hashref rather than a string. There may be a string formatter in the future since I half wrote one but I talked myself out of it in favor of an array ref manipulation scheme. =head2 L This package is Moose based. You probably already have an opinion on Moose so this may tip you one way or the other. =head2 Multiple output paths Allowing more than one destination using the same logging software in a script space is helpful. This means you can write your output to multiple sources without wiring up the connection or finishing the destination definition until later. See also L. =head2 Source filtering Excessive outputs for troubleshooting or outputs that are only used in rare circumstances will overburden code. Having a source filter will allow the code to remain in source control (no retyping and deleting print statements) while still not burdening run time operations generally (unless you need the outputs). See also L and L =head2 Custom urgency levels If you feel the need you can re-define the urgency level words =head2 Re-routing print statements See L =head2 Re-routing warn statements See L =head2 Message meta data When messages are sent the switchboard bundles them with meta-data. Mostly this is basic stuff like where did I come from and when was I made. For details review L =head1 Build/Install from Source =over B<1.> Download a compressed file with the code B<2.> Extract the code from the compressed file. =over If you are using tar this should work: tar -zxvf Log-Shiras-v0.xx.tar.gz =back B<3.> Change (cd) into the extracted directory. B<4.> Run the following (For Windows find what version of make was used to compile your perl) perl -V:make (for Windows below substitute the correct make function (s/make/dmake/g)?) >perl Makefile.PL >make >make test >make install # As sudo/root >make clean =back =head1 SUPPORT =over =item L =back =head1 TODO =over B<1.> Build a Database connection Report role B<2.> Add TapFatal with a fatal gracefully feature B<3.> Incorporate L with logging? http://tinypig2.blogspot.com/2016/09/tattletale-variables.html =back =head1 AUTHOR =over =item Jed Lund =item jandrew@cpan.org =back =head1 COPYRIGHT This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this package This software is copyrighted (c) 2012, 2016 by Jed Lund =head1 DEPENDANCIES See individual modules =head1 SEE ALSO =over =item L =item L =item L =item L =item L =back =cut