Condition Handling With Logging

Condition Handling

The book Advanced R has a great section on conditions, and how to handle them. Please be sure to review that before continuing with the rest of this section.

Also note that webR is enabled for this page, so you can run the code interactively and get a better sense of how this all works!

Conditions

Ok, so maybe you didn’t spend the time reading the chapter on conditions in Advanced R, so here’s a quick rundown:

  • Conditions in R is similar to Python and raising an exception. Read Hadley’s translation of Peter Seibel’s condition system in Lisp to R), with a few differences.

  • Conditions can be signaled through errors, warnings, and messages (stop, warning, message , respectively)

    • In stringr, interp.R shows an example of stop(), which will result in stopping the execution of any code.

      • # If there are nested placeholders, each part will not contain a full
        
        # placeholder in which case we report invalid string interpolation template.
        
        if (any(!grepl("\\\\\$(\\\\\[.\*?\\\\\])?\\\\{.+\\\\}", parts)))
        
            stop("Invalid template string for interpolation.", call. = FALSE)
  • You can ignore conditions (using try(), surpressWarnings() , or surpressMessages() ) so that code will execute even if it errors

  • You can also handle them (tryCatch() and withCallingHandlers()) to override the default of stopping your code execution, and perhaps try running the code that failed in an alternative way.

Signalling Conditions

Try running the code below and see what happens.


Notice how the last code does not run? That’s because the stop() function stops additional code from executing. Try changing it to a warning() and see what happens.

Examples of Condition Handling

Let’s jump right into some examples of condition handling. We’ll use the same example in the Introduction section that introduced tryCatch().

The example below will print out a warning message when log() is attempting to compute a negative number. As a result, we print out a message saying something went wrong, and suggest that a negative number was computed, and pass along the warning message that log() generates.


Be sure to review the output above. You’ll see the warning message Uh oh…simpleWarning in log(i): NaNs produced\n

Now try modifying the code above, and change Line 23 so that log() computes the absolute value of i .

If you get stuck, expand the code block below!

Show the code
      # calculate the log of value i
      print(paste("The log of i is: ", log(i)))
      
      # if a warning is thrown from running log(), then handle it
      , warning = function(w) {
        
        print(paste0("Uh oh. Something went wrong. Is i a negative number?: ", w))
        
        # MODIFY CODE HERE. 
        # take absolute value of i instead
        print(paste0("Using absolute value instead. The log of abs(i) is: ", log(abs(i))))

      }

Other great examples where tryCatch can apply:

  • You want to create a database connection. But if it fails, then stop() any further code execution. Or use warning() and try connecting to an alternative database or system. If this happens repeatedly then you can set up ways to get notified of recurring warnings() happening in your code.
  • You are doing some ETL process, but for whatever reason a row in the data frame can’t be processed. You can send a warning() condition and continue processing subsequent rows.

Condition Handling with log4r

Let’s convert the same code above, but include logging with the log4r package.


With a logging package like log4r, it’s easier to see the urgency of each message. Several of these statements are just informational. But it’s clear when a WARN message occurs, and you can use logging systems to alert on these specific severity levels.