NAME

Log::Shiras::Switchboard - Log::Shiras message screening and delivery

DESCRIPTION

Shiras - A small subspecies of Moose found in the western United States (of America).

This is the class for message traffic control in the 'Log::Shiras' package. For a general overview of the whole package see the top level documentation . Traffic is managed using name spaces. For the purposes of logging this package uses three types of name space with an additional wrapper. The first name space is the source code name space. This name space is managed by putting labeled comment tags in the code and then exposing them with a source code filter. This is mostly used when you want to have debug code available that does not impact your regular runs of the code. This space is managed by Log::Shiras::Unhide. The source code name space is a flat list. The next name space is the caller name space. The caller name space is assigned in the code with targeted embedded statements to the master_talk method. Boilerplate for managing these calls can be found in Log::Shiras::Telephone. If you wish to inject name_space modifications from the calling script you can use the role Log::Shiras::LogSpace. The caller namespace can be heirarchical and represented by a Hash of hashrefs. The final name space is the destination or report namespace. This namespace is flat but each position can contain more than one actual report. Any message to a specific report name is sent to all reports assigned to that name. Managing the traffic between the caller name space and the report name space is done by setting allowed urgency levels in the name space bounds., urgency levels, and report names.

In order to stich all this together at run time this is a singleton class and so 'new' is the wrong way to get a new instance of this class. The right way is to use the method get_operator. The upside of using a singleton is you can write a caller (message source) with an intended urgency and destination name and not build the actual destination till run time.

Initialization

This class does not use ->new. Use 'get_operator' instead.

get_operator( %args )

    Definition: This method replaces the call to ->new or other instantiation methods. The Log::Shiras::Switchboard class is a MooseX::Singleton and as such needs to be called in a slightly different fashion. This method can be used to either connect to the existing switchboard or start the switchboard with new settings. Each call to this method will implement the settings passed in %args merging them with any pre-existing settings. Where pre-existing settings disagree with new settings the new settings take precedence. So be careful!

    Accepts: [%args|$args_ref|full/file/path.(json|yml)] %args are treated the same as attributes passed to other class style calls to new. The data can either be passed as a fat comma list or a hashref. If this method receives a string it will try to treat it like a full file path to a JSON or YAML file with the equivalent $args_ref stored. See conf_file to pass a file path and arguments.

    Returns: an instance of the Log::Shiras::Switchboard class called an 'operator'. This operator can act on the switchboard to perform any of the methods including any attribute access methods.

Attributes

Data passed to get_operator when creating an instance. For modification of these attributes see the remaining Methods used to act on the operator. DO NOT USE 'Log::Shiras::Switchboard->new' to get a new class instance

name_space_bounds

    Definition: This attribute stores the boundaries set for the name-space management of communications (generally from Log::Shiras::Telephone) message data sources. This value ref defines where in the name-space, to which reports, and at what urgency level messages are allows to pass. Name spaces are stored as a hash of hashes that goes as deep as needed. To send a message between a specific caller name-space and a named 'report' destination this hash ref tree must have the key 'UNBLOCK' at or below the target name space in the hashref tree. The UNBLOCK key must have as a value a hashref with report names as keys and the minimum allowed pass level as the value. That(ose) report(s) then remain(s) open to communication farther out on the caller name space branch until a new UNBLOCK key sets different permission level or a 'BLOCK' key is implemented. The difference between a BLOCK and UNBLOCK key is that a BLOCK key value only needs to contain report keys (the key values are unimportant). Any level assigned to the report name by a BLOCK key is ignored and all communication at that point and further in the branch is cut off all for all deeper levels of the name space branch for that report. There are a couple of significant points for review;

      * UNBLOCK and BLOCK should not be used as branch of the telephone name-space tree

      * If a caller name-space is not listed here or a report name is not explicitly UNBLOCKed then the message is blocked by default.

      * Even though 'log_file' is the default report it is not 'UNBLOCK'ed by default. It must be explicitly UNBLOCKed to be used.

      * UNBLOCKing or BLOCKing of a report can occur independant of it's existance. This allows the addition of a report later and have it work upon its creation.

      * If an UNBLOCK and BLOCK key exist at the same point in a name space then the hashref associated with the UNBLOCK key is evaluated first and the hashref associated with the BLOCK key is evaluated second. This means that the BLOCK command can negate a report UNBLOCKing level.

      * Any name space on the same branch (but deeper) than an UNBLOCK command remains UNBLOCKed for the listed report urgency levels until a deeper UNBLOCK or BLOCK is registered for that report.

      * When UNBLOCKing a report at a deeper level than an initial UNBLOCK setting the new level can be set higher or lower than the initial setting.

      * BLOCK commands are only valuable deeper than an initial UNBLOCK command. The Tree trunk starts out 'BLOCK'ed by default.

      * All BLOCK commands completly block the report(s) named for that point and deeper independant of the urgency value associated with report name key in the BLOCK hashref.

      * The hash key whos hashref value contains an UNBLOCK hash key is the point in the NameSpace where the report is UNBLOCKed to the defined level.

    Default all caller name-spaces are blocked (no reporting)

    Range The caller name-space is stored and searched as a hash of hashes. No array refs will be correctly read as any part of the name-space definition. At each level of the name-space the switchboard will also recognize the special keys 'UNBLOCK' and 'BLOCK' in that order. As a consequence UNBLOCK and BLOCK are not supported as name-space elements. Each UNBLOCK (or BLOCK) key should have a hash ref of report name keys as it's value. The hash ref of report name keys should contain the minimum allowed urgency level down to which the report is UNBLOCKed. The value associated with any report key in a BLOCK hash ref is not tested since BLOCK closes all reporting from that point and deeper.

    Example

    name_space_bounds =>{
    	Name =>{#<-- name-space
    		Space =>{#<-- name-space
    			UNBLOCK =>{#<-- Telephone name-space 'Name::Space' is unblocked
    				log_file => 'warn'#<-- but only for calls to the 'log_file' report
    			},					  #     with an urgency of 'warn' or greater
    			Boundary =>{#<-- name-space
    				UNBLOCK =>{#<-- The deeper space 'Name::Space::Boundary' receives a new setting
    					log_file => 'trace',#<-- messages are allowed at 'trace' urgency now
    					special_report => 'eleven',<-- a new report and level are added
    				},
    				Place =>{},<-- deeper name-space - log_file permissions still 'trace'
    			},
    		},
    	},
    }

    Warning All active name-space boundaries must coexist in the singleton. There is only one master name-space for the singleton. New calls for object intances can overwrite existing object instances name-space boundaries. No cross instance name-space protection is done. This requires conscious managment! It is entirely possible to call for another operator in the same program space with overlapping name-space boundaries that changes reporting for a callers originally used in the context of the original operator.

    attribute methods Methods provided to adjust this attribute

      get_name_space

        Definition: Returns the full program namespace

reports

    Definition: This attribute stores report names and associated composed class instances for that name. The attribute expects a hash of arrays . Each hash key is the report name and the array contains the report instances associated with that name. Each passed array object will be tested to see if it is an object that can( 'add_line' ). If not this code will try to coerce the passed reference at the array position into an object using MooseX::ShortCut::BuildInstance.

    Default no reports are active. If a message is sent to a non-existant report name then nothing happens unless self reporting is fully enabled. Then it is possible to collect various warning messages related to the failure of a message.

    Example

    reports =>{
    	log_file =>[<-- report name
    			Print::Wisper->new,#<-- a reporting instance of a class ( see Synopsis )
    			{#<-- MooseX::ShortCut::BuildInstance definition for a different report
    				package => 'Print::Excited',#<-- name this (new) class
    				add_methods =>{
    					add_line => sub{#<-- ensure it has an 'add_line' method
    						shift;
    						my @input = ( ref $_[0]->{message} eq 'ARRAY' ) ?
    										@{$_[0]->{message}} : $_[0]->{message};
    						my @new_list;
    						map{ push @new_list, $_ if $_ } @input;
    						chomp @new_list;
    						print '!!!' . uc(join( ' ', @new_list)) . "!!!\n";
    					}
    				},
    			}
    		],
    	other_name =>[],#<-- name created but no report instances added (maybe later?)
    },

    warning: any re-definition of the outputs for a report name will only push the new report instance onto the existing report array ref. To remove an existing report output instance you must delete all report instances and the report name and then re-implement the report name and it's outputs.

    attribute methods Methods provided to adjust this attribute

      get_reports

        Definition: Returns the full report hashref of arrays

      has_no_reports( $report )

        Definition: Checks if the $report requested has a key in the hashref

      get_report( $report )

        Definition: Returns the array ref of stored report objects for that $report

      remove_reports( $report1 [, $report2] )

        Definition: Deletes all storeage (and use of) $report1 etc.

logging_levels

    Definition: Each report name recognizes 12 different logging levels [0..11] (They go to 11! :). Each position within the logging levels can be assigned a name that is not case sensitive. Either the position integer or the name assigned to that position can be used to describe the urgency 'level'. Each message can be sent with name. The urgency level of a message can be defined for each sent message. If you do not wish to use the default name for each logging position or you wish to name the logging positions that are not named then use this attribute. Not all of the elements need to be defined. There can be gaps between defined levels but counting undefined positions there can never be more than 12 total positions in the level array. The priority or urgency is lowest first to highest last on the list. Where requests sent with an urgency at or above the permissions barrier will pass. Since there are default priority names already in place this attribute is a window dressing setting and not much more.

    Default The default array of priority / urgency levels is;

    'trace', 'debug', 'info', 'warn', 'error', 'fatal',
    undef, undef, undef, undef, undef, 'eleven',

    Any report name without a custom priority array will use the default array.

    Example

    logging_levels =>{
    	log_file =>[ qw(<-- report name (others use the default list)
    			foo
    			bar
    			baz
    			fatal
    	) ],
    }

    fatal The Switchboard will confess for all messages sent with a priority or urgency level that matches qr/fatal/i. The switchboard will check for permissions to pass the fatal message but will not take any other actions prior to sending the 'message' with a confess stack and dying. 'fatal' can be set anywhere in the custom priority list from lowest to highest but fatal is the only one that will die. (priorities higher than fatal will not die) But, if the message is blocked for the message name-space, report, and level then the code will NOT die.> If 'fatal' is the requested level from the caller but it is not on the (custom) list for the report desination then the priority of the message drops to 0 and 0 position urgencies must be accepted for the report to die. (even if the listed level at the 0 position is not 'fatal').

attribute methods Methods provided to adjust this attribute

    has_log_levels( $report )

      Definition: Indicates if a custom log level list is stored for $report.

    add_log_levels( $report )

      Definition: Sets the log level name strings for $report

      Accepts: the value must be an array ref of no more than 12 total positions

    remove_log_levels( $report1 [, $report2] )

      Definition: Removes the custom log_level list for the $report[s]

    set_all_log_levels( $full_hashref_of_arrayrefs )

      Definition: Completely resets all custom log levels to $full_hashref_of_arrayrefs

    get_all_log_levels

      Definition: Returns the full hashref of arrayrefs for all custom log levels

all_buffering

    Definition: Buffering in this package is only valuable if you want to eliminate some of the sent messages after they were created. Buffering allows for clearing of sent messages from between two save points. For this to occur buffering must be on and flushing the buffer to the report need to occur at all known good points. When some section of prior messages are to be discarded then a clear_buffer command can be sent and all buffered messages after the last flush will be discarded. If buffering is turned off the messages are sent directly to the report for processing with no holding period. This attribute accepts a hash ref where the keys are report names and the values empty arrayrefs You could theoretically pre-load your buffer here but it is not reccomended. If a new instance of this class is called with an 'all_buffering' arg sent then it will flush any pre-existing buffers (even if they are duplicated in the new call) then delete them and set the new passed list fresh.

    Default All buffering is off

    Example

    buffering =>{
    	log_file => [],
    }

    attribute methods Methods provided to adjust this attribute

      set_all_buffering( $hasref_of_arrayrefs )

        Definition: completely resets all buffers to $hasref_of_arrayrefs but flushes all the old buffers first

      has_buffer( $report )

        Definition: Checks if there is an active buffer for $report

      stop_buffering( $report1 [, $report2] )

        Definition: Removes the buffer for the $report[s] (flushing them first)

conf_file

    Definition: It is possible to pass all the Attribute settings to get_operator as a config file. If you wish to mix your metaphores then one of the attribute keys can be 'conf_file' with the value being the full file path of a YAML or JSON file. If you pass other attributes and conf_file then where there is conflict the other attributes overwrite the file settings.

    Default nothing

    Accepts: a full file path to a config file with attribute settings

Methods

These are methods used to adjust outcomes for the activities in the switchboard or to leverage information held by the switchboard.

master_talk( $args_ref )

    Definition: This is a way to directly call a report using the switchboard operator. In a real telephone situation this would be that cool handset that the telephone repairman brought with him. Like the Telephone repairman's phone it plugs in directly to the switchboard (or in the repairmains case into a telephone line) and is a bit trickier to operate than absolutely necessary. For a nicer message sending interface see Log::Shiras::Telephone. When the $args_ref message is received the switchboard will check the name_space_bounds permissions and then test;

    $args_ref->{level} =~ /fatal/i

    If the message passes those two tests then it will attach metadata to to the $args_ref. It should be noted that the reaction to matching level to fatal is to confess (Carp) each element of the {message} ArrayRef. Any message buffering is then handled or the message is sent to the report name and each report in that name-space receives the $args_ref as the arguments to a call $report->add_line( $args_ref ).

    The metadata attached to the message is a follows

    date_time => The date and time the message was sent in CLDR format of 'yyyy-MM-dd hh:mm:ss'
    
    package => The package name of the message source
    
    filename => The (full) file name of the message source
    
    line => The line number of the message source

    Returns: The number of times the add_line call was made. There are some special cases.

    -3 = The call was not allowed by name_space permissions set in the switchboard
    -2 = The message was buffered rather than sent to a report
    -1 = The message was blocked as risking deep recursion
     0 = The call had permissions but found no report implementations to connect with
     1(and greater) = This indicates how many report instances received the message

    Accepts: The passed args must be a HashRef and contain the following elements (any others will be ignored by the switchboard but not stripped).

      name_space the value is the caller name_space as used by name_space_bounds

      level value is the urgency level of the message sent. It can either be an integer in the set [0..11] or one of the defined logging level strings.

      report the value is the report name (destination) for the message ref

      message the message key must have a value that is an array_ref. It is assumed that content can be parsed into somthing else at the report level including any ArrayRef sub-elements that may be Objects or hashrefs.

      carp_stack if this key is passed and set to a true value then Carp - longmess will be run on the message and the results will be split on the newline and pushed onto the end of the 'message' array_ref.

      source_sub this key is generally handled in the background by Log::Shiras but if you write a new caller subroutine to lay over 'master_talk' then providing that name to this key will make the metada added to the message stop at the correct caller level.

        example

        {
        	name_space => 'MyCoolScript::my_subroutine',
        	level => 'warn',
        	report => 'log_file',
        	message =>[ 'Dont ignore these words' ],
        }

      carp_stack [optional] This is a simple passed boolean value that will trigger a traditional Carp longmess stack to be split by /\n\s*/ and then pushed on the end of the message array ref. Before the message is stored this key will be deleted whether it was positive or negative.

      source_sub [really optional] This is rarely used unless you are writing a replacement for Log::Shiras::Telephone. If you are writing a replacement then a full method space string is passed here. This will be used to travel the caller stack to find where the message line originated. The equivalent for Log::Shiras::Telephone is;

        example

        { source_sub => 'Log::Shiras::Telephone::talk' }

add_name_space_bounds( $ref )

    Definition: This will graft more name-space boundaries onto the existing name-space. The passed ref will be treated as the 'scion_ref' using Data::Walk::Graft.

    Accepts: a data_ref (must start at the root of the main ref) of data to graft to the main name_space_bounds ref

    Returns: The updated name-space data ref

remove_name_space_bounds( $ref )

    Definition: This will prune the name-space boundaries using the passed name-space ref. The passed ref will be treated as the 'slice_ref' using Data::Walk::Prune.

    Accepts: a data_ref (must start at the root of the main ref) of data used to prune the main name_space_bounds ref

    Returns: The updated name-space data ref

add_reports( %args )

    Definition: This will add more report output instances to the existing named report registered instances. If the items in the passed report list are not already report object instances that ->can( 'add_line' ) there will be an attempt to build them using "build_instance( %args|\%args )" in MooseX::ShortCut::BuildInstance. If (and only if) the report name does not exist then the report name will also be added to the report registry.

    Accepts: a hash of arrays with the report objects as items in the array

    Returns: 1

get_log_levels( $report_name )

    Definition: This will return the log level names names for a given report name in an array ref. If no custom levels are defined it will return the default level list.

    Accepts: a report name

    Returns: an array ref of the defined log levels for that report.

send_buffer_to_output( $report_name )

    Definition: This will flush the contents of the $report_name buffer to all the associated report objects.

    Accepts: a $report_name

    Returns: The number of times that $report_object->add_line( $message_ref ) was called to complete the buffer flush.

start_buffering( $report_name )

    Definition: This will start buffering for the $report_name. If the buffering is already implemented then nothing new happens. No equivalent report or name_space_bounds are required to turn buffering on!

    Accepts: a $report_name string

    Returns: 1

clear_buffer( $report_name )

    Definition: This will remove all messages currently in the buffer without sending them to the report.

    Accepts: a $report_name string

    Returns: 1

SYNOPSIS

This is pretty long so I put it at the end

#!perl
use Modern::Perl;
use lib 'lib', '../lib',;
use Log::Shiras::Unhide qw( :debug :InternalSwitchboarD );#
use Log::Shiras::Switchboard;
###InternalSwitchboarD	use Log::Shiras::Report::Stdout;
$| = 1;
###LogSD warn "lets get ready to rumble...";
my $operator = Log::Shiras::Switchboard->get_operator(
		name_space_bounds =>{
			main =>{
				UNBLOCK =>{
					# UNBLOCKing the quiet, loud, and run reports (destinations)
					# 	at the 'main' caller name_space and deeper
					quiet	=> 'warn',
					loud	=> 'info',
					run		=> 'trace',
				},
			},
			Log =>{
				Shiras =>{
###InternalSwitchboarD	Switchboard =>{#<-- Internal reporting enabled here
###InternalSwitchboarD		get_operator =>{
###InternalSwitchboarD			UNBLOCK =>{
###InternalSwitchboarD				# UNBLOCKing log_file
###InternalSwitchboarD				# 	at Log::Shiras::Switchboard::get_operator
###InternalSwitchboarD				#	(self reporting)
###InternalSwitchboarD				log_file => 'info',
###InternalSwitchboarD			},
###InternalSwitchboarD		},
###InternalSwitchboarD		master_talk =>{
###InternalSwitchboarD			_buffer_decision =>{
###InternalSwitchboarD				UNBLOCK =>{
###InternalSwitchboarD					# UNBLOCKing log_file
###InternalSwitchboarD					# 	at Log::Shiras::Switchboard::master_talk::_buffer_decision
###InternalSwitchboarD					#	(self reporting)
###InternalSwitchboarD					log_file => 'trace',
###InternalSwitchboarD				},
###InternalSwitchboarD			},
###InternalSwitchboarD		},
###InternalSwitchboarD		send_buffer_to_output =>{
###InternalSwitchboarD			UNBLOCK =>{
###InternalSwitchboarD				# UNBLOCKing log_file
###InternalSwitchboarD				# 	at Log::Shiras::Switchboard::_flush_buffer
###InternalSwitchboarD				#	(self reporting)
###InternalSwitchboarD				log_file => 'info',
###InternalSwitchboarD			},
###InternalSwitchboarD		},
###InternalSwitchboarD	},#<-- Internal reporting enabled through here
				},
			},
		},
		reports =>{
			quiet =>[
				Print::Wisper->new,
			],
			loud =>[
				{
					package => 'Print::Excited',
					add_methods =>{
						add_line => sub{
							shift;
							my @input = ( ref $_[0]->{message} eq 'ARRAY' ) ?
											@{$_[0]->{message}} : $_[0]->{message};
							my @new_list;
							map{ push @new_list, $_ if $_ } @input;
							chomp @new_list;
							print '!!!' . uc(join( ' ', @new_list)) . "!!!\n";
						}
					},
				}
			],
###InternalSwitchboarD	log_file =>[
###InternalSwitchboarD		Log::Shiras::Report::Stdout->new,
###InternalSwitchboarD	],
		},
		all_buffering =>{
			quiet => [],
		},
	);
###LogSD warn "sending the message 'Hello World 1'";
$operator->master_talk({
	report => 'log_file', level => 'warn', name_space => 'main',
	message =>[ 'Hello World 1' ] });
###LogSD warn "The name_space 'main' does not have destination 'log_file' permissions";
###LogSD warn "sending the message 'Hello World 2' to the report 'quiet'";
$operator->master_talk({
	report => 'quiet', level => 'warn', name_space => 'main',
	message =>[ 'Hello World 2' ] });
###LogSD warn "message went to the buffer - turning off buffering for the 'quiet' destination ...";
$operator->stop_buffering( 'quiet' );
###LogSD warn "should have printed what was in the 'quiet' buffer ...";
$operator->master_talk({
	report => 'quiet', level => 'debug', name_space => 'main',
	message =>[ 'Hello World 3' ] });
###LogSD warn "sending the message 'Hello World 4' to the report 'loud'";
$operator->master_talk({
	report => 'loud', level => 'info', name_space => 'main',
	message =>[ 'Hello World 4' ] });
###LogSD warn "sending the message 'Hello World 5' to the report 'run'";
my $result = 1;
$result = $operator->master_talk({
	report => 'run', level => 'warn', name_space => 'main',
	message =>[ 'Hello World 5' ] });
###LogSD warn "message to 'run' at 'warn' level was approved";
###LogSD warn "...but found -$result- reporting destinations (None were set up)";

package Print::Wisper;
sub new{
	bless {}, shift;
}
sub add_line{
	shift;
	my @input = ( ref $_[0]->{message} eq 'ARRAY' ) ?
					@{$_[0]->{message}} : $_[0]->{message};
	my @new_list;
	map{ push @new_list, $_ if $_ } @input;
	chomp @new_list;
	print '--->' . lc(join( ' ', @new_list )) . "<---\n";
}

1;

#######################################################################################
# Synopsis Screen Output for the following condition
# use Log::Shiras::Unhide;
# 01: --->hello world 2<---
# 02: !!!HELLO WORLD 4!!!
#######################################################################################

#######################################################################################
# Synopsis Screen Output for the following condition
# use Log::Shiras::Unhide qw( :debug );
# 01: Using Log::Shiras::Unhide-v0.29_1 strip_match string: (LogSD) at ../lib/Log/Shiras/Unhide.pm line 88.
# 02: lets get ready to rumble... at log_shiras_switchboard.pl line 7.
# 03: sending the message 'Hello World 1' at log_shiras_switchboard.pl line 80.
# 04: The name_space 'main' does not have destination 'log_file' permissions at log_shiras_switchboard.pl line 84.
# 05: sending the message 'Hello World 2' to the report 'quiet' at log_shiras_switchboard.pl line 85.
# 06: message went to the buffer - turning off buffering for the 'quiet' destination ... at log_shiras_switchboard.pl line 89.
# 07: --->hello world 2<---
# 08: should have printed what was in the 'quiet' buffer ... at log_shiras_switchboard.pl line 91.
# 09: sending the message 'Hello World 4' to the report 'loud' at log_shiras_switchboard.pl line 95.
# 10: !!!HELLO WORLD 4!!!
# 11: sending the message 'Hello World 5' to the report 'run' at log_shiras_switchboard.pl line 99.
# 12: message to 'run' at 'warn' level was approved at log_shiras_switchboard.pl line 104.
# 13: ...but found -0- reporting destinations (None were set up) at log_shiras_switchboard.pl line 105.
#######################################################################################

#######################################################################################
# Synopsis Screen Output for the following conditions
# use Log::Shiras::Unhide qw( :debug :InternalSwitchboarD );
# 01: Using Log::Shiras::Unhide-v0.29_1 strip_match string: (LogSD|InternalSwitchboarD) at ../lib/Log/Shiras/Unhide.pm line 88.
# 02: You uncovered internal logging statements for Log::Shiras::Types-v0.29_1 at ..\lib\Log\Shiras\Types.pm line 5.
# 03: You uncovered internal logging statements for Log::Shiras::Switchboard-v0.29_1 at ..\lib\Log\Shiras\Switchboard.pm line 5.
# 04: lets get ready to rumble... at log_shiras_switchboard.pl line 7.
# 05: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 06: | line  - 0704   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 07: 	:(	Arrived at _buffer_decision for report: log_file
# 08: 		..with buffer setting:  ):
# 09: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 10: | line  - 0715   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 11: 	:(	Current action for report -log_file- is: report ):
# 12: | level - 2      | name_space - Log::Shiras::Switchboard::get_operator
# 13: | line  - 0211   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 14: 	:(	Switchboard finished updating the following arguments:
# 15: 		reports
# 16: 		name_space_bounds
# 17: 		all_buffering ):
# 18: sending the message 'Hello World 1' at log_shiras_switchboard.pl line 80.
# 19: The name_space 'main' does not have destination 'log_file' permissions at log_shiras_switchboard.pl line 84.
# 20: sending the message 'Hello World 2' to the report 'quiet' at log_shiras_switchboard.pl line 85.
# 21: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 22: | line  - 0704   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 23: 	:(	Arrived at _buffer_decision for report: quiet
# 24: 		..with buffer setting: 1 ):
# 25: | level - 1      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 26: | line  - 0709   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 27: 	# 01: 	:(	The buffer is active - sending the message to the buffer (not the report). ):
# 28: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 29: | line  - 0715   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 30: 	:(	Current action for report -quiet- is: buffer ):
# 31: message went to the buffer - turning off buffering for the 'quiet' destination ... at log_shiras_switchboard.pl line 89.
# 32: --->hello world 2<---
# 33: should have printed what was in the 'quiet' buffer ... at log_shiras_switchboard.pl line 91.
# 34: sending the message 'Hello World 4' to the report 'loud' at log_shiras_switchboard.pl line 95.
# 35: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 36: | line  - 0704   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 37: 	:(	Arrived at _buffer_decision for report: loud
# 38: 		..with buffer setting:  ):
# 39: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 40: | line  - 0715   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 41: 	:(	Current action for report -loud- is: report ):
# 42: !!!HELLO WORLD 4!!!
# 43: sending the message 'Hello World 5' to the report 'run' at log_shiras_switchboard.pl line 99.
# 44: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 45: | line  - 0704   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 46: 	:(	Arrived at _buffer_decision for report: run
# 47: 		..with buffer setting:  ):
# 48: | level - 2      | name_space - Log::Shiras::Switchboard::master_talk::_buffer_decision
# 49: | line  - 0715   | file_name  - ..\lib\Log\Shiras\Switchboard.pm
# 50: 	:(	Current action for report -run- is: report ):
# 51: message to 'run' at 'warn' level was approved at log_shiras_switchboard.pl line 104.
# 52: ...but found -0- reporting destinations (None were set up) at log_shiras_switchboard.pl line 105.
#######################################################################################

SYNOPSIS EXPLANATION

    use Log::Shiras::Unhide qw( :debug :InternalSwitchboarD );
    ..
    ###LogSD warn "lets get ready to rumble...";

    Log::Shiras::Unhide strips ###MyCoolTag tags - see Log::Shiras::Unhide for more information. It represents the only driver between the three example outputs (All run from the same basic script). For instance when the :debug tag is passed to Unhide then ###LogSD is stripped. When :InternalSwitchboarD is passed it strips ###InternalSwitchboarD.

    Each of the remaining functions is documented above but the difference between the three outputs are based on what is unhid. In all cases 'Hello World [1..5]' is sent to master_talk in the switchboard. All of the calls are valid syntax but not all calls have the necessary target or urgency to be completed.

    In the first output it is obvious that only 'Hello World 2' and 'Hello World 4' have the necessary permissions to be completed. Each one is sent to a different report object so it will be obvious based on the output what path it took to be printed.

    In the second output only the ###LogSD tags are removed and so comments associated with the actions are exposed. In this case these comments only exist in the script space so warning messages are mostly the only thing exposed that is visible. Since ~::Unhide is a source filter it also provides a warning from the class showing that a source filter is turned on and what is being scrubbed. This includes scrubbing through the script and all used modules. (But not 'with' roles!).

    In the final output the ###InternalSwitchboarD tags are also stripped. Since there are a lot of these in Log::Shiras::Switchboard there is a number of things available to see from that class. However the operator only has released log_file messages for the ~::get_operator and ~::_buffer_decision name spaces. A new class is also exposed that can take advantage of message metadata and uses it to show where the message came from as well has what urgency it was sent with.

SUPPORT

TODO

    1. Add method to pull a full caller($x) stack and add it to message metadata. Probably should be triggered in the master_talk call args.

    2. Investigate the possibility of an ONLY keyword in addition to of UNBLOCK - how would this be implemented? - Future uncertain

AUTHOR

Jed Lund
jandrew@cpan.org

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 module.

DEPENDENCIES

SEE ALSO