; docformat = 'rst' ;+ ; `MG_LOG` is a procedural interface to the logging framework. ; ; `MG_LOG` is a convenience routine so that the `MGffLogger` object does not ; need to be explicitly stored by the application using the logging. If more ; than one logger is required, then named loggers can be used using the `NAME` ; keyword. ; ; The error levels are: critical (level 1), error (level 2), warning ; (level 3), informational (level 4), debug (level 5). Only log messages with ; a level less than or equal to the current logger level are actually ; recorded. So if a logger is set to level 3 (warnings), then log messages ; with levels 1 (critical), 2 (error), or 3 (warning) would be displayed, but ; log messages with levels 4 (informational) or 5 (debug) would be ignored. ; ; Named subloggers can be created using the `NAME` keyword. These subloggers ; should be used for individual applications or functional areas of an ; application. ; ; For example, the following starts the logging framework and creates a ; logger object with name "mg_example" returned via the `LOGGER` keyword:: ; ; mg_log, name='mg_example', logger=logger ; ; This logger would next be configured, i.e., set its level, specify a file ; for log messages to written to, set a format for log messages, etc. For ; example, to log critical errors, errors, and warnings to the file ; `my_application.log`, do:: ; ; logger->setProperty, level=3, filename='my_application.log' ; ; Later, messages can be sent to this logger by using the name used ; previously:: ; ; mg_log, 'A problem occurred!', /warning, name='mg_example' ; ; Further refinement can be done with a hierarchy of names. The following ; creates a new sublogger:: ; ; mg_log, name='mg_example/gui', logger=gui_logger ; ; This type of hierarchy is useful for applications with subsystems with ; independent level values. The effective log level for log messages sent to a ; sublogger is the most restrictive log level from all the parent loggers. For ; example, if the level of `gui_logger` was set to "Informational" with:: ; ; gui_logger->setProperty, level=4 ; ; Then informational log messages would not be logged because the parent ; logger, "mg_example", has a level of 3, i.e., "Warning". ; ; :Examples: ; Try the main-level program at the end of this file for a longer example. ; To run it, do:: ; ; IDL> .run mg_log ;- ;+ ; Messages are logged via this routine. Also, the `LOGGER` keyword returns the ; logging object which is used to configure the logging. ; ; :Params: ; msg : in, optional, type=string ; message to log, if present; is interpreted as a format string when ; additional parameters are present ; arg1 : in, optional, type=string ; optional argument to be substituted into `msg` format string ; arg2 : in, optional, type=string ; optional argument to be substituted into `msg` format string ; arg3 : in, optional, type=string ; optional argument to be substituted into `msg` format string ; ; :Keywords: ; name : in, optional, type=string ; path to logger to send message to ; critical : in, optional, type=boolean ; set to specify the message as critical ; error : in, optional, type=boolean ; set to specify the message as an error ; warning : in, optional, type=boolean ; set to specify the message as a warning ; informational : in, optional, type=boolean ; set to specify the message as informational ; debug : in, optional, type=boolean ; set to specify the message as debug ; last_error : in, optional, type=boolean ; set to place a stack trace for the last error in the log; placed after ; the logging of any normal message in this call ; logger : out, optional, type=object ; `MGffLogger` object ; quit : in, optional, type=boolean ; set to quit logging; will log an normal message in this call before ; quitting ; _extra : in, optional, type=keywords ; keywords to `MGffLogger::setProperty` to configure the logger ;- pro mg_log, msg, arg1, arg2, arg3, name=name, $ debug=debug, informational=informational, $ warning=warning, error=error, critical=critical, $ last_error=lastError, $ logger=logger, quit=quit, _extra=e compile_opt strictarr on_error, 2 @mg_log_common case n_params() of 0: _msg = '' 1: _msg = msg 2: _msg = string(arg1, format='(%"' + msg + '")') 3: _msg = string(arg1, arg2, format='(%"' + msg + '")') 4: _msg = string(arg1, arg2, arg3, format='(%"' + msg + '")') endcase ; create the top-level logger if it doesn't already exist in the ; mg_log_common common block if (~obj_valid(mgLogger)) then mgLogger = obj_new('MGffLogger', level=5) ; use (optional) name to lookup actual logger or use the top-level logger ; if not named logger = n_elements(name) eq 0L ? mgLogger : mgLogger->getByName(name) ; pass on keywords to the logger logger->setProperty, _extra=e ; log messages if (n_params() gt 0L && obj_valid(logger)) then begin levels = [keyword_set(critical), $ keyword_set(error), $ keyword_set(warning), $ keyword_set(informational), $ keyword_set(debug)] level = max(levels * (lindgen(5) + 1L)) if (level eq 0L) then level = 5L ; default level is DEBUG logger->print, _msg, level=level, back_levels=1 endif ; do after regular messages so that a regular message and the stack trace ; can be logged with one call to MG_LOG if (keyword_set(lastError)) then logger->insertLastError, back_levels=1 ; do last so that a quitting message can be logged at the same time that the ; logger is shutdown if (keyword_set(quit)) then obj_destroy, logger end ; main-level example program mg_log, logger=logger logger->setProperty, level=3 print, 'Top level logger @ LEVEL=3:' mg_log, 'Debugging message', /debug ; won't show up since LEVEL=3 mg_log, 'Informational message', /informational ; won't show up since LEVEL=3 mg_log, 'Warning message', /warning mg_log, 'Error message', /error mg_log, 'Critical message', /critical mg_log, name='mg_log', logger=mgLogLogger mgLogLogger->setProperty, level=1 print print, 'mg_log logger @ LEVEL=1:' mg_log, 'Debugging message', name='mg_log', /debug mg_log, 'Informational message', name='mg_log', /informational mg_log, 'Warning message', name='mg_log', /warning mg_log, 'Error message', name='mg_log', /error mg_log, 'Critical message', name='mg_log', /critical mg_log, name='mg_log/example', logger=mgLogExampleLogger mgLogExampleLogger->setProperty, level=2 print print, 'mg_log/example logger @ LEVEL=2, mg_log logger @ LEVEL=1:' mg_log, 'Debugging message', name='mg_log/example', /debug mg_log, 'Informational message', name='mg_log/example', /informational mg_log, 'Warning message', name='mg_log/example', /warning mg_log, 'Error message', name='mg_log/example', /error mg_log, 'Critical message', name='mg_log/example', /critical mgLogLogger->setProperty, level=2 print print, 'mg_log/example logger @ LEVEL=2, mg_log logger @ LEVEL=2:' mg_log, 'Debugging message', name='mg_log/example', /debug mg_log, 'Informational message', name='mg_log/example', /informational mg_log, 'Warning message', name='mg_log/example', /warning mg_log, 'Error message', name='mg_log/example', /error mg_log, 'Critical message', name='mg_log/example', /critical mg_log, /quit end