Coder Social home page Coder Social logo

debugme's Introduction

debugme

Debug R Packages

R-CMD-check CRAN RStudio mirror downloads Codecov test coverage

Specify debug messages as special string constants, and control debugging of packages via environment variables. This package was largely influenced by the debug npm package.

Installation and Usage

Stable version:

install.packages("debugme")

To install the development version:

pak::pak("r-lib/debugme")

To use debugme in your package, import it, and then add the following .onLoad function to your package:

.onLoad <- function(libname, pkgname) {
  debugme::debugme()
}

You can now add debug messages via character literals. No function calls are necessary. For example:

"!DEBUG Start up phantomjs"
private$start_phantomjs(phantom_debug_level)

"!DEBUG Start up shiny"
private$start_shiny(path)

"!DEBUG create new phantomjs session"
private$web <- session$new(port = private$phantom_port)

"!DEBUG navigate to Shiny app"
private$web$go(private$get_shiny_url())

The string literals are simply ignored when debugging is turned off. To turn on debugging for a package, set the environment variable DEBUGME to the package name you want to debug. E.g. from a bash shell:

export DEBUGME=mypackage

Or from within R:

Sys.setenv(DEBUGME = "mypackage")

Separate multiple package names with commas:

export DEBUGME=mypackage,otherpackage

The debug messages will be prefixed by the package names, and assuming your terminal supports color, will be colored differently for each package.

Example

Dynamic code

The debugme debug strings may contain R code between backticks. This code is evaluated at runtime, if debugging is turned on. A single debug string may contain multiple backticked code chunks:

"!DEBUG x = `x`, y = `y`"
if (x != y) {
...

Motivation

I have always wanted a debugging tool that

  • is very simple to use,
  • can be controlled via environment variables, without changing anything it the packages themselves,
  • has zero impact on performance when debugging is off.

debugme is such a tool.

Performance

Function calls are relatively cheap in R, but they still do have an impact. If you never want to worry about the log messages making your code slower, you will like debugme. debugme debug strings have practically no performance penalty when debugging is off.

Here is a simple comparison to evaluate debugging overhead with a function call, f1(), debugging with debug strings, f2(), and no debugging at all.

debug <- function(msg) { }
f1 <- function() {
  for (i in 1:100) {
    debug("foobar")
    # Avoid optimizing away the loop
    i <- i + 1
  }
}
f2 <- function() {
  for (i in 1:100) {
    "!DEBUG foobar"
    # Avoid optimizing away the loop
    i <- i + 1
  }
}
f3 <- function() {
  for (i in 1:100) {
    # Avoid optimizing away the loop
    i <- i + 1
  }
}
microbenchmark::microbenchmark(f1(), f2(), f3())
#> Warning in microbenchmark::microbenchmark(f1(), f2(), f3()): less accurate
#> nanosecond times to avoid potential integer overflows
#> Unit: microseconds
#>  expr    min     lq      mean median     uq      max neval cld
#>  f1() 10.332 10.496 103.29499 10.578 10.701 9277.398   100   a
#>  f2()  1.394  1.435   8.29676  1.435  1.435  687.406   100   a
#>  f3()  1.107  1.189   7.86011  1.189  1.189  667.767   100   a

License

MIT © Gábor Csárdi

debugme's People

Contributors

gaborcsardi avatar kforner avatar krlmlr avatar mhenderson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

debugme's Issues

Upkeep for debugme (2023)

Pre-history

  • usethis::use_readme_rmd()
  • usethis::use_roxygen_md()
  • usethis::use_github_links()
  • usethis::use_pkgdown_github_pages()
  • usethis::use_tidy_github_labels()
  • usethis::use_tidy_style()
  • urlchecker::url_check()

2020

  • usethis::use_package_doc()
  • usethis::use_testthat(3)
  • Align the names of R/ files and test/ files

2021

  • Remove check environments section from cran-comments.md
  • Use lifecycle instead of artisanal deprecation messages

2022

  • Handle and close any still-open master --> main issues
  • usethis:::use_codecov_badge("r-lib/debugme")
  • Update pkgdown site using instructions at https://tidytemplate.tidyverse.org
  • Update lifecycle badges with more accessible SVGs: usethis::use_lifecycle()

2023

  • Update copyright holder in DESCRIPTION: person("Posit Software, PBC", role = c("cph", "fnd"))
  • Run devtools::document() to re-generate package-level help topic with DESCRIPTION changes
  • usethis::use_tidy_logo()
  • usethis::use_tidy_coc()
  • Use pak::pak("r-lib/debugme") in README
  • Consider running usethis::use_tidy_dependencies() and/or replace compat files with use_standalone()
  • #53
  • #54
    or file an issue if you don't have time to do it now
  • #55

Eternal

  • usethis::use_mit_license()
  • usethis::use_package("R", "Depends", "3.6")
  • usethis::use_tidy_description()
  • usethis::use_tidy_github_actions()
  • devtools::build_readme()
  • Re-publish released site if needed

Created on 2023-11-03 with usethis::use_tidy_upkeep_issue(), using usethis v2.2.2.9000

debug levels?

Without straying into making debugme into a fullfledged logger, do you have thoughts on allowing at least one additional level like MESSAGE?

Allow tags

In general re-think the annotation, debug levels, etc.

use a filter to select debugging by level like Smart::Comment do

Hi Gabor,

I have just discovered your package and I am already a big fan !
Do you know the Smart::Comment perl package ?
It uses the same kind of approach, using comments instead of string litterals (which you can not since R discards them in parsed code).

You set the level of the debugging by the number of '#', eg.
### is a level 1 debug
#### is a level2 debug
and you can select the debugging level at execution time using the Smart_Comment env var, e.g.
Smart_Comment=###:#### ./my_script.pl
which I think is nice since when you want to debug a script, you do not a priori know which packages it uses (can be indirect), so selecting the package via DEBUGME might not be the most convenient approach.

Maybe the syntax could be expanded like this:
DEBUGME=mypkg : turns on debugging for mypkg
DEBUGME=mypkg:1 turns on debugging level 1 for mypkg
DEBUGME=mypkg1:1,mypkg2:3
DEBUGME=1 turns on debugging level 1 for all packages

What do you think ?

Karl

Plans for V2

  • Use comments, if possible. Comments look nicer, and they really have zero overhead. (It might not be possible, as it probably requires re-parsing the code, especially if CRAN will include the source refs without the parse data.)
  • Assertions #32
  • Re-think debug levels
  • Tagging
  • Turn debugging on-off using:
    • Package names
    • Debug levels
    • Tags
    • Function names
    • File names
    • Etc ???
  • C/C++ support
  • Formatters, defaulting to glue
  • JSON (?) logging, basically some way to log composite objects that can be inspected
  • Logging to a pipe or fifo, to be able to inspect, browse while the logging is active
  • Interactive log browser, an HTML widget would be nice.
  • Handle repeated log messages better
  • Ability to stop in a browser(), if the debug message is active. We probably just need to
    make sure that something like
    ## !DEBUG { if (cond) browser() } blah
    
    works

error with functions without arguments

Hi,

I believe I stumbled on a bug with 0-args functions.
Here's a reproducible example:

library(debugme)
debugme:::initialize_colors('dummy')
env <- new.env()
assign('noarg', function() 'noarg', env)
debugme(env, 'dummy')
# Error in as.function.default(x, envir) : list argument expected

traceback()
# 9: as.function.default(c(value, if (is.null(bd) || is.list(bd)) list(bd) else bd), 
#        envir)
# 8: as.function(c(value, if (is.null(bd) || is.list(bd)) list(bd) else bd), 
#        envir)
# 7: `formals<-`(`*tmp*`, value = NULL)
# 6: instrument(get(x, envir = env))
# 5: assign(x, instrument(get(x, envir = env)), envir = env)
# 4: (function (x) 
#    assign(x, instrument(get(x, envir = env)), envir = env))(dots[[1L]][[1L]])
# 3: mapply(FUN = f, ..., SIMPLIFY = FALSE)
# 2: Map(function(x) assign(x, instrument(get(x, envir = env)), envir = env), 
#        funcs)
# 1: debugme(env, "dummy")

From my understanding, it comes from here:
https://github.com/gaborcsardi/debugme/blob/master/R/instrument.R#L12

Because the formals are NULL, but formals<- does not seem to accept a NULL value for the new formals.
I don't understand how I did not see this behavior before, maybe the .onLoad() hook is run in a try() ?

By the way, looking at the code: https://github.com/gaborcsardi/debugme/blob/master/R/instrument.R#L1 , I have the feeling that the pkg arg is never used...

WISH: Near-zero overhead assertions

(continuation of my Tweet https://twitter.com/henrikbengtsson/status/984323561656483841)

Analogously to how you can produce debug messages using:

    "!DEBUG Hello world: x = `x`"

I'd like to run assertion statements that have near-zero overhead, e.g.

    "!ASSERT 'x' is integer `stopifnot(is.integer(x))`"

This will allow package developers to add lots of internal assertions validating not only the contract of returned values, but also intermediate values.

The above could be achieved by

    "!DEBUG `stopifnot(is.integer(x))`"

but the downside is that this will also trigger lots of DEBUG-produced output if such exists. Not only may such output clutter troubleshooting but it may also have side effects conflicting with any troubleshooting efforts, e.g. in a DEBUG statement may touch a promise (think "delayed assignment") causing different results than when disabled.

Any assert framework should be supported, so it should not be hard coded to stopifnot() [which comes with even more overhead in R (>= 3.5.0)], assertthat, checkmate, ...

Document integration with plogr

  • Make sure that enabling/disabling of {plogr} is consistent with the {debugme} strategy
  • Make {plogr} use the same output routine
  • Show a worked example
  • Document

debugme, package support and datasets

First, thanks for putting this package together it is nice having the ability to have debug statements in a package with almost no cost. I recently started adding debugme to a package that I am putting together and noticed some issues with package datasets. The issue is that after adding debugme to the package and activating it, that the type of my datasets will change from data.frame to list.

I recreated the problem in a minimal package using the example package in Rstudio and debugme (1.1.0 from rcran or master from github) on R 3.5.0 and 3.5.1 as follows:

Data creation:
testdata <- data.frame(x=17, y=42)
usethis::use_data(testdata)

.onLoad:
.onLoad <- function(libname, pkgname) {
debugme::debugme()
}

Then after loading the package the (called test) the type of testdata will have changed from a data.frame to a list. If helpful, I can provide the complete test package code that reproduces the error.

I did a little bit of digging and it looks like the error relates to the object set selected for inspection. Specifically, this line in debugme::debugme:
objects <- ls(env, all.names = TRUE)

In my test package, I see this:

objects
".NAMESPACE." ".S3MethodsTable." ".onLoad" ".packageName" "hello"

At the start of the debugme::debugme function I have:

class(test::testdata)
[1] "data.frame"
After calling instrument on namespace (objects[1])
assign(objects[1], debugme:::instrument(get(objects[1], envir=env), pkg), envir=env)
The type changes from data.frame to list
class(test::testdata)
[1] "list"

It looks like the instrumentation of .NAMESPACE. results in a change in the dataset in the package. If I replace the all.names = T to all.names = F in ls:
objects <- ls(env, all.names = F)

Then, my dataset works fine after loading as the ls now excludes patterns starting with dot.

This makes me wonder what the rationale for having all.names = T is? I am wondering if it is to ensure instrumentation of .onLoad and friends or if I am missing something?

Problem configuring debugme for plumber application

I want to use DEBUG for a plumber application. You can find it here: https://github.com/nuest/o2r-inspecter/tree/debugme-issue-report

I would like to configure the debugging using the package name inspecter, but there might be an issue with the environments or with the way my package is set up.

To find out more I added logs of the default values used in debug::debugme() at three times:

This is what I get (without a DEBUGME environment variable set):

R version 3.4.3 (2017-11-30) -- "Kite-Eating Tree"
[...]

> library("inspecter", verbose = TRUE)
onLoad: libname: /home/daniel/R/x86_64-pc-linux-gnu-library/3.4 environment: base 
<environment: namespace:base>

Attaching package: ‘inspecter’

The following object is masked from ‘package:stats’:

    start

> inspecter::start()
start: pkg: R_GlobalEnv 
<environment: R_GlobalEnv>
Starting server to listen on port 8091
Running the swagger UI at http://127.0.0.1:8091/__swagger__/

Enabling debugging for all environments does the trick for now:

> Sys.setenv(DEBUGME = "R_GlobalEnv,base,inspecter")
> library("inspecter", verbose = TRUE)
onLoad: libname: /home/daniel/R/x86_64-pc-linux-gnu-library/3.4 environment: base 
<environment: namespace:base>

Attaching package: ‘inspecter’

The following object is masked from ‘package:stats’:

    start

> inspecter::start()
start: pkg: R_GlobalEnv 
<environment: R_GlobalEnv>
inspecter starting inspecter +24095ms 
inspecter initialize plumber with route definitions from /home/daniel/R/x86_64-pc-linux-gnu-library/3.4/inspecter/api.R +1ms 
inspecter run plumber +22ms 
Starting server to listen on port 8091
Running the swagger UI at http://127.0.0.1:8091/__swagger__/
inspecter +-2017-12-15 11:23:52 | GET /status | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/63.0.3239.84 Chrome/63.0.3239.84 Safari/537.36  from  127.0.0.1 +8336ms 
inspecter +-2017-12-15 11:23:52 | GET /status | response sent: 200 | size: 344 B +22ms

Any help or ideas appreciated, if this setup is too complex for you to evaluate I can try to work out a minimal reprex.

Dynamic messages

With sg like

"!DEBUG reading file `filename`"
"!INFO  reading files `paste(filenames, collapse = ", ")`"

I.e. all back-ticked chunks are simply converted to code, and their return value is put in the string.

Make it easier to go into "debug mode"

What would it take to make it easier to turn debugging messages on (and off) during development?

I think just a helper function would be nice versus manually setting an env var. Maybe it could default to the current package?

Then there's also the issue of turning it on, then needing to reload the package. That sounds a bit harder to smooth over, but maybe also possible? I somehow thought I needed to install/restart/reload, but load_all() works, so nevermind.

debugme modifies data.frame to list inside R6 class field

enabling debugme through R environment variable (and building the package again), modifies data.frames in R6 class fields from data.frames to lists.

zzz.R

.onLoad <- function(libname, pkgname) {
  debugme::debugme()
}

testClass.R

library(R6)
testClass <- R6Class(
  classname = "testClass",
  public = list(
    initialize = function() {
      print(class(private$df))
      print(private$df)
    },
    df2 = data.frame(
      ID = c(0,1,2,3),
      name = c("a","b","c","d"),
      bool = c(T,F,F,F),
      stringsAsFactors = F
    )
  ),
  private = list(
    df = data.frame(
      ID = c(0,1,2,3),
      name = c("a","b","c","d"),
      bool = c(T,F,F,F),
      stringsAsFactors = F
    )
  )
)

output

> library(testpackage)
> testClass
<testClass> object generator
  Public:
    df2: data.frame
    initialize: function () 
    clone: function (deep = FALSE) 
  Private:
    df: data.frame
  Parent env: <environment: namespace:testpackage>
  Locked objects: TRUE
  Locked class: FALSE
  Portable: TRUE
> Sys.getenv("DEBUGME")
[1] ""
> Sys.setenv("DEBUGME" = "testpackage")

Restarting R session...

> library(testpackage)
> Sys.getenv("DEBUGME")
[1] "testpackage"
> testClass
<testClass> object generator
  Public:
    df2: list
    initialize: function () 
    clone: function (deep = FALSE) 
  Private:
    df: list
  Parent env: <environment: namespace:testpackage>
  Locked objects: TRUE
  Locked class: FALSE
  Portable: TRUE

session info

─ Session info ────────────────────────────────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 3.6.0 (2019-04-26)
 os       Ubuntu 18.04.4 LTS          
 system   x86_64, linux-gnu           
 ui       RStudio                     
 language (EN)                        
 collate  C.UTF-8                     
 ctype    C.UTF-8                     
 tz       Etc/UTC                     
 date     2020-02-13                  

─ Packages ────────────────────────────────────────────────────────────────────────────────────────────
 ! package     * version date       lib source        
   assertthat    0.2.1   2019-03-21 [1] CRAN (R 3.6.0)
   cli           2.0.1   2020-01-08 [1] CRAN (R 3.6.0)
   crayon        1.3.4   2017-09-16 [1] CRAN (R 3.6.0)
   debugme       1.1.0   2017-10-22 [1] CRAN (R 3.6.0)
   fansi         0.4.1   2020-01-08 [1] CRAN (R 3.6.0)
   glue          1.3.1   2019-03-12 [1] CRAN (R 3.6.0)
 P packrat       0.5.0   2018-11-14 [?] CRAN (R 3.6.0)
   R6            2.4.1   2019-11-12 [1] CRAN (R 3.6.0)
   sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 3.6.0)
   testpackage * 0.1.0   2020-02-13 [1] local         
   withr         2.1.2   2018-03-15 [1] CRAN (R 3.6.0)

Support going to the code

We could add ids to the debug messages somehow, and then jump to their place in the code quickly, either just showing the code on the screen like tracer, or jumping there in RStudio.

Custom formatters

Could be implemented with an argument to debugme(), like debugme::debugme(formatter = debugme:::handle_dynamic_code(.)) . Perhaps even with the default formatter = ..

Comparison to futile.logger

Looking forward to where this packages goes! I really like the colored output and the configuration via environment variables (reminds me of npm's debug).

I have no opinion yet on the non-R statements for writing logs... got to try it out.

Besides from these three points, are there any other features that set this apart from futile.logger (also on GitHub)? Just thinking that if I log for logging packages for R, I only know about these two and new users who have to decide could be helped with some info.

Let instrument recurse into environments

Currently the package only instruments functions which are defined at top level of a package namespace. But sometimes additional functions are stored inside environments which then do not get instrumented. This is also the case for R6 classes which are stored as environment in the namespace.

FR: Show file and line with each debug message

Is this information available during instrumentation?

Colored gray, between package name and message. Ideally should be aligned so that the messages still start in the same column for each package.

package R/file.R:123      Message
package R/other-file.R:45 Other message

Release debugme 1.2.0

Prepare for release:

  • git pull
  • Check current CRAN check results
  • Bump required R version in DESCRIPTION to 4.0
  • Polish NEWS
  • usethis::use_github_links()
  • urlchecker::url_check()
  • devtools::build_readme()
  • devtools::check(remote = TRUE, manual = TRUE)
  • devtools::check_win_devel()
  • revdepcheck::revdep_check(num_workers = 8)
  • Update cran-comments.md
  • git push
  • Draft blog post
  • Slack link to draft blog in #open-source-comms

Submit to CRAN:

  • usethis::use_version('minor')
  • devtools::submit_cran()
  • Approve email

Wait for CRAN...

  • Accepted 🎉
  • Finish & publish blog post
  • Add link to blog post in pkgdown news menu
  • usethis::use_github_release()
  • usethis::use_dev_version(push = TRUE)
  • Tweet

Move `master` branch to `main`

The master branch of this repository will soon be renamed to main, as part of a coordinated change across several GitHub organizations (including, but not limited to: tidyverse, r-lib, tidymodels, and sol-eng). We anticipate this will happen by the end of September 2021.

That will be preceded by a release of the usethis package, which will gain some functionality around detecting and adapting to a renamed default branch. There will also be a blog post at the time of this master --> main change.

The purpose of this issue is to:

  • Help us firm up the list of targetted repositories
  • Make sure all maintainers are aware of what's coming
  • Give us an issue to close when the job is done
  • Give us a place to put advice for collaborators re: how to adapt

message id: euphoric_snowdog

Auto-debug packages

Even if they don't explicitly support debugme. Just add traces to both at the beginning and end of functions. Could be a little too much, though.

Suppress time stamp diff for a specific call

Really enjoy using your package, so here's another feature request:

Allow disabling/suppressing the time diff after each line per debug statement.

For more extensive debug cases I like to print the environment variables:

"!!!DEBUG Full environment:\n`capture.output(print(base::Sys.getenv()))`"

Which gives the output (excerpt):

mypackage Full environment:
CLICOLOR_FORCE                            1 +13ms mypackage Full environment:
CLUTTER_IM_MODULE                         xim +13ms mypackage Full environment:
COMPIZ_BIN_PATH                           /usr/bin/ +13ms mypackage Full environment:
COMPIZ_CONFIG_PROFILE                     ubuntu +13ms mypackage Full environment:
DBUS_SESSION_BUS_ADDRESS                  unix:abstract=/tmp/dbus-VNMWlDe8Oz +13ms mypackage Full environment:
DEBUGME                                   inspecter +13ms mypackage Full environment:
DEFAULTS_PATH                             /usr/share/gconf/ubuntu.default.path +13ms mypackage Full environment:
DESKTOP_SESSION                           ubuntu +13ms mypackage Full environment:
DISPLAY                                   :0 +13ms mypackage Full environment:

AFAICS there is no way to print a multi-line statement from within a DEBUG statement, and this might be out of scope? Maybe there is a solution I don't see to have line breaks in the output created by debug statements...

Some ideas:

a) defining some syntax to allow multiline output: "!!!DEBUG NOBREAK message..."
b) exposing a function to users for checking if logging is enabled, so I can check before I make a potentially costly call: debugme::isEnabled(level = 1)

Draw call tree

I.e. indent the output, and also draw a tree at the beginning of the line.

still calculating unused debugs?

Q: when a "!DEBUG ..." message does not meet the !-threshold, why is its `expression` still evaluated?

.onLoad <- function(libname, pkgname) {
  if (requireNamespace("debugme", quietly = TRUE)) {
    # https://github.com/r-lib/debugme/issues/26#issuecomment-773615879
    get(".onLoad", asNamespace("debugme"))(libname, pkgname)
    debugme::debugme()
  }
}

#' @export
testme <- function(...) {
  msg <- "!DEBUG This is a test of debug level `0+1`"
  message(msg)
  msg <- "!!DEBUG This is a test of debug level `0+2`"
  message(msg)
  TRUE
}

Sys.setenv(DEBUGME="!mypackage")
devtools::document()
testme()
# mypackage This is a test of debug level 1 +5872ms 
# This is a test of debug level 1
# !!DEBUG This is a test of debug level 2
# [1] TRUE

I expected the first expression `0+1` to be evaluated, since it should be displayed. But I expected the second msg with `0+2` to instead message the raw string. This is the output I expected:

testme()
# mypackage This is a test of debug level 1 +5872ms 
# This is a test of debug level 1
# !!DEBUG This is a test of debug level `0+2`
# [1] TRUE

(I'm not suggesting that every use of "!DEBUG" will have a corresponding message or such (by definition of this package).)

sessionInfo()
> sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19042)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252 
[2] LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_4.0.3

debugme sets .Random.seed on load

I just transferred this from pillar, which is how it came into my life. But once I dug around, it became clear debugme was touching .Random.seed upon load. That explains why I talk about pillar a lot.

I picked this up because of some tests in reprex re: environment hygiene.

Something new in pillar touches the random seed, presumably something in .onLoad().

Once you figure out what it is, hopefully you can make it not so or put it inside withr::with_preserve_seed(). I don't see an obvious culprit, so is it debugme?

jenny@2020-mbp reprex $ R --vanilla

R version 4.0.2 (2020-06-22) -- "Taking Off Again"
(blah blah blah)

> ls(all.names = TRUE)
character(0)

> loadNamespace("pillar")
<environment: namespace:pillar>

> ls(all.names = TRUE)
[1] ".Random.seed"

Enable time stamp mode manually for terminal output

It would be great to have full timestamps in addition to/replacing the diff ones on the terminal, as an option. I want to use debugme for logging a web application, and seeing when something happened should help identify issues.

What do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.