11 Print debugging
In the previous chapter we covered the interactive debugger in Positron with browser()
and observe()
. In this chapter, we’ll explore another commonly used technique for identifying and resolving issues or errors in your code: print debugging.
11.1 Exposing variables and values
Launch app with the shinypak
package:
launch('11_debug-print')
Print debugging uses a simpler approach than the interactive debugger, and it’s well-suited for a variety of development workflows. Print debugging involves inserting a print()
(or cat()
) statement into the body of a function to output variables, values, or other important information at various points.
11.2 Reactive printing
To track reactivity, we need to place the print functions in a reactive expression, observer, or event handler. This allows us to see when these values are triggered (and any other values they work with).
Using well-placed calls to print()
or cat()
allows us to display input values, which helps us to understand the inner-workings of our application.
For example, placing the code below in the server function of our variable input module will print the selected variables to the console:
<- function(id) {
mod_var_input_server
moduleServer(id, function(input, output, session) {
observe({
cat("Selected x, y, and color:\n")
print(c('x' = input$x,
'y' = input$y,
'color' = input$z))
|>
}) bindEvent(c(input$x, input$y, input$x))
return(
reactive({
list(
"y" = input$y,
"x" = input$x,
"z" = input$z,
"alpha" = input$alpha,
"size" = input$size,
"plot_title" = input$plot_title
)
})
)
}) }
- 1
-
Wrap in
observe()
to provide reactive context for printing
- 2
-
Print message with
cat()
- 3
-
Print reactives with
print()
- 4
- Bind this event to print whenever the variable inputs change
After running the function, we can view the output in the Console (or log file).
Unfortunately, print()
and cat()
can only provide a snapshot of values or variables at the location and time of the print call. This limits their usefulness in exploring the other parts of the environment or interacting with the running application.
However, we can place verbatimTextOutput()
in our module UI function:
show/hide updated mod_var_input_ui()
<- function(id) {
mod_var_input_ui <- NS(id)
ns tagList(
selectInput(
inputId = ns("y"),
label = "Y-axis:",
choices = c(
"IMDB rating" = "imdb_rating",
"IMDB number of votes" = "imdb_num_votes",
"Critics Score" = "critics_score",
"Audience Score" = "audience_score",
"Runtime" = "runtime"
),selected = "audience_score"
),selectInput(
inputId = ns("x"),
label = "X-axis:",
choices = c(
"IMDB rating" = "imdb_rating",
"IMDB number of votes" = "imdb_num_votes",
"Critics Score" = "critics_score",
"Audience Score" = "audience_score",
"Runtime" = "runtime"
),selected = "imdb_rating"
),selectInput(
inputId = ns("z"),
label = "Color by:",
choices = c(
"Title Type" = "title_type",
"Genre" = "genre",
"MPAA Rating" = "mpaa_rating",
"Critics Rating" = "critics_rating",
"Audience Rating" = "audience_rating"
),selected = "mpaa_rating"
),verbatimTextOutput(ns("vars")),
sliderInput(
inputId = ns("alpha"),
label = "Alpha:",
min = 0, max = 1, step = 0.1,
value = 0.5
),sliderInput(
inputId = ns("size"),
label = "Size:",
min = 0, max = 5,
value = 2
),textInput(
inputId = ns("plot_title"),
label = "Plot title",
placeholder = "Enter plot title"
)
) }
- 1
- Print the values to the UI
And an accompanying renderPrint()
in the module server function to print the values in the UI:
show/hide updated mod_var_input_server()
<- function(id) {
mod_var_input_server
moduleServer(id, function(input, output, session) {
observe({
cat("Selected x, y, and color:\n")
print(c('x' = input$x,
'y' = input$y,
'color' = input$z))
$vars <- renderPrint({
outputlist('x' = input$x,
'y' = input$y,
'color' = input$z)
})|>
}) bindEvent(c(input$x, input$y, input$x))
return(
reactive({
list(
"y" = input$y,
"x" = input$x,
"z" = input$z,
"alpha" = input$alpha,
"size" = input$size,
"plot_title" = input$plot_title
)
})
)
}) }
- 1
- Reactive context
- 2
-
Print message with
cat()
- 3
-
Print to inputs with
print()
- 4
-
Print inputs to UI
- 5
- Bind this event to print whenever the variable inputs change
This allows us to view the inputs in the UI as they change in the server.
11.3 Reactive values
A powerful tool for capturing and printing input values in the server is reactiveValuesToList()
:
reactiveValuesToList(x = , all.names = )
- 1
-
I recommend setting
all.names
toTRUE
.
This function can be used inside server-side code (modules or server functions) to collect all the input values. When placed in the app server function, the function will return the inputs from both modules.
Below is an example of using reactiveValuesToList()
inside the our app server function:
<- function(input, output, session) {
movies_server
$vals <- renderPrint({
output<- reactiveValuesToList(x = input, all.names = TRUE)
app_vals str(app_vals)
})
<- mod_var_input_server("vars")
selected_vars
mod_scatter_display_server("plot", var_inputs = selected_vars)
}
We’ll also add the following to the bslib = TRUE
section of movies_ui()
to print the output of the reactive list to the UI:
<- function(bslib = FALSE) {
movies_ui addResourcePath(
prefix = 'www',
directoryPath = system.file('www/', package = 'sap'))
if (isFALSE(bslib)) {
tagList(
::page_fillable(
bslibh1("Movie Reviews"),
::layout_sidebar(
bslibsidebar =
::sidebar(
bslibtitle = tags$h4("Sidebar inputs"),
img(
src = "www/shiny.png",
height = 60,
width = 55,
style = "margin:10px 10px"
),mod_var_input_ui("vars")
),::card(
bslibfull_screen = TRUE,
::card_header(
bslib$h4("Scatter Plot")
tags
),::card_body(fillable = TRUE,
bslibmod_scatter_display_ui("plot")
),::card_footer(
bslib$blockquote(
tags$em(
tags$p(
tags"The data for this application comes from the ",
$a("Building web applications with Shiny",
tagshref = "https://rstudio-education.github.io/shiny-course/"
),"tutorial"
)
)
)
)
)
)
)
)else {
} tagList(
::page_fillable(
bslibtitle = "Movie Reviews (bslib)",
theme = bslib::bs_theme(
bg = "#101010",
fg = "#F6F5F5",
primary = "#EE6F57",
secondary = "#32E0C4",
success = "#FF4B5C",
base_font = sass::font_google("Ubuntu"),
heading_font = sass::font_google("Ubuntu")
),::layout_sidebar(
bslibsidebar = bslib::sidebar(
mod_var_input_ui("vars")
),::card(
bslibfull_screen = TRUE,
::card_header(
bslib$img(
tagssrc = "www/bootstrap.png",
height = 80,
width = 100,
style = "margin:10px 10px"
)
),::card_body(
bslibverbatimTextOutput(outputId = "vals"),
mod_scatter_display_ui("plot")
)
)
)
)
)
} }
- 1
- Printed reactive value outputs
After loading the changes to our package, we can view the application with the captured and printed reactive values:
Note the difference between the two printed values: the output in the sidebar has been printed from within the module server function, so the input names are contained within that namespace (i.e., x
, y
, etc.). However, the list returned from reactiveValuesToList()
has been placed in the app server function, so we can see the module id
appended to the input name (i.e., vars-y
, vars-x
, etc.).