% Copyright (C) 2017-2020 Olivier Boudeville % % This file is part of the Ceylan-Myriad library. % % This library is free software: you can redistribute it and/or modify % it under the terms of the GNU Lesser General Public License or % the GNU General Public License, as they are published by the Free Software % Foundation, either version 3 of these Licenses, or (at your option) % any later version. % You can also redistribute it and/or modify it under the terms of the % Mozilla Public License, version 1.1 or later. % % This library is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU Lesser General Public License and the GNU General Public License % for more details. % % You should have received a copy of the GNU Lesser General Public % License, of the GNU General Public License and of the Mozilla Public License % along with this library. % If not, see and % . % % Author: Olivier Boudeville [olivier (dot) boudeville (at) esperide (dot) com] % Creation date: Friday, November 1, 2013. % Gathering of various very low-level trace-related facilities on the console. % % They are mostly useful so that their call can be replaced by calls to the far % more advanced facilities of the 'Traces' layer with no change in their % parameters. % % For example, 'trace_utils:debug_fmt( "I am the ~B.", [ 1 ] )' may be replaced % by '?debug_fmt( "I am the ~B.", [ 1 ] )' to switch from basic traces on the % console to traces on the Traces subsystem. % % As a result, for a trace severity S in [ debug, trace, info, warning, error, % fatal ], 'trace_utils:S' may be replaced as a whole by '?S' to promote a very % debug-oriented trace into a more durable one. % % See trace_utils_test.erl for testing. % -module(trace_utils). % To resolve name clash: -compile( { no_auto_import, [ error/1 ] } ). % An actual trace message: -type trace_message() :: string(). % 7 levels of severity, from least important to most: debug, trace, info, % warning, error and fatal (void being always muted): % -type trace_severity() :: 'debug'| 'trace' | 'info' | 'warning' | 'error' | 'fatal' | 'void'. % A format with quantifiers (such as ~p): -type trace_format() :: text_utils:format_string(). % Values corresponding to format quantifiers: -type trace_values() :: text_utils:format_values(). % Categorization of a trace message: -type trace_message_categorization() :: string(). % An applicative timestamp for a trace: -type trace_timestamp() :: string(). -export_type([ trace_message/0, trace_severity/0, trace_format/0, trace_values/0, trace_message_categorization/0, trace_timestamp/0 ]). -export([ debug/1, debug_fmt/2, debug_categorized/2, debug_categorized_timed/3, trace/1, trace_fmt/2, trace_categorized/2, trace_categorized_timed/3, info/1, info_fmt/2, info_categorized/2, info_categorized_timed/3, warning/1, warning_fmt/2, warning_categorized/2, warning_categorized_timed/3, error/1, error_fmt/2, error_categorized/2, error_categorized_timed/3, fatal/1, fatal_fmt/2, fatal_categorized/2, fatal_categorized_timed/3, void/1, void_fmt/2, void_categorized/2, void_categorized_timed/3, echo/2, echo/3, echo/4 ]). % Implementation notes: % % Compared to mere io:format/{1,2} calls, these trace primitives add % automatically the trace type (ex: "[debug] ") at the beginning of the message, % finishes it with a carriage-return/line-feed, and for the most important trace % types, try to ensure they are synchronous (blocking). % Outputs specified debug message. -spec debug( trace_message() ) -> void(). debug( Message ) -> actual_display( "[debug] " ++ Message ). % Outputs specified formatted debug message. -spec debug_fmt( trace_format(), trace_values() ) -> void(). debug_fmt( Format, Values ) -> actual_display( "[debug] " ++ Format, Values ). % Outputs specified debug message, with specified message categorization. -spec debug_categorized( trace_message(), trace_message_categorization() ) -> void(). debug_categorized( Message, _MessageCategorization=uncategorized ) -> actual_display( "[debug] ~s", [ Message ] ); debug_categorized( Message, MessageCategorization ) -> actual_display( "[debug][~s] ~s", [ MessageCategorization, Message ] ). % Outputs specified debug message, with specified message categorization and % time information. % -spec debug_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). debug_categorized_timed( Message, _MessageCategorization=uncategorized, Timestamp ) -> actual_display( "[debug][at ~s] ~s", [ Timestamp, Message ] ); debug_categorized_timed( Message, MessageCategorization, Timestamp ) -> actual_display( "[debug][~s][at ~s] ~s", [ MessageCategorization, Timestamp, Message ] ). % Outputs specified trace message. -spec trace( trace_message() ) -> void(). trace( Message ) -> actual_display( "[trace] " ++ Message ). % Outputs specified formatted trace message. -spec trace_fmt( trace_format(), trace_values() ) -> void(). trace_fmt( Format, Values ) -> actual_display( "[trace] " ++ Format, Values ). % Outputs specified trace message, with specified message categorization. -spec trace_categorized( trace_message(), trace_message_categorization() ) -> void(). trace_categorized( Message, _MessageCategorization=uncategorized ) -> actual_display( "[trace] ~s", [ Message ] ); trace_categorized( Message, MessageCategorization ) -> actual_display( "[trace][~s] ~s", [ MessageCategorization, Message ] ). % Outputs specified trace message, with specified message categorization and % time information. % -spec trace_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). trace_categorized_timed( Message, _MessageCategorization=uncategorized, Timestamp ) -> actual_display( "[trace][at ~s] ~s", [ Timestamp, Message ] ); trace_categorized_timed( Message, MessageCategorization, Timestamp ) -> actual_display( "[trace][~s][at ~s] ~s", [ MessageCategorization, Timestamp, Message ] ). % Outputs specified info message. -spec info( trace_message() ) -> void(). info( Message ) -> actual_display( "[info] " ++ Message ). % Outputs specified formatted info message. -spec info_fmt( trace_format(), trace_values() ) -> void(). info_fmt( Format, Values ) -> actual_display( "[info] " ++ Format, Values ). % Outputs specified info message, with specified message categorization. -spec info_categorized( trace_message(), trace_message_categorization() ) -> void(). info_categorized( Message, _MessageCategorization=uncategorized ) -> actual_display( "[info] ~s", [ Message ] ); info_categorized( Message, MessageCategorization ) -> actual_display( "[info][~s] ~s", [ MessageCategorization, Message ] ). % Outputs specified info message, with specified message categorization and time % information. % -spec info_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). info_categorized_timed( Message, _MessageCategorization=uncategorized, Timestamp ) -> actual_display( "[info][at ~s] ~s", [ Timestamp, Message ] ); info_categorized_timed( Message, MessageCategorization, Timestamp ) -> actual_display( "[info][~s][at ~s] ~s", [ MessageCategorization, Timestamp, Message ] ). % Outputs specified warning message. -spec warning( trace_message() ) -> void(). warning( Message ) -> severe_display( "[warning] " ++ Message ), system_utils:await_output_completion(). % Outputs specified formatted warning message. -spec warning_fmt( trace_format(), trace_values() ) ->void(). warning_fmt( Format, Values ) -> severe_display( "[warning] " ++ Format, Values ), system_utils:await_output_completion(). % Outputs specified warning message, with specified message categorization. -spec warning_categorized( trace_message(), trace_message_categorization() ) -> void(). warning_categorized( Message, _MessageCategorization=uncategorized ) -> severe_display( "[warning] ~s", [ Message ] ); warning_categorized( Message, MessageCategorization ) -> severe_display( "[warning][~s] ~s", [ MessageCategorization, Message ] ). % Outputs specified warning message, with specified message categorization and % time information. % -spec warning_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). warning_categorized_timed( Message, _MessageCategorization=uncategorized, Timestamp ) -> severe_display( "[warning][at ~s] ~s", [ Timestamp, Message ] ); warning_categorized_timed( Message, MessageCategorization, Timestamp ) -> severe_display( "[warning][~s][at ~s] ~s", [ MessageCategorization, Timestamp, Message ] ). % Outputs specified error message. -spec error( trace_message() ) -> void(). error( Message ) -> severe_display( "[error] " ++ Message ), system_utils:await_output_completion(). % Outputs specified formatted error message. -spec error_fmt( trace_format(), trace_values() ) -> void(). error_fmt( Format, Values ) -> severe_display( "[error] " ++ Format, Values ), system_utils:await_output_completion(). % Outputs specified error message, with specified message categorization. -spec error_categorized( trace_message(), trace_message_categorization() ) -> void(). error_categorized( Message, _MessageCategorization=uncategorized ) -> severe_display( "[error] ~s", [ Message ] ); error_categorized( Message, MessageCategorization ) -> severe_display( "[error][~s] ~s", [ MessageCategorization, Message ] ). % Outputs specified error message, with specified message categorization and % time information. % -spec error_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). error_categorized_timed( Message, _MessageCategorization=uncategorized, Timestamp ) -> severe_display( "[error][at ~s] ~s", [ Timestamp, Message ] ); error_categorized_timed( Message, MessageCategorization, Timestamp ) -> severe_display( "[error][~s][at ~s] ~s", [ MessageCategorization, Timestamp, Message ] ). % Outputs specified fatal message. -spec fatal( trace_message() ) -> void(). fatal( Message ) -> severe_display( "[fatal] " ++ Message ), system_utils:await_output_completion(). % Outputs specified formatted fatal message. -spec fatal_fmt( trace_format(), trace_values() ) -> void(). fatal_fmt( Format, Values ) -> severe_display( "[fatal] " ++ Format, Values ), system_utils:await_output_completion(). % Outputs specified fatal message, with specified message categorization. -spec fatal_categorized( trace_message(), trace_message_categorization() ) -> void(). fatal_categorized( Message, _MessageCategorization=uncategorized ) -> severe_display( "[fatal] ~s", [ Message ] ); fatal_categorized( Message, MessageCategorization ) -> severe_display( "[fatal][~s] ~s", [ MessageCategorization, Message ] ). % Outputs specified fatal message, with specified message categorization and % time information. % -spec fatal_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). fatal_categorized_timed( Message, _MessageCategorization=uncategorized, Timestamp ) -> severe_display( "[fatal][at ~s] ~s", [ Timestamp, Message ] ); fatal_categorized_timed( Message, MessageCategorization, Timestamp ) -> severe_display( "[fatal][~s][at ~s] ~s", [ MessageCategorization, Timestamp, Message ] ). % "Outputs" specified void message. -spec void( trace_message() ) -> void(). void( _Message ) -> ok. % "Outputs" specified formatted void message. -spec void_fmt( trace_format(), trace_values() ) -> void(). void_fmt( _Format, _Values ) -> ok. % "Outputs" specified void message, with specified message categorization. -spec void_categorized( trace_message(), trace_message_categorization() ) -> void(). void_categorized( _Message, _MessageCategorization ) -> ok. % "Outputs" specified void message, with specified message categorization and % time information. % -spec void_categorized_timed( trace_message(), trace_message_categorization(), trace_timestamp() ) -> void(). void_categorized_timed( _Message, _MessageCategorization, _Timestamp ) -> ok. % Echoes specified trace in specified trace channel. % % Defined notably to perform integrated operations (a trace being sent through % both a basic system and a more advanced one), in order that the trace macros % of upper layers (ex: send_fatal_fmt/3, in the Traces layer) do not need to % bind variables in their body (which may trigger bad matches as soon as more % than once trace is sent in the same scope). % -spec echo( trace_message(), trace_severity() ) -> void(). echo( TraceMessage, _TraceSeverity=debug ) -> debug( TraceMessage ); echo( TraceMessage, _TraceSeverity=trace ) -> trace( TraceMessage ); echo( TraceMessage, _TraceSeverity=info ) -> info( TraceMessage ); echo( TraceMessage, _TraceSeverity=warning ) -> warning( TraceMessage ); echo( TraceMessage, _TraceSeverity=error ) -> error( TraceMessage ); echo( TraceMessage, _TraceSeverity=fatal ) -> fatal( TraceMessage ); echo( _TraceMessage, _TraceSeverity=void ) -> ok. % Echoes specified trace in specified trace channel, for specified message % categorization. % % Defined notably to perform integrated operations (a trace being sent through % both a basic system and a more advanced one), in order that the trace macros % of upper layers (ex: send_fatal_fmt/3, in the Traces layer) do not need to % bind variables in their body (which may trigger bad matches as soon as more % than once trace is sent in the same scope). % -spec echo( trace_message(), trace_severity(), trace_message_categorization() ) -> void(). echo( TraceMessage, _TraceSeverity=debug, MessageCategorization ) -> debug_categorized( TraceMessage, MessageCategorization ); echo( TraceMessage, _TraceSeverity=trace, MessageCategorization ) -> trace_categorized( TraceMessage, MessageCategorization ); echo( TraceMessage, _TraceSeverity=info, MessageCategorization ) -> info_categorized( TraceMessage, MessageCategorization ); echo( TraceMessage, _TraceSeverity=warning, MessageCategorization ) -> warning_categorized( TraceMessage, MessageCategorization ); echo( TraceMessage, _TraceSeverity=error, MessageCategorization ) -> error_categorized( TraceMessage, MessageCategorization ); echo( TraceMessage, _TraceSeverity=fatal, MessageCategorization ) -> fatal_categorized( TraceMessage, MessageCategorization ); echo( _TraceMessage, _TraceSeverity=void, _MessageCategorization ) -> ok. % Echoes specified trace in specified trace channel, for specified message % categorization and timestamp. % % Defined notably to perform integrated operations (a trace being sent through % both a basic system and a more advanced one), in order that the trace macros % of upper layers (ex: send_fatal_fmt/3, in the Traces layer) do not need to % bind variables in their body (which may trigger bad matches as soon as more % than once trace is sent in the same scope). % -spec echo( trace_message(), trace_severity(), trace_message_categorization(), trace_timestamp() ) -> void(). echo( TraceMessage, _TraceSeverity=debug, MessageCategorization, Timestamp ) -> debug_categorized_timed( TraceMessage, MessageCategorization, Timestamp ); echo( TraceMessage, _TraceSeverity=trace, MessageCategorization, Timestamp ) -> trace_categorized_timed( TraceMessage, MessageCategorization, Timestamp ); echo( TraceMessage, _TraceSeverity=info, MessageCategorization, Timestamp ) -> info_categorized_timed( TraceMessage, MessageCategorization, Timestamp ); echo( TraceMessage, _TraceSeverity=warning, MessageCategorization, Timestamp ) -> warning_categorized_timed( TraceMessage, MessageCategorization, Timestamp ); echo( TraceMessage, _TraceSeverity=error, MessageCategorization, Timestamp ) -> error_categorized_timed( TraceMessage, MessageCategorization, Timestamp ); echo( TraceMessage, _TraceSeverity=fatal, MessageCategorization, Timestamp ) -> fatal_categorized_timed( TraceMessage, MessageCategorization, Timestamp ); echo( _TraceMessage, _TraceSeverity=void, _MessageCategorization, _Timestamp ) -> ok. % Helper section. % Displays specified message. % % Note: adds a carriage-return/line-feed at the end of the message. % % (helper, to provide a level of indirection) % -spec severe_display( trace_message() ) -> void(). severe_display( Message ) -> Bar = "----------------", % Could be also error_logger:info_msg/1 for example: actual_display( "\n<" ++ Bar ++ "\n" ++ Message ++ "\n" ++ Bar ++ ">\n" ). % Displays specified format-based message. % % Note: adds a carriage-return/line-feed at the end of the message. % % (helper, to provide a level of indirection) % -spec severe_display( trace_format(), trace_values() ) -> void(). severe_display( Format, Values ) -> Message = text_utils:format( Format, Values ), severe_display( Message ). % Displays specified message. % % Note: adds a carriage-return/line-feed at the end of the message. % % (helper, to provide a level of indirection) % -spec actual_display( trace_message() ) -> void(). actual_display( Message ) -> % Default-timeout may not be sufficient (30 seconds, in milliseconds) basic_utils:display_timed( Message, _TimeOut=30000 ). % Displays specified format-based message. % % Note: adds a carriage-return/line-feed at the end of the message. % % (helper, to provide a level of indirection) % -spec actual_display( trace_format(), trace_values() ) -> void(). actual_display( Format, Values ) -> basic_utils:display( Format, Values ).