From a3b4d8664417c1060ef74c9adb192e1ba59f44f5 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Thu, 8 Aug 2024 14:55:48 -0500 Subject: [PATCH 1/9] Run more examples Requires some new techology to ensure that (a) examples don't affect global logging state and (b) use `appender_stdout()` inside `R CMD check`. I also had to fix a few to make them actually work, since they clearly haven't been run for a while. Also took this opportunity to not generate `.Rd` files for all non-exported function. Fixes #164 --- R/appenders.R | 16 ++++++---- R/formatters.R | 18 ++++++----- R/helpers.R | 17 ++++++----- R/layouts.R | 22 +++++++++----- R/logger.R | 43 ++++++++++++++------------- R/utils.R | 17 ++++++----- R/zzz.R | 51 +++++++++++++++++++------------- man/appender_file.Rd | 9 +++--- man/catch_base_log.Rd | 36 ---------------------- man/fail_on_missing_package.Rd | 4 +-- man/fallback_namespace.Rd | 18 ----------- man/formatter_glue_or_sprintf.Rd | 2 -- man/formatter_json.Rd | 4 +-- man/formatter_logging.Rd | 4 +-- man/formatter_pander.Rd | 4 +-- man/get_logger_definitions.Rd | 21 ------------- man/layout_glue_generator.Rd | 4 +-- man/layout_json.Rd | 4 +-- man/layout_json_parser.Rd | 6 ++-- man/layout_logging.Rd | 4 ++- man/log_appender.Rd | 9 +++--- man/log_eval.Rd | 4 +-- man/log_failure.Rd | 4 +-- man/log_layout.Rd | 4 +-- man/log_level.Rd | 11 +++---- man/log_separator.Rd | 2 ++ man/log_threshold.Rd | 4 +-- man/log_tictoc.Rd | 2 -- man/log_with_separator.Rd | 2 ++ man/top_env_name.Rd | 18 ----------- man/validate_log_level.Rd | 18 ----------- man/with_log_threshold.Rd | 4 +-- 32 files changed, 152 insertions(+), 234 deletions(-) delete mode 100644 man/catch_base_log.Rd delete mode 100644 man/fallback_namespace.Rd delete mode 100644 man/get_logger_definitions.Rd delete mode 100644 man/top_env_name.Rd delete mode 100644 man/validate_log_level.Rd diff --git a/R/appenders.R b/R/appenders.R index 2e880034..09eb1666 100644 --- a/R/appenders.R +++ b/R/appenders.R @@ -48,7 +48,8 @@ appender_stdout <- structure(function(lines) { #' @export #' @return function taking `lines` argument #' @family `log_appenders` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' ## ########################################################################## #' ## simple example logging to a file #' t <- tempfile() @@ -68,6 +69,8 @@ appender_stdout <- structure(function(lines) { #' ## define the file logger with log rotation enabled #' log_appender(appender_file(f, max_lines = 3, max_files = 5L)) #' +#' ## enable internal logging to see what's actually happening in the logrotate steps +#' log_threshold(TRACE, namespace = ".logger") #' ## log 25 messages #' for (i in 1:25) log_info(i) #' @@ -77,10 +80,7 @@ appender_stdout <- structure(function(lines) { #' cat(readLines(t), sep = "\n") #' }) #' -#' ## enable internal logging to see what's actually happening in the logrotate steps -#' log_threshold(TRACE, namespace = ".logger") -#' ## run the above commands again -#' } +#' \dontshow{logger:::namespaces_set(old)} appender_file <- function(file, append = TRUE, max_lines = Inf, max_bytes = Inf, max_files = 1L) { # nolint force(file) force(append) @@ -166,7 +166,11 @@ appender_tee <- function(file, append = TRUE, max_lines = Inf, max_bytes = Inf, force(max_files) structure( function(lines) { - appender_console(lines) + if (in_pkgdown() || is_checking_logger()) { + appender_stdout(lines) + } else { + appender_console(lines) + } appender_file(file, append, max_lines, max_bytes, max_files)(lines) }, generator = deparse(match.call()) diff --git a/R/formatters.R b/R/formatters.R index d6acb039..b3ea392d 100644 --- a/R/formatters.R +++ b/R/formatters.R @@ -99,7 +99,7 @@ formatter_glue_safe <- structure(function(..., #' @return character vector #' @family `log_formatters` #' @export -#' @examples \dontrun{ +#' @examples #' formatter_glue_or_sprintf("{a} + {b} = %s", a = 2, b = 3, 5) #' formatter_glue_or_sprintf("{pi} * {2} = %s", pi * 2) #' formatter_glue_or_sprintf("{pi} * {2} = {pi*2}") @@ -109,7 +109,6 @@ formatter_glue_safe <- structure(function(..., #' formatter_glue_or_sprintf("Hi {c('foo', 'bar')}, did you know that 2*4=%s", 2 * 4) #' formatter_glue_or_sprintf("Hi %s, did you know that 2*4={2*4}", c("foo", "bar")) #' formatter_glue_or_sprintf("Hi %s, did you know that 2*4=%s", c("foo", "bar"), 2 * 4) -#' } formatter_glue_or_sprintf <- structure(function(msg, ..., .logcall = sys.call(), .topcall = sys.call(-1), .topenv = parent.frame()) { @@ -168,12 +167,13 @@ formatter_glue_or_sprintf <- structure(function(msg, ..., #' @export #' @note This functionality depends on the \pkg{jsonlite} package. #' @family `log_formatters` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_formatter(formatter_json) #' log_layout(layout_json_parser()) #' log_info(everything = 42) #' log_info(mtcars = mtcars, species = iris$Species) -#' } +#' \dontshow{logger:::namespaces_set(old)} formatter_json <- structure(function(..., .logcall = sys.call(), .topcall = sys.call(-1), .topenv = parent.frame()) { fail_on_missing_package("jsonlite") @@ -219,7 +219,8 @@ skip_formatter <- function(message, ...) { #' @return character vector #' @export #' @family `log_formatters` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_formatter(formatter_logging) #' log_info("42") #' log_info(42) @@ -227,7 +228,7 @@ skip_formatter <- function(message, ...) { #' log_info("foo %s", "bar") #' log_info("vector %s", 1:3) #' log_info(12, 1 + 1, 2 * 2) -#' } +#' \dontshow{logger:::namespaces_set(old)} formatter_logging <- structure(function(..., .logcall = sys.call(), .topcall = sys.call(-1), .topenv = parent.frame()) { params <- list(...) @@ -251,7 +252,8 @@ formatter_logging <- structure(function(..., #' @note This functionality depends on the \pkg{pander} package. #' @export #' @family `log_formatters` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_formatter(formatter_pander) #' log_info("42") #' log_info(42) @@ -259,7 +261,7 @@ formatter_logging <- structure(function(..., #' log_info(head(iris)) #' log_info(head(iris), style = "simple") #' log_info(lm(hp ~ wt, mtcars)) -#' } +#' \dontshow{logger:::namespaces_set(old)} formatter_pander <- structure(function(x, ..., .logcall = sys.call(), .topcall = sys.call(-1), .topenv = parent.frame()) { fail_on_missing_package("pander") diff --git a/R/helpers.R b/R/helpers.R index d3d7b43f..ac8ebfd3 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -7,7 +7,8 @@ #' its result on a single line separated by `=>`, while setting to #' `TRUE` will log the expression and the result in separate #' sections reserving line-breaks and rendering the printed results -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_eval(pi * 2, level = INFO) #' #' ## lowering the log level threshold so that we don't have to set a higher level in log_eval @@ -36,7 +37,7 @@ #' #' ## doing something computationally intensive #' log_eval(system.time(for (i in 1:100) mad(runif(1000))), multiline = TRUE) -#' } +#' \dontshow{logger:::namespaces_set(old)} #' @importFrom utils capture.output #' @export log_eval <- function(expr, level = TRACE, multiline = FALSE) { @@ -84,6 +85,7 @@ log_eval <- function(expr, level = TRACE, multiline = FALSE) { #' @param width max width of message -- longer text will be wrapped into multiple lines #' @export #' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_separator() #' log_separator(ERROR, separator = "!", width = 60) #' log_separator(ERROR, separator = "!", width = 100) @@ -92,6 +94,7 @@ log_eval <- function(expr, level = TRACE, multiline = FALSE) { #' log_separator(ERROR, separator = "!", width = 100) #' log_layout(layout_blank) #' log_separator(ERROR, separator = "!", width = 80) +#' \dontshow{logger:::namespaces_set(old)} #' @seealso [log_with_separator()] log_separator <- function(level = INFO, namespace = NA_character_, @@ -120,6 +123,7 @@ log_separator <- function(level = INFO, #' @inheritParams log_separator #' @export #' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_with_separator("An important message") #' log_with_separator("Some critical KPI down!!!", separator = "$") #' log_with_separator("This message is worth a {1e3} words") @@ -140,6 +144,7 @@ log_separator <- function(level = INFO, #' logger <- layout_glue_generator(format = "{node}/{pid}/{namespace}/{fn} {time} {level}: {msg}") #' log_layout(logger) #' log_with_separator("Boo!", level = FATAL, width = 120) +#' \dontshow{logger:::namespaces_set(old)} #' @seealso [log_separator()] log_with_separator <- function(..., level = INFO, namespace = NA_character_, separator = "=", width = 80) { base_info_chars <- nchar(catch_base_log(level, namespace, .topcall = sys.call(-1))) @@ -183,7 +188,7 @@ log_with_separator <- function(..., level = INFO, namespace = NA_character_, sep #' @param level see [log_levels()] #' @param namespace x #' @export -#' @examples \dontrun{ +#' @examples #' log_tictoc("warming up") #' Sys.sleep(0.1) #' log_tictoc("running") @@ -191,7 +196,6 @@ log_with_separator <- function(..., level = INFO, namespace = NA_character_, sep #' log_tictoc("running") #' Sys.sleep(runif(1)) #' log_tictoc("and running") -#' } #' @author Thanks to Neal Fultz for the idea and original implementation! log_tictoc <- function(..., level = INFO, namespace = NA_character_) { ns <- fallback_namespace(namespace) @@ -223,10 +227,9 @@ tictocs <- new.env() #' Logs the error message to console before failing #' @param expression call #' @export -#' @examples \dontrun{ +#' @examples #' log_failure("foobar") -#' log_failure(foobar) -#' } +#' try(log_failure(foobar)) log_failure <- function(expression) { tryCatch(expression, error = function(e) { log_error(e$message) diff --git a/R/layouts.R b/R/layouts.R index dad76c80..66e4bbf3 100644 --- a/R/layouts.R +++ b/R/layouts.R @@ -78,7 +78,8 @@ get_logger_meta_variables <- function(log_level = NULL, namespace = NA_character #' that is returned when calling [log_layout()] for the currently #' used layout #' @export -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' example_layout <- layout_glue_generator( #' format = "{node}/{pid}/{ns}/{ans}/{topenv}/{fn} {time} {level}: {msg}" #' ) @@ -86,7 +87,7 @@ get_logger_meta_variables <- function(log_level = NULL, namespace = NA_character #' #' log_layout(example_layout) #' log_info("try {runif(1)}") -#' } +#' \dontshow{logger:::namespaces_set(old)} #' @seealso See example calls from [layout_glue()] and [layout_glue_colors()]. #' @family `log_layouts` layout_glue_generator <- function(format = '{level} [{format(time, "%Y-%m-%d %H:%M:%S")}] {msg}') { @@ -142,14 +143,17 @@ layout_simple <- structure(function(level, msg, namespace = NA_character_, #' @return character vector #' @export #' @family `log_layouts` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_layout(layout_logging) #' log_info(42) #' log_info(42, namespace = "everything") #' +#' \dontrun{ #' devtools::load_all(system.file("demo-packages/logger-tester-package", package = "logger")) #' logger_tester_function(INFO, 42) #' } +#' \dontshow{logger:::namespaces_set(old)} layout_logging <- structure(function(level, msg, namespace = NA_character_, .logcall = sys.call(), .topcall = sys.call(-1), .topenv = parent.frame()) { meta <- get_logger_meta_variables( @@ -217,11 +221,12 @@ layout_glue_colors <- layout_glue_generator( #' @export #' @note This functionality depends on the \pkg{jsonlite} package. #' @family `log_layouts` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_layout(layout_json()) #' log_info(42) #' log_info("ok {1:3} + {1:3} = {2*(1:3)}") -#' } +#' \dontshow{logger:::namespaces_set(old)} layout_json <- function(fields = default_fields()) { force(fields) @@ -246,14 +251,17 @@ layout_json <- function(fields = default_fields()) { #' @export #' @note This functionality depends on the \pkg{jsonlite} package. #' @family `log_layouts` -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_formatter(formatter_json) #' log_info(everything = 42) +#' #' log_layout(layout_json_parser()) #' log_info(everything = 42) +#' #' log_layout(layout_json_parser(fields = c("time", "node"))) #' log_info(cars = row.names(mtcars), species = unique(iris$Species)) -#' } +#' \dontshow{logger:::namespaces_set(old)} layout_json_parser <- function(fields = default_fields()) { force(fields) diff --git a/R/logger.R b/R/logger.R index 8925bc42..53734cc6 100644 --- a/R/logger.R +++ b/R/logger.R @@ -95,7 +95,7 @@ logger <- function(threshold, formatter, layout, appender) { #' Checks if provided namespace exists and falls back to global if not #' @param namespace string #' @return string -#' @keywords internal +#' @noRd fallback_namespace <- function(namespace) { if (!exists(namespace, envir = namespaces, inherits = FALSE)) { namespace <- "global" @@ -162,7 +162,8 @@ delete_logger_index <- function(namespace = "global", index) { #' @param index index of the logger within the namespace #' @return currently set log level threshold #' @export -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' ## check the currently set log level threshold #' log_threshold() #' @@ -178,7 +179,7 @@ delete_logger_index <- function(namespace = "global", index) { #' #' ## set the log level threshold in all namespaces to ERROR #' log_threshold(ERROR, namespace = log_namespaces()) -#' } +#' \dontshow{logger:::namespaces_set(old)} #' @family log configutation functions log_threshold <- function(level = NULL, namespace = "global", index = 1) { log_config_setter("threshold", level, namespace = namespace, index = index) @@ -192,10 +193,11 @@ log_threshold <- function(level = NULL, namespace = "global", index = 1) { #' [layout_glue_generator()], default NULL #' @inheritParams log_threshold #' @export -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_layout(layout_json()) #' log_info(42) -#' } +#' \dontshow{logger:::namespaces_set(old)} #' @family log configutation functions log_layout <- function(layout = NULL, namespace = "global", index = 1) { if (!is.null(layout) && !is.function(layout)) { @@ -227,21 +229,23 @@ log_formatter <- function(formatter = NULL, namespace = "global", index = 1) { #' [appender_tee()], default NULL #' @inheritParams log_threshold #' @export -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' ## change appender to "tee" that writes to the console and a file as well #' t <- tempfile() #' log_appender(appender_tee(t)) #' log_info(42) -#' log_info(42:44) +#' log_info(43) +#' log_info(44) #' readLines(t) #' #' ## poor man's tee by stacking loggers in the namespace #' t <- tempfile() -#' log_appender(appender_console) +#' log_appender(appender_stdout) #' log_appender(appender_file(t), index = 2) #' log_info(42) #' readLines(t) -#' } +#' \dontshow{logger:::namespaces_set(old)} #' @family log configutation functions log_appender <- function(appender = NULL, namespace = "global", index = 1) { if (!is.null(appender) && !is.function(appender)) { @@ -254,7 +258,7 @@ log_appender <- function(appender = NULL, namespace = "global", index = 1) { #' Find the logger definition(s) specified for the current namespace #' with a fallback to the global namespace #' @return list of function(s) -#' @keywords internal +#' @noRd #' @importFrom utils getFromNamespace #' @param namespace override the default / auto-picked namespace with #' a custom string @@ -294,7 +298,8 @@ log_namespaces <- function() { #' where the formatter function will be evaluated and that is used #' to look up the `namespace` as well via `logger:::top_env_name` #' @export -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_level(INFO, "hi there") #' log_info("hi there") #' @@ -308,13 +313,10 @@ log_namespaces <- function() { #' ## multiple lines #' log_info("ok {1:3} + {1:3} = {2*(1:3)}") #' -#' log_layout(layout_json()) +#' log_layout(layout_json(c("level", "msg"))) #' log_info("ok {1:3} + {1:3} = {2*(1:3)}") -#' -#' ## note for the JSON output, glue is not automatically applied -#' log_info(glue::glue("ok {1:3} + {1:3} = {2*(1:3)}")) -#' } -#' @return Invisible `list` of `logger` objects. See [logger()] for more details on the format/ +#' \dontshow{logger:::namespaces_set(old)} +#' @return Invisible `list` of `logger` objects. See [logger()] for more details on the format. log_level <- function(level, ..., namespace = NA_character_, .logcall = sys.call(), .topcall = sys.call(-1), .topenv = parent.frame()) { ## guess namespace @@ -357,7 +359,7 @@ log_level <- function(level, ..., namespace = NA_character_, #' Assure valid log level #' @param level [log_levels()] object or string representation #' @return [log_levels()] object -#' @keywords internal +#' @noRd validate_log_level <- function(level) { if (inherits(level, "loglevel")) { return(level) @@ -418,7 +420,8 @@ log_trace <- function(..., namespace = NA_character_, #' @param threshold [log_levels()] #' @inheritParams log_threshold #' @export -#' @examples \dontrun{ +#' @examples +#' \dontshow{old <- logger:::namespaces_set()} #' log_threshold(TRACE) #' log_trace("Logging everything!") #' x <- with_log_threshold( @@ -433,7 +436,7 @@ log_trace <- function(..., namespace = NA_character_, #' ) #' x #' log_trace("DONE") -#' } +#' \dontshow{logger:::namespaces_set(old)} with_log_threshold <- function(expression, threshold = ERROR, namespace = "global", index = 1) { old <- log_threshold(threshold, namespace = namespace, index = index) on.exit(log_threshold(old, namespace = namespace, index = index)) diff --git a/R/utils.R b/R/utils.R index 23faa0fc..c37be390 100644 --- a/R/utils.R +++ b/R/utils.R @@ -3,12 +3,11 @@ #' @param min_version optional minimum version needed #' @export #' @importFrom utils packageVersion compareVersion -#' @examples \dontrun{ +#' @examples #' f <- function() fail_on_missing_package("foobar") -#' f() +#' try(f()) #' g <- function() fail_on_missing_package("stats") #' g() -#' } fail_on_missing_package <- function(pkg, min_version) { pc <- sys.call(which = 1) if (!requireNamespace(pkg, quietly = TRUE)) { @@ -39,7 +38,7 @@ fail_on_missing_package <- function(pkg, min_version) { #' Returns the name of the top level environment from which the logger was called #' @return string -#' @keywords internal +#' @noRd #' @param .topenv call environment top_env_name <- function(.topenv = parent.frame()) { environmentName(topenv(.topenv)) @@ -65,11 +64,11 @@ deparse_to_one_line <- function(x) { #' Catch the log header #' @return string -#' @keywords internal #' @param level see [log_levels()] #' @param namespace string +#' @noRd #' @examples -#' \dontrun{ +#' \dontshow{old <- logger:::namespaces_set()} #' catch_base_log(INFO, NA_character_) #' logger <- layout_glue_generator(format = "{node}/{pid}/{namespace}/{fn} {time} {level}: {msg}") #' log_layout(logger) @@ -77,7 +76,7 @@ deparse_to_one_line <- function(x) { #' fun <- function() catch_base_log(INFO, NA_character_) #' fun() #' catch_base_log(INFO, NA_character_, .topcall = call("funLONG")) -#' } +#' \dontshow{logger:::namespaces_set(old)} catch_base_log <- function(level, namespace, .topcall = sys.call(-1), .topenv = parent.frame()) { namespace <- fallback_namespace(namespace) @@ -100,3 +99,7 @@ catch_base_log <- function(level, namespace, .topcall = sys.call(-1), .topenv = in_pkgdown <- function() { identical(Sys.getenv("IN_PKGDOWN"), "true") } + +is_checking_logger <- function() { + Sys.getenv("_R_CHECK_PACKAGE_NAME_", "") != "logger" +} diff --git a/R/zzz.R b/R/zzz.R index 5bfd3732..1ce86845 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -2,36 +2,45 @@ namespaces <- new.env(parent = emptyenv()) .onLoad <- function(libname, pkgname) { - namespaces_reset() + namespaces_set(namespaces_default()) } namespaces_reset <- function() { rm(list = ls(namespaces), envir = namespaces) + namespaces_set(namespaces_default()) +} + +namespaces_default <- function() { + has_glue <- requireNamespace("glue", quietly = TRUE) + needs_stdout <- in_pkgdown() || is_checking_logger() - ## default namespace's logger settings - namespaces$global <- list( - ## there can be multiple loggers for a namespace - default = list( - threshold = as.loglevel(Sys.getenv("LOGGER_LOG_LEVEL", unset = "INFO")), - layout = layout_simple, - formatter = formatter_sprintf, - appender = if (in_pkgdown()) appender_stdout else appender_console + list( + global = list( + default = list( + threshold = as.loglevel(Sys.getenv("LOGGER_LOG_LEVEL", unset = "INFO")), + layout = layout_simple, + formatter = if (has_glue) formatter_glue else formatter_sprintf, + appender = if (needs_stdout) appender_stdout else appender_console + ) + ), + .logger = list( + default = list( + threshold = ERROR, + layout = layout_simple, + formatter = formatter_sprintf, + appender = if (needs_stdout) appender_stdout else appender_console + ) ) ) +} - if (requireNamespace("glue", quietly = TRUE)) { - log_formatter(formatter_glue, namespace = "global", index = 1) - } +namespaces_set <- function(new = namespaces_default()) { + old <- as.list(namespaces) - ## internal namespace for debugging logger - namespaces$.logger <- list( - default = list( - threshold = ERROR, - layout = layout_simple, - formatter = formatter_sprintf, - appender = appender_console - ) - ) + rm(list = ls(namespaces), envir = namespaces) + list2env(new, namespaces) + + invisible(old) } .onAttach <- function(libname, pkgname) { diff --git a/man/appender_file.Rd b/man/appender_file.Rd index 04d06a8a..8b8f5780 100644 --- a/man/appender_file.Rd +++ b/man/appender_file.Rd @@ -40,7 +40,7 @@ renamed to \code{logfile.2}) until the specified \code{max_files}, then the oldest file (\code{logfile.{max_files-1}}) is deleted. } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} ## ########################################################################## ## simple example logging to a file t <- tempfile() @@ -60,6 +60,8 @@ f <- file.path(t, "log") ## define the file logger with log rotation enabled log_appender(appender_file(f, max_lines = 3, max_files = 5L)) +## enable internal logging to see what's actually happening in the logrotate steps +log_threshold(TRACE, namespace = ".logger") ## log 25 messages for (i in 1:25) log_info(i) @@ -69,10 +71,7 @@ lapply(list.files(t, full.names = TRUE), function(t) { cat(readLines(t), sep = "\n") }) -## enable internal logging to see what's actually happening in the logrotate steps -log_threshold(TRACE, namespace = ".logger") -## run the above commands again -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_appenders}: diff --git a/man/catch_base_log.Rd b/man/catch_base_log.Rd deleted file mode 100644 index b07ce97e..00000000 --- a/man/catch_base_log.Rd +++ /dev/null @@ -1,36 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{catch_base_log} -\alias{catch_base_log} -\title{Catch the log header} -\usage{ -catch_base_log( - level, - namespace, - .topcall = sys.call(-1), - .topenv = parent.frame() -) -} -\arguments{ -\item{level}{see \code{\link[=log_levels]{log_levels()}}} - -\item{namespace}{string} -} -\value{ -string -} -\description{ -Catch the log header -} -\examples{ -\dontrun{ -catch_base_log(INFO, NA_character_) -logger <- layout_glue_generator(format = "{node}/{pid}/{namespace}/{fn} {time} {level}: {msg}") -log_layout(logger) -catch_base_log(INFO, NA_character_) -fun <- function() catch_base_log(INFO, NA_character_) -fun() -catch_base_log(INFO, NA_character_, .topcall = call("funLONG")) -} -} -\keyword{internal} diff --git a/man/fail_on_missing_package.Rd b/man/fail_on_missing_package.Rd index c0299eb7..d239e1de 100644 --- a/man/fail_on_missing_package.Rd +++ b/man/fail_on_missing_package.Rd @@ -15,10 +15,8 @@ fail_on_missing_package(pkg, min_version) Check if R package can be loaded and fails loudly otherwise } \examples{ -\dontrun{ f <- function() fail_on_missing_package("foobar") -f() +try(f()) g <- function() fail_on_missing_package("stats") g() } -} diff --git a/man/fallback_namespace.Rd b/man/fallback_namespace.Rd deleted file mode 100644 index 2a76263b..00000000 --- a/man/fallback_namespace.Rd +++ /dev/null @@ -1,18 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/logger.R -\name{fallback_namespace} -\alias{fallback_namespace} -\title{Checks if provided namespace exists and falls back to global if not} -\usage{ -fallback_namespace(namespace) -} -\arguments{ -\item{namespace}{string} -} -\value{ -string -} -\description{ -Checks if provided namespace exists and falls back to global if not -} -\keyword{internal} diff --git a/man/formatter_glue_or_sprintf.Rd b/man/formatter_glue_or_sprintf.Rd index 1d6d1ac1..43af7ec7 100644 --- a/man/formatter_glue_or_sprintf.Rd +++ b/man/formatter_glue_or_sprintf.Rd @@ -44,7 +44,6 @@ Note that this function tries to be smart when passing arguments to returns an unformatted string. } \examples{ -\dontrun{ formatter_glue_or_sprintf("{a} + {b} = \%s", a = 2, b = 3, 5) formatter_glue_or_sprintf("{pi} * {2} = \%s", pi * 2) formatter_glue_or_sprintf("{pi} * {2} = {pi*2}") @@ -55,7 +54,6 @@ formatter_glue_or_sprintf("Hi {c('foo', 'bar')}, did you know that 2*4=\%s", 2 * formatter_glue_or_sprintf("Hi \%s, did you know that 2*4={2*4}", c("foo", "bar")) formatter_glue_or_sprintf("Hi \%s, did you know that 2*4=\%s", c("foo", "bar"), 2 * 4) } -} \seealso{ Other \code{log_formatters}: \code{\link{formatter_glue}()}, diff --git a/man/formatter_json.Rd b/man/formatter_json.Rd index 11e513a6..c33e6fd2 100644 --- a/man/formatter_json.Rd +++ b/man/formatter_json.Rd @@ -36,12 +36,12 @@ Transforms all passed R objects into a JSON list This functionality depends on the \pkg{jsonlite} package. } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_formatter(formatter_json) log_layout(layout_json_parser()) log_info(everything = 42) log_info(mtcars = mtcars, species = iris$Species) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_formatters}: diff --git a/man/formatter_logging.Rd b/man/formatter_logging.Rd index 52a824af..ba10c5ed 100644 --- a/man/formatter_logging.Rd +++ b/man/formatter_logging.Rd @@ -38,7 +38,7 @@ something like \code{\link[=log_eval]{log_eval()}} and logs the R expression(s) result(s) as well. } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_formatter(formatter_logging) log_info("42") log_info(42) @@ -46,7 +46,7 @@ log_info(4 + 2) log_info("foo \%s", "bar") log_info("vector \%s", 1:3) log_info(12, 1 + 1, 2 * 2) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_formatters}: diff --git a/man/formatter_pander.Rd b/man/formatter_pander.Rd index ce9571dd..91d52a37 100644 --- a/man/formatter_pander.Rd +++ b/man/formatter_pander.Rd @@ -39,7 +39,7 @@ Formats R objects with pander This functionality depends on the \pkg{pander} package. } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_formatter(formatter_pander) log_info("42") log_info(42) @@ -47,7 +47,7 @@ log_info(4 + 2) log_info(head(iris)) log_info(head(iris), style = "simple") log_info(lm(hp ~ wt, mtcars)) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_formatters}: diff --git a/man/get_logger_definitions.Rd b/man/get_logger_definitions.Rd deleted file mode 100644 index 4539fa4f..00000000 --- a/man/get_logger_definitions.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/logger.R -\name{get_logger_definitions} -\alias{get_logger_definitions} -\title{Find the logger definition(s) specified for the current namespace -with a fallback to the global namespace} -\usage{ -get_logger_definitions(namespace = NA_character_, .topenv = parent.frame()) -} -\arguments{ -\item{namespace}{override the default / auto-picked namespace with -a custom string} -} -\value{ -list of function(s) -} -\description{ -Find the logger definition(s) specified for the current namespace -with a fallback to the global namespace -} -\keyword{internal} diff --git a/man/layout_glue_generator.Rd b/man/layout_glue_generator.Rd index b1d450bf..d8cfbdf1 100644 --- a/man/layout_glue_generator.Rd +++ b/man/layout_glue_generator.Rd @@ -24,7 +24,7 @@ used layout set by \code{\link[=get_logger_meta_variables]{get_logger_meta_variables()}} } } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} example_layout <- layout_glue_generator( format = "{node}/{pid}/{ns}/{ans}/{topenv}/{fn} {time} {level}: {msg}" ) @@ -32,7 +32,7 @@ example_layout(INFO, "try {runif(1)}") log_layout(example_layout) log_info("try {runif(1)}") -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ See example calls from \code{\link[=layout_glue]{layout_glue()}} and \code{\link[=layout_glue_colors]{layout_glue_colors()}}. diff --git a/man/layout_json.Rd b/man/layout_json.Rd index b13b69ce..64d5d8da 100644 --- a/man/layout_json.Rd +++ b/man/layout_json.Rd @@ -20,11 +20,11 @@ Generate log layout function rendering JSON This functionality depends on the \pkg{jsonlite} package. } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_layout(layout_json()) log_info(42) log_info("ok {1:3} + {1:3} = {2*(1:3)}") -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_layouts}: diff --git a/man/layout_json_parser.Rd b/man/layout_json_parser.Rd index 6c67db99..950690df 100644 --- a/man/layout_json_parser.Rd +++ b/man/layout_json_parser.Rd @@ -19,14 +19,16 @@ fields with parsed list from JSON message This functionality depends on the \pkg{jsonlite} package. } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_formatter(formatter_json) log_info(everything = 42) + log_layout(layout_json_parser()) log_info(everything = 42) + log_layout(layout_json_parser(fields = c("time", "node"))) log_info(cars = row.names(mtcars), species = unique(iris$Species)) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_layouts}: diff --git a/man/layout_logging.Rd b/man/layout_logging.Rd index 1256ee79..b87ec783 100644 --- a/man/layout_logging.Rd +++ b/man/layout_logging.Rd @@ -43,14 +43,16 @@ character vector Format a log record as the logging package does by default } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_layout(layout_logging) log_info(42) log_info(42, namespace = "everything") +\dontrun{ devtools::load_all(system.file("demo-packages/logger-tester-package", package = "logger")) logger_tester_function(INFO, 42) } +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other \code{log_layouts}: diff --git a/man/log_appender.Rd b/man/log_appender.Rd index db96e589..2145c65c 100644 --- a/man/log_appender.Rd +++ b/man/log_appender.Rd @@ -19,21 +19,22 @@ destination, eg \code{\link[=appender_console]{appender_console()}}, \code{\link Get or set log record appender function } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} ## change appender to "tee" that writes to the console and a file as well t <- tempfile() log_appender(appender_tee(t)) log_info(42) -log_info(42:44) +log_info(43) +log_info(44) readLines(t) ## poor man's tee by stacking loggers in the namespace t <- tempfile() -log_appender(appender_console) +log_appender(appender_stdout) log_appender(appender_file(t), index = 2) log_info(42) readLines(t) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other log configutation functions: diff --git a/man/log_eval.Rd b/man/log_eval.Rd index bd957b7e..3a54eaa1 100644 --- a/man/log_eval.Rd +++ b/man/log_eval.Rd @@ -22,7 +22,7 @@ sections reserving line-breaks and rendering the printed results} Evaluate an expression and log results } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_eval(pi * 2, level = INFO) ## lowering the log level threshold so that we don't have to set a higher level in log_eval @@ -51,5 +51,5 @@ log_eval(f <- log_eval, multiline = TRUE) ## doing something computationally intensive log_eval(system.time(for (i in 1:100) mad(runif(1000))), multiline = TRUE) -} +\dontshow{logger:::namespaces_set(old)} } diff --git a/man/log_failure.Rd b/man/log_failure.Rd index 219583d7..a9bd1d53 100644 --- a/man/log_failure.Rd +++ b/man/log_failure.Rd @@ -13,8 +13,6 @@ log_failure(expression) Logs the error message to console before failing } \examples{ -\dontrun{ log_failure("foobar") -log_failure(foobar) -} +try(log_failure(foobar)) } diff --git a/man/log_layout.Rd b/man/log_layout.Rd index 598fa845..68ac58a9 100644 --- a/man/log_layout.Rd +++ b/man/log_layout.Rd @@ -20,10 +20,10 @@ log_layout(layout = NULL, namespace = "global", index = 1) Get or set log record layout } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_layout(layout_json()) log_info(42) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other log configutation functions: diff --git a/man/log_level.Rd b/man/log_level.Rd index 39ab7282..0df0f166 100644 --- a/man/log_level.Rd +++ b/man/log_level.Rd @@ -101,13 +101,13 @@ where the formatter function will be evaluated and that is used to look up the \code{namespace} as well via \code{logger:::top_env_name}} } \value{ -Invisible \code{list} of \code{logger} objects. See \code{\link[=logger]{logger()}} for more details on the format/ +Invisible \code{list} of \code{logger} objects. See \code{\link[=logger]{logger()}} for more details on the format. } \description{ Log a message with given log level } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_level(INFO, "hi there") log_info("hi there") @@ -121,10 +121,7 @@ log_debug("hi there") ## multiple lines log_info("ok {1:3} + {1:3} = {2*(1:3)}") -log_layout(layout_json()) +log_layout(layout_json(c("level", "msg"))) log_info("ok {1:3} + {1:3} = {2*(1:3)}") - -## note for the JSON output, glue is not automatically applied -log_info(glue::glue("ok {1:3} + {1:3} = {2*(1:3)}")) -} +\dontshow{logger:::namespaces_set(old)} } diff --git a/man/log_separator.Rd b/man/log_separator.Rd index 5ac3d682..ff174c65 100644 --- a/man/log_separator.Rd +++ b/man/log_separator.Rd @@ -43,6 +43,7 @@ to look up the \code{namespace} as well via \code{logger:::top_env_name}} Logs a long line to stand out from the console } \examples{ +\dontshow{old <- logger:::namespaces_set()} log_separator() log_separator(ERROR, separator = "!", width = 60) log_separator(ERROR, separator = "!", width = 100) @@ -51,6 +52,7 @@ log_layout(logger) log_separator(ERROR, separator = "!", width = 100) log_layout(layout_blank) log_separator(ERROR, separator = "!", width = 80) +\dontshow{logger:::namespaces_set(old)} } \seealso{ \code{\link[=log_with_separator]{log_with_separator()}} diff --git a/man/log_threshold.Rd b/man/log_threshold.Rd index 48adbd5c..47573e2b 100644 --- a/man/log_threshold.Rd +++ b/man/log_threshold.Rd @@ -20,7 +20,7 @@ currently set log level threshold Get or set log level threshold } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} ## check the currently set log level threshold log_threshold() @@ -36,7 +36,7 @@ log_warn(2) ## set the log level threshold in all namespaces to ERROR log_threshold(ERROR, namespace = log_namespaces()) -} +\dontshow{logger:::namespaces_set(old)} } \seealso{ Other log configutation functions: diff --git a/man/log_tictoc.Rd b/man/log_tictoc.Rd index 4412aa55..9048891c 100644 --- a/man/log_tictoc.Rd +++ b/man/log_tictoc.Rd @@ -17,7 +17,6 @@ log_tictoc(..., level = INFO, namespace = NA_character_) Tic-toc logging } \examples{ -\dontrun{ log_tictoc("warming up") Sys.sleep(0.1) log_tictoc("running") @@ -26,7 +25,6 @@ log_tictoc("running") Sys.sleep(runif(1)) log_tictoc("and running") } -} \author{ Thanks to Neal Fultz for the idea and original implementation! } diff --git a/man/log_with_separator.Rd b/man/log_with_separator.Rd index 5d5c603e..b0682d8f 100644 --- a/man/log_with_separator.Rd +++ b/man/log_with_separator.Rd @@ -32,6 +32,7 @@ to a common, global namespace.} Logs a message in a very visible way } \examples{ +\dontshow{old <- logger:::namespaces_set()} log_with_separator("An important message") log_with_separator("Some critical KPI down!!!", separator = "$") log_with_separator("This message is worth a {1e3} words") @@ -52,6 +53,7 @@ log_with_separator("Boo!", level = FATAL) logger <- layout_glue_generator(format = "{node}/{pid}/{namespace}/{fn} {time} {level}: {msg}") log_layout(logger) log_with_separator("Boo!", level = FATAL, width = 120) +\dontshow{logger:::namespaces_set(old)} } \seealso{ \code{\link[=log_separator]{log_separator()}} diff --git a/man/top_env_name.Rd b/man/top_env_name.Rd deleted file mode 100644 index 31f65216..00000000 --- a/man/top_env_name.Rd +++ /dev/null @@ -1,18 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{top_env_name} -\alias{top_env_name} -\title{Returns the name of the top level environment from which the logger was called} -\usage{ -top_env_name(.topenv = parent.frame()) -} -\arguments{ -\item{.topenv}{call environment} -} -\value{ -string -} -\description{ -Returns the name of the top level environment from which the logger was called -} -\keyword{internal} diff --git a/man/validate_log_level.Rd b/man/validate_log_level.Rd deleted file mode 100644 index 73b3893a..00000000 --- a/man/validate_log_level.Rd +++ /dev/null @@ -1,18 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/logger.R -\name{validate_log_level} -\alias{validate_log_level} -\title{Assure valid log level} -\usage{ -validate_log_level(level) -} -\arguments{ -\item{level}{\code{\link[=log_levels]{log_levels()}} object or string representation} -} -\value{ -\code{\link[=log_levels]{log_levels()}} object -} -\description{ -Assure valid log level -} -\keyword{internal} diff --git a/man/with_log_threshold.Rd b/man/with_log_threshold.Rd index 4bd2b597..bf4d1c31 100644 --- a/man/with_log_threshold.Rd +++ b/man/with_log_threshold.Rd @@ -24,7 +24,7 @@ with_log_threshold( Evaluate R expression with a temporarily updated log level threshold } \examples{ -\dontrun{ +\dontshow{old <- logger:::namespaces_set()} log_threshold(TRACE) log_trace("Logging everything!") x <- with_log_threshold( @@ -39,5 +39,5 @@ x <- with_log_threshold( ) x log_trace("DONE") -} +\dontshow{logger:::namespaces_set(old)} } From dc0a91be09ef38216e08484ba4f9424dd33f4d0d Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Thu, 8 Aug 2024 15:51:30 -0500 Subject: [PATCH 2/9] Try reseting example --- R/helpers.R | 3 ++- man/log_tictoc.Rd | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/R/helpers.R b/R/helpers.R index ac8ebfd3..06ce3967 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -196,6 +196,7 @@ log_with_separator <- function(..., level = INFO, namespace = NA_character_, sep #' log_tictoc("running") #' Sys.sleep(runif(1)) #' log_tictoc("and running") +#' \dontshow{rm(list = "global", envir = logger:::tictocs)} #' @author Thanks to Neal Fultz for the idea and original implementation! log_tictoc <- function(..., level = INFO, namespace = NA_character_) { ns <- fallback_namespace(namespace) @@ -221,7 +222,7 @@ log_tictoc <- function(..., level = INFO, namespace = NA_character_) { .topenv = parent.frame() ) } -tictocs <- new.env() +tictocs <- new.env(parent = emptyenv()) #' Logs the error message to console before failing diff --git a/man/log_tictoc.Rd b/man/log_tictoc.Rd index 9048891c..5a72d85b 100644 --- a/man/log_tictoc.Rd +++ b/man/log_tictoc.Rd @@ -24,6 +24,7 @@ Sys.sleep(0.1) log_tictoc("running") Sys.sleep(runif(1)) log_tictoc("and running") +\dontshow{rm(list = "global", envir = logger:::tictocs)} } \author{ Thanks to Neal Fultz for the idea and original implementation! From f4b457eb7e0d1783ee47ac9282323f645721b9c6 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sun, 18 Aug 2024 16:12:02 -0700 Subject: [PATCH 3/9] Fix doc issue --- R/logger.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/logger.R b/R/logger.R index cbbbd7a1..5a99f602 100644 --- a/R/logger.R +++ b/R/logger.R @@ -280,7 +280,8 @@ log_namespaces <- function() { #' Returns number of currently active indices -#' @inheritParams get_logger_definitions +#' @param namespace override the default / auto-picked namespace with +#' a custom string #' @return number of indices #' @export log_indices <- function(namespace = "global") { From 2d28175dcca374c523b4ad185e9f0a1c3bc00214 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sun, 18 Aug 2024 16:29:13 -0700 Subject: [PATCH 4/9] Fix (some) test failures --- R/appenders.R | 6 +----- R/helpers.R | 1 - R/utils.R | 8 ++++++++ R/zzz.R | 5 ++--- man/log_tictoc.Rd | 1 - tests/testthat/test-CRANSKIP-helpers.R | 13 ++++++++----- tests/testthat/test-appender.R | 4 ++-- 7 files changed, 21 insertions(+), 17 deletions(-) diff --git a/R/appenders.R b/R/appenders.R index 09eb1666..7fa78225 100644 --- a/R/appenders.R +++ b/R/appenders.R @@ -166,11 +166,7 @@ appender_tee <- function(file, append = TRUE, max_lines = Inf, max_bytes = Inf, force(max_files) structure( function(lines) { - if (in_pkgdown() || is_checking_logger()) { - appender_stdout(lines) - } else { - appender_console(lines) - } + if (needs_stdout()) appender_stdout(lines) else appender_console(lines) appender_file(file, append, max_lines, max_bytes, max_files)(lines) }, generator = deparse(match.call()) diff --git a/R/helpers.R b/R/helpers.R index 06ce3967..e0b387c6 100644 --- a/R/helpers.R +++ b/R/helpers.R @@ -196,7 +196,6 @@ log_with_separator <- function(..., level = INFO, namespace = NA_character_, sep #' log_tictoc("running") #' Sys.sleep(runif(1)) #' log_tictoc("and running") -#' \dontshow{rm(list = "global", envir = logger:::tictocs)} #' @author Thanks to Neal Fultz for the idea and original implementation! log_tictoc <- function(..., level = INFO, namespace = NA_character_) { ns <- fallback_namespace(namespace) diff --git a/R/utils.R b/R/utils.R index c37be390..9a9d9ad6 100644 --- a/R/utils.R +++ b/R/utils.R @@ -103,3 +103,11 @@ in_pkgdown <- function() { is_checking_logger <- function() { Sys.getenv("_R_CHECK_PACKAGE_NAME_", "") != "logger" } + +needs_stdout <- function() { + in_pkgdown() || is_checking_logger() +} + + +# allow mocking +Sys.time <- NULL diff --git a/R/zzz.R b/R/zzz.R index 1ce86845..d027a4df 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -12,7 +12,6 @@ namespaces_reset <- function() { namespaces_default <- function() { has_glue <- requireNamespace("glue", quietly = TRUE) - needs_stdout <- in_pkgdown() || is_checking_logger() list( global = list( @@ -20,7 +19,7 @@ namespaces_default <- function() { threshold = as.loglevel(Sys.getenv("LOGGER_LOG_LEVEL", unset = "INFO")), layout = layout_simple, formatter = if (has_glue) formatter_glue else formatter_sprintf, - appender = if (needs_stdout) appender_stdout else appender_console + appender = if (needs_stdout()) appender_stdout else appender_console ) ), .logger = list( @@ -28,7 +27,7 @@ namespaces_default <- function() { threshold = ERROR, layout = layout_simple, formatter = formatter_sprintf, - appender = if (needs_stdout) appender_stdout else appender_console + appender = if (needs_stdout()) appender_stdout else appender_console ) ) ) diff --git a/man/log_tictoc.Rd b/man/log_tictoc.Rd index 5a72d85b..9048891c 100644 --- a/man/log_tictoc.Rd +++ b/man/log_tictoc.Rd @@ -24,7 +24,6 @@ Sys.sleep(0.1) log_tictoc("running") Sys.sleep(runif(1)) log_tictoc("and running") -\dontshow{rm(list = "global", envir = logger:::tictocs)} } \author{ Thanks to Neal Fultz for the idea and original implementation! diff --git a/tests/testthat/test-CRANSKIP-helpers.R b/tests/testthat/test-CRANSKIP-helpers.R index 6eb0a9ea..fa8557ca 100644 --- a/tests/testthat/test-CRANSKIP-helpers.R +++ b/tests/testthat/test-CRANSKIP-helpers.R @@ -1,9 +1,12 @@ test_that("tictoc", { - expect_match(capture.output(log_tictoc(), type = "message"), "timer tic 0 secs") - ## let time pass a bit - Sys.sleep(0.01) - expect_match(capture.output(log_tictoc(), type = "message"), "timer toc") - capture.output(expect_silent(log_tictoc()), type = "message") + local_test_logger() + local_mocked_bindings(Sys.time = function() as.POSIXct("2024-01-01 00:00:00")) + + expect_output(log_tictoc(), "timer tic 0 secs") + ## simulate time passing + local_mocked_bindings(Sys.time = function() as.POSIXct("2024-01-01 00:01:00")) + expect_output(log_tictoc(), "timer toc 1 mins") + expect_output(log_tictoc(), "timer tic 0 secs") }) test_that("log with separator", { diff --git a/tests/testthat/test-appender.R b/tests/testthat/test-appender.R index 99a3730c..cded456d 100644 --- a/tests/testthat/test-appender.R +++ b/tests/testthat/test-appender.R @@ -37,8 +37,8 @@ test_that("append to file + print to console", { layout = layout_glue_generator("{level} {msg}"), ) - expect_equal(capture.output(log_info("foobar"), type = "message"), "INFO foobar") - capture.output(log_info("{1:2}"), type = "message") + expect_output(log_info("foobar"), "INFO foobar") + capture.output(log_info("{1:2}")) expect_equal(length(readLines(t)), 3) expect_equal(readLines(t)[1], "INFO foobar") }) From 18135f235e5a100490dc42e2aa847197d93d493a Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sun, 18 Aug 2024 16:34:26 -0700 Subject: [PATCH 5/9] Doh --- R/utils.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/utils.R b/R/utils.R index 9a9d9ad6..1867ee31 100644 --- a/R/utils.R +++ b/R/utils.R @@ -101,13 +101,12 @@ in_pkgdown <- function() { } is_checking_logger <- function() { - Sys.getenv("_R_CHECK_PACKAGE_NAME_", "") != "logger" + Sys.getenv("_R_CHECK_PACKAGE_NAME_", "") == "logger" } needs_stdout <- function() { in_pkgdown() || is_checking_logger() } - # allow mocking Sys.time <- NULL From 71f114b871661861dab642ca9a1a4f65b028b4b0 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sun, 18 Aug 2024 16:58:00 -0700 Subject: [PATCH 6/9] Don't lint mocking helper --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index 1867ee31..59674341 100644 --- a/R/utils.R +++ b/R/utils.R @@ -109,4 +109,4 @@ needs_stdout <- function() { } # allow mocking -Sys.time <- NULL +Sys.time <- NULL # nolint From 21ff96c3090d5ec6b28835e2fa40b6fcb8675e58 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sun, 18 Aug 2024 16:58:45 -0700 Subject: [PATCH 7/9] Also use stdout when testing --- R/utils.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index 59674341..b6f95647 100644 --- a/R/utils.R +++ b/R/utils.R @@ -100,12 +100,16 @@ in_pkgdown <- function() { identical(Sys.getenv("IN_PKGDOWN"), "true") } +is_testing <- function() { + identical(Sys.getenv("TESTTHAT"), "true") +} + is_checking_logger <- function() { Sys.getenv("_R_CHECK_PACKAGE_NAME_", "") == "logger" } needs_stdout <- function() { - in_pkgdown() || is_checking_logger() + in_pkgdown() || is_testing() || is_checking_logger() } # allow mocking From 6d2e0b05d07d39f1ca133e8e96358ec0ddc8e9af Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Sun, 18 Aug 2024 17:04:58 -0700 Subject: [PATCH 8/9] Try a simpler approach --- vignettes/migration.Rmd | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/vignettes/migration.Rmd b/vignettes/migration.Rmd index 325c04c9..54caca4e 100644 --- a/vignettes/migration.Rmd +++ b/vignettes/migration.Rmd @@ -243,13 +243,8 @@ str(as.list(loglevels))
logger ```{r} -levels <- mget( - ls( - envir = environment(logger), pattern = "^[A-Z]" - ), - envir = environment(logger) -) -str(levels[order(-as.numeric(levels))], give.attr = FALSE) +levels <- mget(rev(logger:::log_levels_supported), envir = asNamespace("logger")) +str(levels, give.attr = FALSE) ```
From 878ffc2cbf77599812a3dcebce18b06c1100582c Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 27 Aug 2024 16:46:11 -0500 Subject: [PATCH 9/9] Update example --- R/logger.R | 3 ++- man/log_level.Rd | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/R/logger.R b/R/logger.R index 5a99f602..c76de447 100644 --- a/R/logger.R +++ b/R/logger.R @@ -323,7 +323,8 @@ log_indices <- function(namespace = "global") { #' ## multiple lines #' log_info("ok {1:3} + {1:3} = {2*(1:3)}") #' -#' log_layout(layout_json(c("level", "msg"))) +#' ## use json layout +#' log_layout(layout_json(c("time", "level"))) #' log_info("ok {1:3} + {1:3} = {2*(1:3)}") #' \dontshow{logger:::namespaces_set(old)} #' @return Invisible `list` of `logger` objects. See [logger()] for more details on the format. diff --git a/man/log_level.Rd b/man/log_level.Rd index 0df0f166..2f557672 100644 --- a/man/log_level.Rd +++ b/man/log_level.Rd @@ -121,7 +121,8 @@ log_debug("hi there") ## multiple lines log_info("ok {1:3} + {1:3} = {2*(1:3)}") -log_layout(layout_json(c("level", "msg"))) +## use json layout +log_layout(layout_json(c("time", "level"))) log_info("ok {1:3} + {1:3} = {2*(1:3)}") \dontshow{logger:::namespaces_set(old)} }