Skip to content

Commit

Permalink
export use_tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
pvictor committed Jun 19, 2019
1 parent a73808d commit 5f97bf7
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 54 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: shinylogs
Title: Record Everything that Happens in a 'Shiny' Application
Version: 0.1.5.910
Version: 0.1.5.920
Authors@R: c(person("Fanny", "Meyer", email = "[email protected]", role = c("aut")),
person("Victor", "Perrier", email = "[email protected]", role = c("aut", "cre")),
person("Silex Technologies", comment = "https://www.silex-ip.com", role = "fnd"),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export(store_null)
export(store_rds)
export(store_sqlite)
export(track_usage)
export(use_tracking)
importFrom(DBI,dbConnect)
importFrom(DBI,dbDisconnect)
importFrom(DBI,dbWriteTable)
Expand Down
133 changes: 91 additions & 42 deletions R/tracking.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
#'
#' @description If used in \code{ui} of an application,
#' this will create new \code{input}s available in the server.
#' Set \code{dependencies = FALSE} in \code{\link{track_usage}}
#' server-side to load dependencies only once.
#'
#' @param on_unload Logical, save log when user close the browser window or tab,
#' if \code{TRUE} it prevent to create \code{shinylogs}
#' input during normal use of the application, there will
#' be created only on close, downside is that a popup will appear asking to close the page.
#' @param exclude_input Regular expression to exclude inputs from tracking.
#' @param exclude_input_regex Regular expression to exclude inputs from tracking.
#' @param exclude_input_id Vector of \code{inputId} to exclude from tracking.
#'
#' @note The following \code{input}s will be accessible in the server:
#'
Expand All @@ -22,27 +25,65 @@
#'
#' - \strong{.shinylogs_browserData} : information about the browser where application is displayed.
#'
#' @noRd
#' @export
#'
#' @importFrom htmltools attachDependencies tags singleton
#' @importFrom jsonlite toJSON
#' @importFrom nanotime nanotime
#' @importFrom bit64 as.integer64
#' @importFrom nanotime nanotime
#' @importFrom digest digest
tracking_ui <- function(on_unload = FALSE, exclude_input = NULL) {
#'
#' @examples
#' if (interactive()) {
#'
#' library(shiny)
#'
#' ui <- fluidPage(
#'
#' use_tracking(),
#'
#' splitLayout(
#' cellArgs = list(style = "height: 250px"),
#' radioButtons("radio", "Radio:", names(iris)),
#' checkboxGroupInput("checkbox", "Checkbox:", names(iris)),
#' selectInput("select", "Select:", names(iris))
#' ),
#'
#' verbatimTextOutput("last")
#' )
#'
#' server <- function(input, output, session) {
#'
#' output$last <- renderPrint({
#' input$.shinylogs_lastInput
#' })
#'
#' }
#'
#' shinyApp(ui, server)
#'
#' }
use_tracking <- function(on_unload = FALSE, exclude_input_regex = NULL, exclude_input_id = NULL) {
app_name <- basename(getwd())
timestamp <- Sys.time()
init_log <- data.frame(
app = app_name,
server_connected = get_timestamp(timestamp),
stringsAsFactors = FALSE
)
timestamp <- format(as.integer64(nanotime(timestamp)), scientific = FALSE)
sessionid <- digest::digest(timestamp)
tag_log <- tags$div(tags$script(
init_log$sessionid <- digest::digest(timestamp)
tag_log <- tags$script(
id = "shinylogs-tracking",
type = "application/json",
`data-for` = "shinylogs",
toJSON(list(
toJSON(dropNulls(list(
logsonunload = isTRUE(on_unload),
excludeinput = exclude_input,
sessionid = sessionid
), auto_unbox = TRUE, json_verbatim = TRUE)
))
exclude_input_regex = exclude_input_regex,
exclude_input_id = exclude_input_id,
sessionid = init_log$sessionid
)), auto_unbox = TRUE, json_verbatim = TRUE)
)
attachDependencies(
x = singleton(tag_log),
value = list(
Expand Down Expand Up @@ -90,6 +131,7 @@ parse_lastInput <- function(x, shinysession, name) {
#' @param exclude_users Character vectors of user for whom it is not necessary to save the log.
#' @param get_user A \code{function} to get user name, it should
#' return a character and take one argument: the Shiny session.
#' @param dependencies Load dependencies.
#' @param session The shiny session.
#'
#' @export
Expand Down Expand Up @@ -262,6 +304,7 @@ track_usage <- function(storage_mode,
on_unload = FALSE,
exclude_users = NULL,
get_user = NULL,
dependencies = TRUE,
session = getDefaultReactiveDomain()) {

stopifnot(inherits(storage_mode, "shinylogs.storage_mode"))
Expand All @@ -283,35 +326,37 @@ track_usage <- function(storage_mode,
storage_mode$timestamp <- format(as.integer64(nanotime(timestamp)), scientific = FALSE)
init_log$sessionid <- digest::digest(storage_mode$timestamp)

insertUI(
selector = "body", where = "afterBegin",
ui = singleton(tags$script(
id = "shinylogs-tracking",
type = "application/json",
`data-for` = "shinylogs",
toJSON(dropNulls(list(
logsonunload = isTRUE(on_unload),
exclude_input_regex = exclude_input_regex,
exclude_input_id = exclude_input_id,
sessionid = init_log$sessionid
)), auto_unbox = TRUE, json_verbatim = TRUE)
)),
immediate = TRUE,
session = session
)
insertUI(
selector = "body", where = "afterBegin",
ui = attachDependencies(
x = tags$div(),
value = list(
localforage_dependencies(),
dayjs_dependencies(),
shinylogs_lf_dependencies()
)
),
immediate = FALSE,
session = session
)
if (isTRUE(dependencies)) {
insertUI(
selector = "body", where = "afterBegin",
ui = singleton(tags$script(
id = "shinylogs-tracking",
type = "application/json",
`data-for` = "shinylogs",
toJSON(dropNulls(list(
logsonunload = isTRUE(on_unload),
exclude_input_regex = exclude_input_regex,
exclude_input_id = exclude_input_id,
sessionid = init_log$sessionid
)), auto_unbox = TRUE, json_verbatim = TRUE)
)),
immediate = TRUE,
session = session
)
insertUI(
selector = "body", where = "afterBegin",
ui = attachDependencies(
x = tags$div(),
value = list(
localforage_dependencies(),
dayjs_dependencies(),
shinylogs_lf_dependencies()
)
),
immediate = FALSE,
session = session
)
}


if (isTRUE(storage_mode$console)) {
Expand All @@ -331,8 +376,12 @@ track_usage <- function(storage_mode,
isolate(session$input$.shinylogs_error),
isolate(session$input$.shinylogs_output))
browser_data <- isolate(session$input$.shinylogs_browserData)
browser_data <- as.data.frame(browser_data)
logs$session <- cbind(init_log, browser_data)
if (!is.null(browser_data)) {
browser_data <- as.data.frame(browser_data)
logs$session <- cbind(init_log, browser_data)
} else {
logs$session <- init_log
}
if (isTRUE(!user %in% exclude_users)) {
write_logs(storage_mode, logs)
}
Expand Down
24 changes: 14 additions & 10 deletions inst/assets/js/shinylogs-localForage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
* using Lowdb
* https://github.com/dreamRs/shinylogs
*
* @version 0.0.1
* @version 0.0.2
*/
// on unload or not


// config
Expand Down Expand Up @@ -72,14 +71,16 @@ var browser_connected = dayjs().format();

// Send browser data
if (logsonunload === false) {
Shiny.setInputValue(".shinylogs_browserData", {
user_agent: ua,
screen_res: screen_res,
browser_res: browser_res,
pixel_ratio: pixel_ratio,
browser_connected: browser_connected
}, {
priority: "event"
$(document).on("shiny:connected", function() {
Shiny.setInputValue(".shinylogs_browserData", {
user_agent: ua,
screen_res: screen_res,
browser_res: browser_res,
pixel_ratio: pixel_ratio,
browser_connected: browser_connected
}, {
priority: "event"
});
});
}

Expand Down Expand Up @@ -180,3 +181,6 @@ if (logsonunload === true) {
return "Are you sure?";
};
}



5 changes: 4 additions & 1 deletion man/track_usage.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions man/use_tracking.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5f97bf7

Please sign in to comment.