flibs/m_multilog(n) 1.0 "flibs"

Name

flibs/m_multilog - Manage multiple log files

Table Of Contents

Synopsis

Description

The module m_multilog provides a logging type with a set of type bound procedures and other methods to manage one or more log files. The module and its test program are based on the m_logger module (including unit test) which is part of the flibs library. For applications in need of only one log, m_logger is the recommended module.

OVERVIEW

The goal of this component is to provide a way to write messages both on standard output and on one or more log files, so that a trace of the execution - with desired level of detail - can be read by the user after the execution.

One single statement should be able to write to all open log files with appropriate log level set. Example:

   call log_msg ('Log message', WARNING)

will write to logs with log level equal to or lower than WARNING, i.e. WARNING, INFO and FINE.

The module provides methods to

Individual logs are started with log_t%startup (filename [,options]). The method takes the log file name as first argument: its main purpose is to connect the log to the file. Optional arguments: log information level, append true/false

Logs can be added to the log group with "add_log". Logs can be removed from the log group using the "remove_log" method, which will also close the file connected to the log.

The messages are sent to one or more of the active logs with the static method "log_msg". Infolevel is an optional argument to log_msg, if left out it's set to ALL which means that the message will be written to all logs.

In the following example, extracted from the unit tests of m_multilog provided with the project, one connects the file "test_m_multilog.log" to the log, two messages of which only the first should be written to file and shut down the logging system.

   type (log_t) :: test
   call test%startup ( 'test_m_multilog.log' , INFO )
   call add_log ( test )
   call log_msg ( 'First message' , INFO )
   call log_msg ( 'Second message', FINE )
   call shutdown_log_group ()

By default, the logging is done on all log files with appropriate infolevel and on standard output. The user may want to configure the behaviour of the log_group so that message are not written on standard output.

The static method log_configure(option,value [,log]) is the central point to configure the log group. It takes a character "option" string and a "value" as arguments. In the following example, one writes messages on file and in some cases also to stdout, with and without time stamps.

  type (log_t) :: test
  call test%startup ( 'test_m_multilog.log' )
  call add_log ( test )
  call log_configure ( "writeonstdout" , .false. )
  call log_msg( 'This message is written only on file' )
  call log_configure ( "writeonstdout" , .true. )
  call log_msg( 'This message is written both on screen and on file' )
  call shutdown_log_group ()

METHODS

Public types and parameters:

type(log_t) :: log

Defines a log file to write to. It is opened via the startup method.

integer, parameter :: DEBUG, FINE, INFO, WARNING, ERROR, ALL

Different levels of logging information. Messages are only written to the log file if they have a level equal to or higher than the level for the file. The level "ALL" indicates messages that are written to any file.

integer, parameter :: LOG_LEVEL_VOLUME, LOG_LEVEL_CHAPTER, LOG_LEVEL_SECTION, LOG_LEVEL_SUBSECTION

Different delimiters for the information in the log files. The routine log_delimiter writes the corresponding delimiting string to the log file(s).

The module provides the following methods per logging object (type(log_t)):

this%startup ( log_file ?, append? ?, info_lvl?)

Initialises the log, connect it to the given filename and set default values.

class(log_t), intent(inout) :: this

The logging object.

character(len=*), intent(in) :: log_file

Name of the log file

logical, optional, intent(in) :: append

If present and true, then the messages will be appended to the end of the log file. If present and false, then the initialization of the log overwrites the messages of the previous logging session.

If not provided, the default value is append=.true.

integer, optional, intent(in) :: info_lvl

If present, set log_t%infolevel to the provided value If not present, set to default value INFO.

this%shutdown

Shotdown the log

this%write ( msg ?, info_lvl?)

Log the given character string to one logging unit. If the logging to standard output is enabled, writes the message on standard output.

If the logging to the log file is enabled, writes the message into the log file.

Before outputting directly the message string, the string is trimmed, that is to say that all trailing blanks are removed from the string.

If the time stamp option is enabled, a time stamp with format "year-month-day hh:mm:ss" is inserted before the message. Note: Before outputting directly the message string, the string is trimmed, that is to say that all trailing blanks are removed from the string.

class(log_t), intent(inout) :: this

The logging object.

character(len=*), intent(in) :: msg

Log message to be written

integer, optional, intent(in) :: info_lvl

If present, set log_t%infolevel to the provided value If not present, set to default value INFO.

The module provides the following routines for the global log handler:

shutdown_log_group

Close all logs connected to the log_group object

add_log ( log )

] Add a log_t object to the log group. Up to four log objects can be added.

class(log_t), intent(inout) :: log

log log_t object (initialized with log_t%startup)

remove_log ( log )

] Remove a log_t object from the log group.

class(log_t), intent(inout) :: this

log_t object (initialized with log_t%startup)

log_msg ( msg ?, info_lvl?)

Log the given character string to all logging units with relevant info_lvl. If no info_lvl is specified, ALL is used (write to all logs).

If the logging to standard output is enabled, writes the message on standard output as well as to relevant log files. Before outputting directly the message string, the string is trimmed, that is to say that all trailing blanks are removed from the string.

If the time stamp option is enabled, a time stamp with format "year-month-day hh:mm:ss" is inserted before the message.

character(len=*), intent(in) :: msg

Log message to be written

integer, optional, intent(in) :: info_lvl

Optional: log information level, default = INFO

log_reset ( log)

Set all internal settings to default values.

class(log_t), intent(inout) :: log

log to reset, if not provided all logs are reset

log_configure ( option , value ?log?)
character ( len = * ) , intent(in) :: option
logical, intent(in) :: value
type(log_t), optional, intent(inout) :: log

Set the logical static option of the component to value. The option is set for the log object if given, otherwise it is set for the log group as a whole.

The option may be one of the following.

  • option = "timestamp" : Disable or enable the insertion of time stamps. If the time stamp option is enabled, a time stamp with format "year-month-day hh:mm:ss" is inserted before the message.

  • option = "writeonstdout" : Disable or enable the writing on standard output.

  • option = "writeonlogfile" : Disable or enable the writing on log file.

  • option = "stoponerror" : Configure the behaviour of the component whenever an error is met. If stoponerror is true, then the execution stops if an error is encountered. If stoponerror is false, then the execution continues if an error is encountered. In both cases, a message is displayed on standard output.

log_configure ( option , value ?, log?)
character ( len = * ) , intent(in) :: option
integer, intent(in) :: value
type(log_t), optional, intent(inout) :: log

Configure the integer static option of the component. The option is set for the log object if given, otherwise it is set for the log group as a whole.

The option may be one of the following.

  • option = "logfileunit" : Force the logical unit for logging to be value. Use this feature with caution, since the original logical unit is lost.

log_configure ( option , value)
type(log_t), optional, intent(inout) :: log
character ( len = * ) , intent(in) :: option
character ( len = * ) , intent(in) :: value

Set the character static "option" of the component to "value". The character options are global, so independent of the log objects.

The "option" may be one of the following.

  • option = "level_string_volume" Set the string used for volume delimiter.

  • option = "level_string_chapter" Set the string used for chapter delimiter.

  • option = "level_string_section" Set the string used for section delimiter.

  • option = "level_string_subsection" Set the string used for subsection delimiter.

log_cget ( ?log ,? option , value)
type(log_t), optional, intent(inout) :: log
character ( len = * ) , intent(in) :: option
logical, intent(in) :: value

Get the logical static "option" of the component. The option is retrieved for the log object if given, otherwise it is retrieved for the log group as a whole.

The option may be one of the following.

  • option = "timestamp" : Current value of the option to enable / disable insertion of time stamps.

  • option = "writeonstdout" : Current value of the option to enable / disable writing on standard output.

  • option = "writeonlogfile" : Current value of the option to enable / disable writing on log file.

  • option = "stoponerror" : Current value of the option to enable / disable stopping when an error is met.

log_cget ( ?log ,? option , value)
type(log_t), optional, intent(inout) :: log
character ( len = * ) , intent(in) :: option
integer, intent(in) :: value

Get the integer static "option" of the component. The option is retrieved for the log object if given, otherwise it is retrieved for the log group as a whole.

  • option = "logfileunit" : Current logical unit connected to the logging system.

log_cget ( ?log ,? option , value)
type(log_t), optional, intent(inout) :: log
character ( len = * ) , intent(in) :: option
character ( len = * ) , intent(out) :: value

Get the character static "option" of the component. The character options are global, so independent of the log objects. The log argument is therefore not used, it has been added for uniformity.

The "option" may be one of the following.

  • option = "level_string_volume" Get the string used for volume delimiter.

  • option = "level_string_chapter" Get the string used for chapter delimiter.

  • option = "level_string_section" Get the string used for section delimiter.

  • option = "level_string_subsection" Get the string used for subsection delimiter.

TODO

The order of the info levels - should it be different?

Possibility to define own info levels and/or re-configure the standard ones?