A General Message and Error Reporting System

Provides a system for reporting messages, which provides certain useful features over the standard R system, such as the incorporation of output consolidation, message filtering, assertions, expression substitution, automatic generation of stack traces for debugging, and conditional reporting based on the current "output level".


The reportr package for R is a simple alternative to R's standard functions for producing informative output, such as message(), warning() and stop(). It offers a certain amount more flexibility than these functions, although it is not (yet) a full logging solution. The package is available on CRAN.

Further alternatives in this area include the futile.logger, log4r and logging packages.

Contents

Usage

The key functions in the package are report() and flag(). Both take a reporting level as their first argument, which determines the priority of the message. The functions differ only in that report() reports the message to the console immediately, whereas flag(), like warning(), saves it for reporting later. Flagged messages are reported at the next report() call, to keep output in order.

The setOutputLevel() function determines the minimal reporting level for which output is actually generated; messages below this level are discarded. This is demonstrated below, by creating a message of level Info with the output level set first to Warning (which produces nothing) and then to Info (which allows the message to be reported).

setOutputLevel(Warning)
report(Info, "Test message")
 
setOutputLevel(Info)
report(Info, "Test message")
## INFO: Test message

The reporting levels available, in ascending order of priority, are currently Debug, Verbose, Info, Warning, Question, Error and Fatal. The Error level raises R's "abort" condition, like stop(), so execution will stop. The Fatal level is in practice never used, but can be set as the output level to subdue all reporting.

Using reportr to handle standard messages

It is possible to arrange for reportr to handle messages, warnings and errors raised by code that does not itself use report() or flag(), by using the wrapper function withReportrHandlers(). Take, for example, the simple function

f <- function() message("In f()")

Ordinarily calling this function produces

f()
## In f()

Wrapping this will instead give

withReportrHandlers(f())
## * INFO: In f()

Note that calls to message(...) will translate to report(Info, ...), warning(...) to flag(Warning, ...), and stop(...) to report(Error, ...).

This mechanism is not particularly advantageous in itself, but it allows the user to exercise all of the reportr control options over all code, whether or not it was written with reportr in mind. These facilities are laid out below.

Output consolidation

Sometimes the same warning is generated many times, and seeing a lot of replication isn't particularly helpful. The following function is somewhat artificial, since it does not take advantage of vectorisation in R, but it illustrates the point.

f <- function(xs) {
    ys <- numeric(0)
    for (x in xs) ys <- c(ys,sqrt(x))
    ys
}

Now let's call the function with input that will produce some warnings.

f(-5:5)
##  [1]      NaN      NaN      NaN      NaN      NaN 0.000000 1.000000 1.414214
##  [9] 1.732051 2.000000 2.236068
## Warning messages:
## 1: In sqrt(x) : NaNs produced
## 2: In sqrt(x) : NaNs produced
## 3: In sqrt(x) : NaNs produced
## 4: In sqrt(x) : NaNs produced
## 5: In sqrt(x) : NaNs produced

This duplication of warnings is verbose and unnecessary, and can be consolidated with reportr:

withReportrHandlers(f(-5:5))
## WARNING: [x5] NaNs produced
##  [1]      NaN      NaN      NaN      NaN      NaN 0.000000 1.000000 1.414214
##  [9] 1.732051 2.000000 2.236068

Notice that the five duplicated warnings are reported in one line in this case, along with an indication that the message was produced five times.

Expression substitution

Expression substitution is an alternative to printf-style syntax for incorporating the values of R expressions into strings. It can make messages more readable, and reduce the need for lots of quotation marks. All reportr messages are passed through the es() function for expression substitution, which is part of the ore package. For example,

x <- 3
report(Info, "The value of x is #{x}")
## INFO: The value of x is 3

Note the #{} syntax. Everything within the curly braces is evaluated as an R expression, and the result inserted into the string. Please see ?ore::es for more details.

Message filtering

Sometimes it may be desirable to discard particular messages that would otherwise be reported at the current output level. There are two global options that allow this, reportrMessageFilterIn and reportrMessageFilterOut, each of which takes a Perl-style regular expression. The "in" filter is applied first, keeping only messages that match its regex, and then the "out" filter, which keeps only messages that do not match its regex.

f <- function() {
    report(Info, "One")
    report(Info, "Two")
    report(Info, "Three")
}
 
options(reportrMessageFilterIn="^T")
f()
## * INFO: Two
## * INFO: Three
 
options(reportrMessageFilterIn=NULL, reportrMessageFilterOut="^T")
f()
## * INFO: One

Stack tracing

The Debug reporting level is slightly special. When the current output level is Debug, not only are all messages reported, but stack traces are also automatically provided when the message being reported is of level equal to or above the reportrStackTraceLevel option (the default is Error). For example,

f <- function(x) if (!is.numeric(x)) stop("x must be numeric")
g <- function(x) f(x)
 
withReportrHandlers(g("text"))
## * * ERROR: x must be numeric (in "f(x)")
## --- Begin stack trace ---
## * g("text")
## * * f(x)
## ---  End stack trace  ---

Notice that the number of asterisks in front of the printed message indicates the depth in the stack of the function reporting the message. This can be useful, in a long stream of output, to determine the structure of the reporting code at a glance. The format of this "prefix" can be customised, however: please see ?report for details.

The Question reporting level

In between the Warning and Error reporting levels is a level called Question. This level is used by a function called ask(), which prompts the user for input and returns the result in a string. If the output level is greater than Question, or the session is not interactive, a customisable default value is returned.

f <- function() {
    name <- ask("What is your name?", default="Nobody")
    report(OL$Info, "Hello, #{name}")
    invisible(name)
}
 
setOutputLevel(Info)
f()
## * QUESTION: What is your name? User
## * INFO: Hello, User
 
setOutputLevel(Error)
(f())
## [1] "Nobody"

News

Significant changes to the reportr package are laid out below for each release.

=================================================================================

VERSION 1.3.0

  • The new assert() function reports a message (by default an error) if its first argument produces an error or does not evaluate TRUE.
  • The ask() function gains a "valid" argument, which specifies valid responses. If it is given, the user will be asked repeatedly until they give a suitable answer.

=================================================================================

VERSION 1.2.2

  • The report() function now checks whether the output level is low enough for the message to be displayed, before constructing it. This can save a lot of overhead time when many debug-type messages are to be skipped over.

=================================================================================

VERSION 1.2.1

  • Use of the "%p" syntax in a prefix format string previously caused an error. This has been corrected.
  • The tests have been updated for compatibility with a new version of testthat.

=================================================================================

VERSION 1.2.0

  • The "ore" package is now used by "reportr". It provides improved versions of some of the package's auxiliary functionality. As a result, the s() function and %~% and %!~% operators are no longer exported by "reportr". Please see es(), %~% and %~~% from "ore" instead.
  • It is now possible to configure the level at which the stderr stream is used, using the "reportrStderrLevel" option.
  • A "Fatal" output level has been added. In practice it is never used, but the output level can be set to it, to suppress all output.
  • Flags are now reported at the end of a call to withReportrHandlers().
  • The ask() function now also returns the default value if the R session is noninteractive.
  • The return value from getOutputLevel() is now named with the level name.
  • A set of tests, and a README file, have been added to the package.

=================================================================================

VERSION 1.1.2

  • The "level" argument to report() or flag() may now be given without the "OL$" prefix, viz. report(Info, "Test").

=================================================================================

VERSION 1.1.1

  • The s() function is now vectorised on its first argument.

=================================================================================

VERSION 1.1.0

  • Expression substitution is now performed on messages, using Ruby-like syntax. This allows R expressions to be interpolated into message strings for brevity and clarity.
  • Error messages and stack trace elements are now truncated to keep output readable.

=================================================================================

VERSION 1.0.1

  • Messages are now only printed to stderr() when their level is Warning or higher.

=================================================================================

VERSION 1.0.0

  • Errors generated within the expression passed to withReportrHandlers() are now reported with information on the call, if available. Relevant information should therefore no longer be lost when using reportr, as opposed to the standard R error-reporting system.
  • A "reportrStackTraceLevel" option is now available, allowing for the generation of stack traces at lower output levels than Error if required. The default behaviour is as before.
  • The clearFlags() function has been added, which removes any pending flags.

=================================================================================

VERSION 0.2.0

  • Substantial reworking of the package for greater generality. New functions ask(), getOutputLevel() and withReportrHandlers(), and new infix operator %!~%, have been added. Arguments to other functions have been changed in some cases. The principal mechanisms of report() and flag() remain the same, however.
  • A series of new options can be used for flexible message and stack filtering. See ?report for details.
  • The format of the string prepended to messages can now be customised, rather than just switched on or off. See ?report for details.
  • The new function withReportrHandlers() evaluates an R expression in a context in which reportr handles any errors, warnings and messages raised by it.
  • The new function ask(...) replaces report(OL$Question, ...).
  • Various other tweaks have been made, including one for compatibility with changes coming in R 2.14.0.

=================================================================================

VERSION 0.1.0

  • First public release.

=================================================================================

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("reportr")

1.3.0 by Jon Clayden, 9 months ago


https://github.com/jonclayden/reportr


Report a bug at https://github.com/jonclayden/reportr/issues


Browse source code at https://github.com/cran/reportr


Authors: Jon Clayden


Documentation:   PDF Manual  


GPL-2 license


Imports ore

Suggests testthat


Imported by hybridEnsemble, soma, tractor.base.

Suggested by RNifti.


See at CRAN