Record logs in shiny apps"

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE
)
library(shinylogs)

How to use

Add in your server :

# server
track_usage(storage_mode = store_json(path = "logs/"))

It will store logs in a sub-folder logs/ of your application.

If needed (in complex application), you can force dependencies in UI with :

# UI
use_tracking()

Storage modes

Four modes are available:

Deployment method

Shiny server, RStudio Connect

On a server, if you want to save logs on disk, don't forget to set write permission on the folder you want to save logs.

On RStudio Connect, you need to use an absolute path to specify the directory where to save logs. You can find more information here: Persistent Storage on RStudio Connect

ShinyProxy

With ShinyProxy, you can use a Docker volume to write logs outside of the application container. In application.yml, you can something like this in the specs describing the application:

container-volumes: [ "/var/log/shinylogs:/root/logs" ]

/var/log/shinylogs is a directory on the server where you deploy your applications with ShinyProxy. /root/logs is a directory inside your Docker image, it's the path you can use in track_usage(), e.g. :

track_usage(
  storage_mode = store_json(path = "/root/logs")
)

shinyapps.io

There's no persistent data storage on shinyapps.io, so you can't save logs as JSON or RDS files, you have to use a remote storage method. You can use the builtin method provided to send logs in Googledrive with store_googledrive or use store_custom to send logs wherever you want (dropbox, remote database, ...).

To use Googledrive, you'll need to work with Google's API and set auth to your account, see {gargle} documentation for examples and how to.

Recorded informations

Session

Those data are metadata about the application and the user's browser, here are the filed recorded :

Example:

data.frame(stringsAsFactors=FALSE,
                   app = c("iris-cluster", "iris-cluster", "iris-cluster", "iris-cluster", "iris-cluster", "iris-cluster"),
                  user = c("dreamRs", "dreamRs", "dreamRs", "dreamRs", "dreamRs", "dreamRs"),
      server_connected = c("2019-06-19 14:07:09", "2019-06-19 14:56:32",
                           "2019-06-19 14:57:45", "2019-06-19 15:03:00",
                           "2019-06-19 15:08:53", "2019-08-04 10:58:47"),
             sessionid = c("9815194cfaa6317fbea68ae9537d63d1",
                           "0feeacf3201f5cca088059cec2b0a710",
                           "8b12c138f159cc5805e136338dddac59",
                           "f3950a1588b78d45c53c756a4136df67", "254cafb3d5866384f13022d066546cae",
                           "8a431f4b90b3b1926047dd2539be0793"),
   server_disconnected = c("2019-06-19 14:07:17", "2019-06-19 14:57:39",
                           "2019-06-19 15:01:36", "2019-06-19 15:08:13",
                           "2019-06-19 15:09:38", "2019-08-04 10:58:49"),
            user_agent = c("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
                           "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
                           "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
                           "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
                           "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", NA),
            screen_res = c("1920x1080", "1920x1080", "1920x1080", "1920x1080",
                           "1920x1080", NA),
           browser_res = c("1574x724", "1920x937", "1920x937", "1920x937",
                           "1920x937", NA),
           pixel_ratio = c(1L, 1L, 1L, 1L, 1L, NA),
     browser_connected = c("2019-06-19 14:07:09", "2019-06-19 14:56:32",
                           "2019-06-19 14:57:45", "2019-06-19 15:03:00",
                           "2019-06-19 15:08:53", NA)
)

Inputs

Data about inputs, by default all inputs are recorded (even those not define by developper, like with {htmlwidgets} : {DT}, {leaflet}, ...)

Example:

data.frame(stringsAsFactors=FALSE,
   sessionid = c("9815194cfaa6317fbea68ae9537d63d1",
                 "9815194cfaa6317fbea68ae9537d63d1",
                 "9815194cfaa6317fbea68ae9537d63d1", "9815194cfaa6317fbea68ae9537d63d1",
                 "9815194cfaa6317fbea68ae9537d63d1", "9815194cfaa6317fbea68ae9537d63d1"),
        name = c("xcol", "clusters", "clusters", "clusters", "clusters",
                 "clusters"),
   timestamp = c("2019-06-19 14:07:11", "2019-06-19 14:07:15",
                 "2019-06-19 14:07:15", "2019-06-19 14:07:15",
                 "2019-06-19 14:07:14", "2019-06-19 14:07:13"),
       value = c("Sepal.Width", 6, 4, 5, 7, 4),
        type = c(NA, "shiny.number", "shiny.number", "shiny.number",
                 "shiny.number", "shiny.number"),
     binding = c("shiny.selectInput", "shiny.numberInput", "shiny.numberInput",
                 "shiny.numberInput", "shiny.numberInput",
                 "shiny.numberInput")
)

Outputs

Data recorded each time an output is refreshed :

Example:

data.frame(stringsAsFactors=FALSE,
   sessionid = c("9815194cfaa6317fbea68ae9537d63d1",
                 "9815194cfaa6317fbea68ae9537d63d1",
                 "9815194cfaa6317fbea68ae9537d63d1", "9815194cfaa6317fbea68ae9537d63d1",
                 "9815194cfaa6317fbea68ae9537d63d1", "9815194cfaa6317fbea68ae9537d63d1"),
        name = c("plot1", "plot1", "plot1", "plot1", "plot1", "plot1"),
   timestamp = c("2019-06-19 14:07:15", "2019-06-19 14:07:15",
                 "2019-06-19 14:07:14", "2019-06-19 14:07:15",
                 "2019-06-19 14:07:11", "2019-06-19 14:07:10"),
     binding = c("shiny.imageOutput", "shiny.imageOutput", "shiny.imageOutput",
                 "shiny.imageOutput", "shiny.imageOutput",
                 "shiny.imageOutput")
)

Errors

Errors are recorded only when propagated through an output, this is the red message users see in application, infos saved are:

Example:

data.frame(stringsAsFactors=FALSE,
   sessionid = c("f8f50a3743023aae7d0d6350a2fd6841"),
        name = c("plot1"),
   timestamp = c("2019-06-19 14:07:18"),
       error = c("NA/NaN/Inf in foreign function call (arg 1)")
)


Try the shinylogs package in your browser

Any scripts or data that you put into this service are public.

shinylogs documentation built on April 18, 2022, 5:05 p.m.