GithubHelp home page GithubHelp logo

daroczig / logger Goto Github PK

View Code? Open in Web Editor NEW
247.0 6.0 38.0 2.05 MB

A lightweight, modern and flexible, log4j and futile.logger inspired logging utility for R

Home Page: https://daroczig.github.io/logger

R 100.00%

logger's Introduction

logger

Project Status: Active – The project has reached a stable, usable state and is being actively developed. CRAN Build Status Code Coverage A Mikata Project

A lightweight, modern and flexibly logging utility for R -- heavily inspired by the futile.logger R package and logging Python module.

Installation

CRAN version

install.packages('logger')

The most recent, development version of logger can also be installed from GitHub:

remotes::install_github('daroczig/logger')

Quick example

Setting the log level threshold to something low and logging various messages in ad-hoc and programmatic ways:

library(logger)
log_threshold(DEBUG)
log_info('Script starting up...')
#> INFO [2018-20-11 22:49:36] Script starting up...

pkgs <- available.packages()
log_info('There are {nrow(pkgs)} R packages hosted on CRAN!')
#> INFO [2018-20-11 22:49:37] There are 13433 R packages hosted on CRAN!

for (letter in letters) {
    lpkgs <- sum(grepl(letter, pkgs[, 'Package'], ignore.case = TRUE))
    log_level(if (lpkgs < 5000) TRACE else DEBUG,
              '{lpkgs} R packages including the {shQuote(letter)} letter')
}
#> DEBUG [2018-20-11 22:49:38] 6300 R packages including the 'a' letter
#> DEBUG [2018-20-11 22:49:38] 6772 R packages including the 'e' letter
#> DEBUG [2018-20-11 22:49:38] 5412 R packages including the 'i' letter
#> DEBUG [2018-20-11 22:49:38] 7014 R packages including the 'r' letter
#> DEBUG [2018-20-11 22:49:38] 6402 R packages including the 's' letter
#> DEBUG [2018-20-11 22:49:38] 5864 R packages including the 't' letter

log_warn('There might be many, like {1:2} or more warnings!!!')
#> WARN [2018-20-11 22:49:39] There might be many, like 1 or more warnings!!!
#> WARN [2018-20-11 22:49:39] There might be many, like 2 or more warnings!!!

Setting a custom log layout to render the log records with colors:

library(logger)
log_layout(layout_glue_colors)
log_threshold(TRACE)
log_info('Starting the script...')
log_debug('This is the second log line')
log_trace('Note that the 2nd line is being placed right after the 1st one.')
log_success('Doing pretty well so far!')
log_warn('But beware, as some errors might come :/')
log_error('This is a problem')
log_debug('Note that getting an error is usually bad')
log_error('This is another problem')
log_fatal('The last problem')

Or simply run the related demo:

demo(colors, package = 'logger', echo = FALSE)

colored log output

But you could set up any custom colors and layout, eg using custom colors only for the log levels, make it grayscale, include the calling function or R package namespace with specific colors etc. For more details, see the related vignettes.

Why yet another logging R package?

Although there are multiple pretty good options already hosted on CRAN when it comes to logging in R, such as

  • futile.logger: probably the most popular log4j variant (and I'm a big fan)
  • logging: just like Python's logging package
  • loggit: capture message, warning and stop function messages in a JSON file
  • log4r: log4j-based, object-oriented logger
  • rsyslog: logging to syslog on 'POSIX'-compatible operating systems
  • lumberjack: provides a special operator to log changes in data

Also many more work-in-progress R packages hosted on eg GitHub, such as

But some/most of these packages are

  • not actively maintained any more, and/or maintainers are not being open for new features / patches
  • not being modular enough for extensions
  • prone to scoping issues
  • using strange syntax elements, eg dots in function names or object-oriented approaches not being very familiar to most R users
  • requires a lot of typing and code repetitions

So based on all the above subjective opinions, I decided to write the n+1th extensible log4j logger that fits my liking -- and hopefully yours as well -- with the focus being on:

  • keep it close to log4j
  • respect the most recent function / variable naming conventions and general R coding style
  • by default, rely on glue when it comes to formatting / rendering log messages, but keep it flexible if others prefer sprintf (eg for performance reasons) or other functions
  • support vectorization (eg passing a vector to be logged on multiple lines)
  • make it easy to extend with new features (eg custom layouts, message formats and output)
  • prepare for writing to various services, streams etc
  • provide support for namespaces, preferably automatically finding and creating a custom namespace for all R packages writing log messages, each with optionally configurable log level threshold, message and output formats
  • allow stacking loggers to implement logger hierarchy -- even within a namespace, so that the very same log call can write all the TRACE log messages to the console, while only pushing ERRORs to DataDog and eg INFO messages to CloudWatch
  • optionally colorize log message based on the log level
  • make logging fun

Welcome to the Bazaar, and if you have happened to already use any of the above mentioned R packages for logging, you might find useful the Migration Guide.

Interested in more details?

Check out the main documentation site at https://daroczig.github.io/logger or the vignettes on the below topics:

logger's People

Contributors

aaelony avatar amy17519 avatar artemklevtsov avatar atheriel avatar burgikukac avatar danchaltiel avatar daroczig avatar deeenes avatar earino avatar jozefhajnala avatar kpagacz avatar michaelchirico avatar pawelru avatar philaris avatar polkas avatar stphena avatar tdeenes avatar terashim 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

logger's Issues

Add size quota or log rotation to appender_file

Many enterprise companies require some kind of log file size management to assure that the disk won't get filled with logs causing server instability. Log4j has this capability with the RollingFileAppender class where you specify the log size threshold to roll on, and the number of rolling logs to keep. Looking at all of the R logging packages I can find no such feature. It would be nice if logger supported this capability so that I can use it on some of the autonomous R scripts I have running on servers.

truncate anonymous functions with {fn} formatting

The use of {fn} in a custom formatter goes a little crazy when the calling function name is not easily determined.

logger::log_layout(logger::layout_glue_generator(format = '[{time}] {level} {fn}: {msg}'))
log_info("hello")
# [2019-04-01 15:50:31] INFO NA: hello
func <- function(...) { log_info('hello'); }
func()
# [2019-04-01 15:50:39] INFO func: hello

But when done from an anonymous function (or similar), the log includes the entire function definition.

(function(...) { log_info('hello'); })()
# [2019-04-01 15:50:47] INFO (function(...) {: hello
# [2019-04-01 15:50:47] INFO     log_info("hello"): hello
# [2019-04-01 15:50:47] INFO }): hello

You can imagine how this gets crazy when the anon-function is more than "hello world".

Actually, it's a little more than just an anonymous function. In the code below, the function is perfectly named but not well-named within Map.

Map(func, 1, 2)
# [2019-04-01 15:54:02] INFO function (...) : hello
# [2019-04-01 15:54:02] INFO {: hello
# [2019-04-01 15:54:02] INFO     log_info("hello"): hello
# [2019-04-01 15:54:02] INFO }: hello
# [[1]]
# NULL

I wonder if the solution is to catch when {fn} will expand to something ridiculous and either head it or replace it with something much less unreasonable (such as "omg_im_lost" :-).

Custom Log Level

Is there any possibility to implement a customized log level different from the default?

appender_tee() does not work?

If I run

appender_tee(file.path(getwd(),'log.txt'))

R studio just prints out the structure:

function (lines) 
{
    appender_console(lines)
    appender_file(file)(lines)
}
<bytecode: 0x10c69fdc8>
<environment: 0x106ac7908>
attr(,"generator")
[1] "appender_tee(file = file.path(getwd(), \"log.txt\"))"

It seems that the function itself is not executed because if I now run

log_threshold(INFO) #define the level of output log information (DEBUG, INFO, WARN, ERROR)
log_formatter(formatter_glue)
log_layout(layout_glue_colors) #colorful log messages
appender_tee(file.path(getwd(),'log.txt')) #log both to console and to file
log_warn('I am a higher level log message that is very likely to be printed')

the WARN message is printed to the console but not to file (file was not created)

Shiny logging with plotly creates empty lines on hover

When using log_shiny_input_changes() in an app displaying a plotly plot, I get a lot of empty logging lines when hovering the graph. Can hovers be filtered out of the logging? Also it would be nice if you can set the log levels. For the rest a very nice feature :)

library(shiny)
library(plotly)
library(logger)

shinyApp(
  ui = fluidPage(
    plotlyOutput("plot"),
    selectInput("test", "test", choices = c("a", "b", "c"))
  ),
  server = function(input, output, session) {
    log_shiny_input_changes(input)
    
    output$plot <- renderPlotly({
      plot_ly(mtcars, x = ~mpg, y = ~wt, mode = "markers", type = "scatter")
    })
  }
)

mysql_appender

Is there any way to upload the logs directly to a DB rather than first to a file, open the file and upload it afterwards to DB?

Inconsistent default date formats

Just a question,
in the various layouts the default date formats are not consistent:

while layout_simple or logging has "%Y-%m-%d" as default, layout_glue has "%Y-%d-%m" (a strange format for me)

Does it have an underlying motive or is it just a typo?

Other file accessors besides appender?

Maybe I am being dense but while

log_appender(appender_file(someFilename))

worked great, I think I'd also like a (trivial) create_file(...) or overwrite_file(). Is there a common idiom in the other logging frameworks?

logger is ❤️ though. Really nice so far.

Including a simple text to log without any header

Is it possible to include a simple text (like an SQL query, ...) without any header (level, timestamp), whilst keeping the set layout for everything else?

For example, my current implementation using multiple log_info()

log_info("SQL query")
tictoc::tic("SQL query")
log_info(query)
# query …
log_info(capture.output(tictoc::toc()))

and the result:

INFO [2020-07-22 07:20:16] SQL query
INFO [2020-07-22 07:20:16] SELECT "Content ID", "Content Title"
FROM "Content Table"
INFO [2020-07-22 07:20:41] SQL query: 25.58 sec elapsed

but the preferred result would be something like:

INFO [2020-07-22 07:20:16] SQL query
SELECT "Content ID", "Content Title"
FROM "Content Table"
INFO [2020-07-22 07:20:41] SQL query: 25.58 sec elapsed

UTF-8

Hello,

I am enjoying logger so far. Today I encountered a problem with UTF-8.
I use two appenders - one for console (index 1), one for file output (index 2).

I try to log the phrase "wurde geöffnet" (german for "x has been opened")

logger::log_trace("x wurde geöffnet"):
output in file: "wurde geöffnet"
output in console: "wurde geöffnet"

logger::log_trace(enc2utf8("x wurde ge\u00F6ffnet")):
output in file: "wurde ge?ffnet"
output in console: "wurde geöffnet"

I am on Windows 10, Rstudio 1.3..1056, R 4.0.2.
Sys.setlocale("LC_TIME", "German")

BTW: Is there a way to do reverse file logging? I'd like to have the newest entries at top in my log files (or is that considered bad logging style?)

Status of `appender_dbi`?

Hi,
I read in the vignette:

And the are many other appender functions bundled with logger as well, eg some writing to Syslog, Telegram, Pushbullet, a database table or an Amazon Kinesis stream [...]

But looks like appending to a database backend is not available yet? Just curious (main use-case here would be to trigger other database tasks).

Thanks.

Vary formatter within appender_tee

Is there a way to combine, for example, the layout_glue_colors formatter for the console half of an appender_tee and no formatter for file half of the tee?

log_threshold error when using character input

If log_threshold() is called using a character argument, when the package is not attached, it gives the following error:

> logger::log_threshold("TRACE")
Error in as.environment("package:logger") : 
  no item called "package:logger" on the search list

This would help, for instance, when setting the log threshold using a configuration file (e.g. config.yml).

base::log clash

library(logger)

Attaching package: ‘logger’
The following object is masked from ‘package:base’:
log

Really not good! :-)

How to log the contents of a dataframe?

Hi! Sorry if this is a dumb question, but I want to do something like:

dropped_rows <- grouped_clean_data %>% select(date, idx, n_days) %>% filter(n_days <7)
if (nrow(dropped_rows) > 0){
  log_warn("Dropping the following weeks due to incomplete data:")
  log_warn("{dropped_rows}")
}

But this ... doesn't work. What's the recommend way to achieve something like this?

Append/Prepend new lines to logs

So at the moment if I do

> library(logger)
> log_info("hello world")

I will get something along the lines of

INFO [2019-08-29 14:28:43] hello world

But what I want to achieve is something more like one of the following depending on the situation.


INFO [2019-08-29 14:28:43] hello world
INFO [2019-08-29 14:28:43] hello world


INFO [2019-08-29 14:28:43] hello world

This really helps to break logs ups. I can achieve a space after the log with

> log_info("hello world\n\n")
INFO [2019-08-29 14:28:43] hello world

However the following doesn't achieve the desired effect

> log_trace("\n\nhello world")
INFO [2019-08-29 14:28:43] 
hello world

Get the Parent's fn name or get name of function in mapping calls.

This may be similar to issue #20 . I want to output the fn name to the console and/or output file within a purrr map. For a console example:

`%>%` <- magrittr::`%>%`

## Custom logger output for console
## output: level, time, function name, message
r_log <- logger::layout_glue_generator(
  format = paste(
    '{crayon::bold(colorize_by_log_level(level, levelr))}',
    '[{crayon::italic(format(time, "%Y-%m-%d %H:%M:%S"))}]',
    '{crayon::underline(fn)}{crayon::underline("()")}:',
    '{msg}'
  )
)

## Set custom output for all loggers
logger::log_layout(r_log)

## purrr ----
x <- 1:3 %>% 
  purrr::map(~ {
    logger::log_info("Adding {.x} to 1")
    .x + 1
  })
#> INFO [2020-04-06 13:00:01] .f(): Adding 1 to 1
#> INFO [2020-04-06 13:00:01] .f(): Adding 2 to 1
#> INFO [2020-04-06 13:00:01] .f(): Adding 3 to 1

## Make it a function
add_1 <- function(.x) {
  logger::log_info("Adding {.x} to 1")
  .x + 1
}

x <- 1:3 %>% 
  purrr::map(add_1)
#> INFO [2020-04-06 13:00:01] .f(): Adding 1 to 1
#> INFO [2020-04-06 13:00:01] .f(): Adding 2 to 1
#> INFO [2020-04-06 13:00:02] .f(): Adding 3 to 1

## lapply ----
## Same thing applies to lapply
x <- 1:3 %>% 
  lapply(function(.x) {
    logger::log_info("Adding {.x} to 1")
    .x + 1
  })
#> INFO [2020-04-06 13:00:02] FUN(): Adding 1 to 1
#> INFO [2020-04-06 13:00:02] FUN(): Adding 2 to 1
#> INFO [2020-04-06 13:00:02] FUN(): Adding 3 to 1

x <- 1:3 %>% 
  lapply(add_1)
#> INFO [2020-04-06 13:00:02] FUN(): Adding 1 to 1
#> INFO [2020-04-06 13:00:02] FUN(): Adding 2 to 1
#> INFO [2020-04-06 13:00:02] FUN(): Adding 3 to 1

Created on 2020-04-06 by the reprex package (v0.3.0)

Is there a way within logger::log_info to get the parent functions name if it is called within another function? I wasn't sure if we could change the .logcall, .topcall, or .topenv params to get the functions name to print out or if there was another approach to use fn names. Any help in this matter would be greatly appreciated!

Example 2:

i_want_this_name <- function(message, .x) {
  print(message)
  x <- 1:.x %>% 
    purrr::map(add_1)
  return(NULL)
}

x <- i_want_this_name(
  message = "Hello! Adding 1 to every integer to every number up to .x!",
  .x = 3
)
#> [1] "Hello! Adding 1 to every integer to every number up to .x!"
#> INFO [2020-04-06 13:06:36] .f(): Adding 1 to 1
#> INFO [2020-04-06 13:06:36] .f(): Adding 2 to 1
#> INFO [2020-04-06 13:06:36] .f(): Adding 3 to 1

Thanks!

log_warnings and log_errors displaying "eval" as function instead of function that led to error

I'm experiencing an issue of not seeing the correct displayed "function" when using

logger::log_warnings()
logger::log_errors()

I'm using the standard json formatter (formatter_json), and when errors/warnings occur inside of functions I've written, it would be great if the json "fn" field could include which function exactly led to the error/warning. Right now, I'm seeing for all of these that the json log outputs is for example:

{"time":"2020-10-05 12:09:48","level":"WARN","ns":"base","topenv":"base","fn":"eval","msg":"DE Opimization improved within 50 iterations of the max"}

It would be super helpful to have this JSON evaluate the "fn" field as the actual function (instead of "eval") which called the warning for meta-analysis of which functions in my code are leading to errors/warnings. Thanks!

R logging philosophy

Wasn't sure where else to raise this question so apology for opening an issue for it -- I'm trying to understand a little bit more about the philosophy around logging in R. In my code currently, I have a lot of pieces that look like this:

log_error("Here's a detailed error message")
stop("Here's a slightly less detailed message")

Or

log_warn("Here's a detailed warning message")
warning("Here's a slightly less detailed warning")

This doesn't feel quite right, but I feel like I don't have a good mental model of where "logging" should be used as opposed to R native messaging.

I've taken a look at this stack overflow answer and Hadley's chapter on conditions and I still don't really feel like I understand what's the right way to do messaging + logging.

If there are any resources on this or a concise answer I'd be happy to add to the docs for this package.

timeline for CRAN release?

I apologize, this is not really a good issue, but ...

Do you have an expectation of CRAN release of your recent code? I can always install from this source, but I have production locations in which I prefer to stick with "production" releases. (I'm particularly looking forward to log_errors, et al.)

log_warnings() etc. not compatible with profvis

Thanks for this great package! As a python native dabbling with R, it's great to find something so ergonomic for logging. This isn't really an issue per se, but more of an FYI that if you try to run code with one of the log_warnings(), log_errors(), etc. functions active from inside of a profvis profiling session, you'll get the following error:

Error in globalCallingHandlers(warning = function(m) { :
  should not be called with handlers on the stack
Calls: profvis ... ..stacktraceon.. -> <Anonymous> -> globalCallingHandlers
Execution halted

It's probably not urgent to find a workaround, but a note in the documentation might be helpful for others who come across this as a surprise.

Make it easier to set the log threshold with an environment variable.

I'm a big fan of setting log thresholds using environment variables so that people don't have to edit my apps to change the level.

This is really useful in production environments where the people running my code often do not know R and should not be editing any of the scripts, but who may need to change the log threshold of the application prior to execution.

In order to get this to work with logger, I end up having to do something like this:

log_threshold_from_env_var <- function(){
  log_level_env_var <- Sys.getenv("LOG_LEVEL", "INFO")
  log_levels <- c("FATAL", "ERROR", "WARN", "SUCCESS", "INFO", "DEBUG", "TRACE")
  if (! (log_level_env_var %in% log_levels)){
    err_msg <- "The LOG_LEVEL environment variable must be either unset, or set to a valid log level" 
    stop(err_msg)
  }
  get(log_level_env_var)
}

Which I can use as follows:

library(logger)
log_threshold(log_threshold_from_env_var())

This still defaults to INFO if the env var is unset.

Please could something like this be added to logger to make setting the log threshold from an environment variable more straightforward.

If there's a better way of doing this already, it's not clear from the documentation, so then I'd change this to a documentation request.

Example of logging a matrix?

Would you mind adding an example of how to log a matrix to the documentation or here? Struggling to figure out how to piece all the individual components together.

I thought something like

log_debug("S_tilde is:")
log_formatter(formatter_paste())
log_debug(S_tilde)
log_formatter(formatter_glue())
log_debug("Expected edges: {expected_edges}")
log_debug("Observed edges: {m}")

would work, but the log_debug(S_tilde) line is throwing an error.

New meta vars

I love using this logger, but had to customize my layout function to be able to include new variables. I find it useful to also capture R Version, and package version (ie namespace version if namespace is a package). Can these be added to get_logger_meta_variables?

Weird error when message is json

Latest version from master branch:

library(logger)
log_threshold(DEBUG)
log_info(jsonlite::toJSON(list("key" = "value")))

Error in parse(text = text, keep.source = FALSE) :
:1:7: unexpected '['
1: "key":[
^

appender_tee is showing some wrong outsputs in file but correct outputs in console

Hi,
i am currently working on implementing the logger package into production. The following code causes some strange numbers and signs when the code is executed manually in RStudio. If i use it from a cronjob it looks fine.

Here is the basic code:

log_layout(layout_glue_colors)
  file_name<-paste0("log_files/Trading_Log_",Sys.Date(),".log")
  log_appender(appender_tee(file_name))
  log_info('Starting Script')

Here is the file output

�[1m�[0mINFO�[0m�[0m�[0m�[22m [�[3m2020-10-28 17:17:03�[23m] �[38;5;246mStarting Script�[39m�[0m�[0m

Any ideas? Just updated to version 0.2 via Github still these issues.
I am using R version 4.0.0 (2020-04-24) -- "Arbor Day"

logger issues with pipe

Hi, I have some weird logger problems when I run functions with the pipeline.

Minimal example:

library(magrittr)
fun_1 <- function(x) { logger::log_info("hello_", x) }
fun_2 <- function(x) { logger::log_warn("bye_", x) }

fun_1("Federick")
#> INFO [2020-11-24 16:54:46] hello_Federick
fun_2("Federick")
#> WARN [2020-11-24 16:54:46] bye_Federick

"Federick" %>% 
    fun_1() %>% 
    fun_2()
#> INFO [2020-11-24 16:54:46] hello_Federick
#> WARN [2020-11-24 16:54:46]

Real example: log information is printed before function execution and in reverse order. After printing, the functions are executed correctly and in the correct order.

library(metar)
#> Registered S3 method overwritten by 'quantmod':
#>   method            from
#>   as.zoo.data.frame zoo
mre <- metarExperiment('RealData') %>% 
    metaphlan_ancom(tax_level = 'Genus') %>% 
    kraken_ancom(tax_level = 'Genus') %>% 
    metaphlan_barplots(tax_level = 'Genus') %>% 
    kraken_barplots(tax_level = 'Genus')
#> INFO [2020-24-11 17:03:06] [kraken_barplots   ] running
#> INFO [2020-24-11 17:03:06] [metaphlan_barplots] running
#> INFO [2020-24-11 17:03:06] [kraken_ancom      ] running
#> INFO [2020-24-11 17:03:06] [metaphlan_ancom   ] running
#> INFO [2020-24-11 17:03:06] [metarExperiment   ] Collecting data

Thanks in advance

Logger not appending to file when running shiny from code

I am using logger in a Shiny app I'm developing. It is based on an implementation of an R Package that I have yet to publish, therefore it is difficult to replicate!

Logger stops writing to file, just before an if statement.

My overall settings for logger before executing my shiny app is:

# Setup logger
debug <- 2
if (debug){
  log_threshold(DEBUG)
  
  if (debug == 2)
    log_threshold(TRACE)
} else {
  log_threshold(INFO)
}
log_appender(appender = appender_tee(file = "../app.log"))

My server:

# Define server logic required to draw a histogram
server <- function(input, output) {
  log_info(
    "[***************************] Starting new run [***************************]"
  )
  
  # Log input changes
  logger::log_shiny_input_changes(input)
  
  # Generating circExperiment object here
  source("import_circSample.R")
  
  # Collect alignment statistics
  source("collectStatistics.R")
  # Sys.sleep(1)   ## Uncommenting this, ensures that everything is written to file
  
  log_debug("Generating random plot")
  Sys.sleep(1)   ## Inserting sleep here does nothing to resolve the issue
  output$totalreads <- renderPlot(first, height = 2560)
}

Logger stops recording inside my collectStatistics.R:

log_info("Collecting all statistics")

long_table <- TRUE

##Last logged record
log_trace(paste(
  "Variables:",
  paste("Long table format:", long_table),
  sep = "\n"
))

if (long_table) {
  
  bsj <- bsjStats(object, out_type = "long")
  align <- alignmentStats(object, out_type = "long")
} else {
  
  bsj <- bsjStats(object, out_type = "wide")
  align <- alignmentStats(object, out_type = "wide") 
}

# Everything from here is not logged
log_debug("Removing unwanted entry from alignment statistics")
...

Even though I can't show you the stat functions, I hope this brings some light to the issue..

sessionInfo()
R version 4.0.2 (2020-06-22) Platform: x86_64-pc-linux-gnu (64-bit) Running under: Arch Linux  Matrix products: default BLAS:   /usr/lib/libblas.so.3.9.0 LAPACK: /usr/lib/liblapack.so.3.9.0  locale:  [1] LC_CTYPE=en_DK.UTF-8       LC_NUMERIC=C               LC_TIME=en_DK.UTF-8        LC_COLLATE=en_DK.UTF-8     LC_MONETARY=en_DK.UTF-8    LC_MESSAGES=en_DK.UTF-8     [7] LC_PAPER=en_DK.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_DK.UTF-8 LC_IDENTIFICATION=C         attached base packages: [1] stats4    parallel  stats     graphics  grDevices utils     datasets  methods   base       other attached packages:  [1] ensembldb_2.12.1        AnnotationFilter_1.12.0 GenomicFeatures_1.40.0  AnnotationDbi_1.50.1    Biobase_2.48.0          GenomicRanges_1.40.0    GenomeInfoDb_1.24.2      [8] IRanges_2.22.2          S4Vectors_0.26.1        BiocGenerics_0.34.0     circulaR_0.0.0.9000     shiny_1.5.0             shinydashboard_0.7.1    logger_0.2.0            [15] tidyr_1.1.0             ggplot2_3.3.2           ggthemes_4.2.0          stringr_1.4.0           dplyr_1.0.0             tibble_3.0.1            usethis_1.6.1            loaded via a namespace (and not attached):   [1] colorspace_1.4-1                       ellipsis_0.3.1                         htmlTable_2.0.0                        biovizBase_1.36.0                        [5] XVector_0.28.0                         base64enc_0.1-3                        fs_1.4.2                               dichromat_2.0-0                          [9] rstudioapi_0.11                        farver_2.0.3                           bit64_0.9-7                            fansi_0.4.1                             [13] interactiveDisplayBase_1.26.3          splines_4.0.2                          geneplotter_1.66.0                     knitr_1.29                              [17] jsonlite_1.7.0                         Formula_1.2-3                          Rsamtools_2.4.0                        annotate_1.66.0                         [21] cluster_2.1.0                          dbplyr_1.4.4                           png_0.1-7                              BiocManager_1.30.10                     [25] readr_1.3.1                            compiler_4.0.2                         httr_1.4.1                             backports_1.1.8                         [29] lazyeval_0.2.2                         assertthat_0.2.1                       Matrix_1.2-18                          fastmap_1.0.1                           [33] cli_2.0.2                              later_1.1.0.1                          acepack_1.4.1                          htmltools_0.5.0                         [37] prettyunits_1.1.1                      tools_4.0.2                            gtable_0.3.0                           glue_1.4.1                              [41] GenomeInfoDbData_1.2.3                 rappdirs_0.3.1                         Rcpp_1.0.4.6                           vctrs_0.3.1                             [45] Biostrings_2.56.0                      rtracklayer_1.48.0                     xfun_0.15                              mime_0.9                                [49] lifecycle_0.2.0                        XML_3.99-0.3                           AnnotationHub_2.20.0                   zlibbioc_1.34.0                         [53] scales_1.1.1                           BSgenome_1.56.0                        VariantAnnotation_1.34.0               ProtGenerics_1.20.0                     [57] hms_0.5.3                              promises_1.1.1                         SummarizedExperiment_1.18.1            RColorBrewer_1.1-2                      [61] BSgenome.Hsapiens.NCBI.GRCh38_1.3.1000 yaml_2.2.1                             curl_4.3                               memoise_1.1.0                           [65] gridExtra_2.3                          biomaRt_2.44.1                         rpart_4.1-15                           latticeExtra_0.6-29                     [69] stringi_1.4.6                          RSQLite_2.2.0                          BiocVersion_3.11.1                     genefilter_1.70.0                       [73] checkmate_2.0.0                        BiocParallel_1.22.0                    rlang_0.4.6                            pkgconfig_2.0.3                         [77] matrixStats_0.56.0                     bitops_1.0-6                           evaluate_0.14                          lattice_0.20-41                         [81] purrr_0.3.4                            labeling_0.3                           htmlwidgets_1.5.1                      GenomicAlignments_1.24.0                [85] bit_1.1-15.2                           tidyselect_1.1.0                       plyr_1.8.6                             magrittr_1.5                            [89] DESeq2_1.28.1                          R6_2.4.1                               generics_0.0.2                         Hmisc_4.4-0                             [93] DelayedArray_0.14.0                    DBI_1.1.0                              pillar_1.4.4                           foreign_0.8-80                          [97] withr_2.2.0                            survival_3.2-3                         RCurl_1.98-1.2                         nnet_7.3-14                            [101] crayon_1.3.4                           BiocFileCache_1.12.0                   rmarkdown_2.3                          jpeg_0.1-8.1                           [105] progress_1.2.2                         locfit_1.5-9.4                         grid_4.0.2                             data.table_1.12.8                      [109] blob_1.2.1                             digest_0.6.25                          pbmcapply_1.5.0                        xtable_1.8-4                           [113] httpuv_1.5.4                           openssl_1.4.2                          munsell_0.5.0                          Gviz_1.32.0                            [117] askpass_1.1
--

async logging

For slow appenders, it might be useful to run in the background, also to collect multiple log records / time intervals before calling the appender.

Logging stacktrace//escaping glue

So I'm trying to log the stacktrace from inside options(error={}) (see: https://stackoverflow.com/questions/1975110/printing-stack-trace-and-continuing-after-error-occurs-in-r)

The problem here is that these strings will often have glue special characters, that then cause additional errors. To get around this, I'm escaping strings before passing them in:

escape_glue_syntax <- function(value) { str_replace_all(value, '\\{', '{{') %>% str_replace_all('\\}','}}') }

This works, but feels pretty nasty- when what I really want is to just not use glue formatting.


Tangentially, I thought maybe I should just call warning(the_string) and use log_warnings() to capture them into the logger, but despite the reference page (https://daroczig.github.io/logger/reference/log_warnings.html), this doesn't seem to exist?

Any help/advice would be appreciated.

log_errors will still produce an error log when using a try/tryCatch

When I am using logger::log_errors(), if I want to catch failures, logger will still log those errors; which I don't necessarily always want. For example:

library(logger)
log_errors()

my_fun <- function() {
  res <- try(stop("hello world"), silent = TRUE)
  if (methods::is(res, "try-error")) {
    TRUE
  } else {
    FALSE
  }
}

my_fun()
# ERROR [2019-11-11 15:47:08] hello world
# [1] TRUE

return value?

Have you considered invisibly returning the log message?

I find myself periodically doing something like:

if (x < badcondition) {
  logger::log_fatal("message of badness {x}")
  stop("message of badness ", x)
}

I can form the message once and use it in both logger::log_fatal and stop, but (1) I might like to take advantage of logger's formatting methodologies (e.g., glue or json); and (2) I think a more straight-forward approach is something like:

if (x < badcondition) {
  stop(logger::log_fatal("message of badness {x}"))
}

(This if course applies to other loggers, not just log_fatal.)

I'd think there are two good options for exactly what to return:

  • "message of badness 42", before some of the final formatting ... or
  • "[2019-07-12 17:04:42] FATAL message of badness 42", the literal full log entry

Thoughts?

json logging

I think we can do a little bit better compared to what we have at the moment

We can serialize arbitrary R object (msg) to JSON instead of simple message = as.character(msg). So it can be just:

    toJSON(list(
            level = attr(level, 'level'),
            timestamp = Sys.time(),
            message = msg
        ), auto_unbox = TRUE))

Add Microsoft Teams Appender

Add a basic appender for posting to a Microsoft Teams channel.

I will be submitting a pull request for this shortly.

Feature request: integration with tryCatch

Dear colleagues,

Following the best practices of our Software developer colleagues the data scientist team where I am working for have started to implement trycatch + standard logging to debug our containerized code faster.

I have been experimenting with logger and so far the experience is awesome!. However it is a bit tricky to combine with trycatch. For example:

s3upload <- function(file_path, file_name_s3, target_bucket, region_name) {
  tryCatch(
    {
      
      s3save(file = paste0(file_path, file_name_s3),
                 bucket = target_bucket,
                 object = paste0("example/", 
                                 file_name),
                 multipart = TRUE,
                 show_progress = TRUE)
      log_info(paste0("Data uploaded to s3!: ", file_name))
    }, error = function(e) {
      message(e)
    }, warning = function(w) {
      message(w)
    }
  )
}

When running this (which btw is wrong code) I get the following error:

> s3upload(file_path = argument_parser$output_path, 
+          file_name_s3 = file_name,
+          target_bucket = argument_parser$bucket, 
+          region_name = argument_parser$region)
formal argument "file" matched by multiple actual arguments

When running with logger:

s3upload <- function(file_path, file_name_s3, target_bucket, region_name) {
  tryCatch(
    {
      
      s3save(file = paste0(file_path, file_name_s3),
                 bucket = target_bucket,
                 object = paste0("example/", 
                                 file_name),
                 multipart = TRUE,
                 show_progress = TRUE)
      log_info(paste0("Data uploaded to s3!: ", file_name))
    }, error = function(e) {
      log_error(e)
    }, warning = function(w) {
      log_warn(w)
    }
  )
}

I get a very cryptic error.

> s3upload(file_path = argument_parser$output_path, 
+          file_name_s3 = file_name,
+          target_bucket = argument_parser$bucket, 
+          region_name = argument_parser$region)
 Error: All unnamed arguments must be length 1 

I am misunderstanding the usage of logger in this situations? Should I be using trycatchlog instead? Is this a feature that is not supported yet?

BR
/Edgar

Get logging level from environement variable

Hello,

Thanks for the library.

I would like to configure the logging level with an environment variable.

logging_level <- Sys.getenv("LOGGING_LEVEL", "INFO", FALSE)
logging_levels <- c(
  "trace" = TRACE,
  "debug" = DEBUG,
  "info" = INFO,
  "success" = SUCCESS,
  "warn" = WARN,
  "error" = ERROR,
  "fatal" = FATAL
)
logging_level <- logging_levels[tolower(logging_level)]
logging_level <- ifelse(is.na(logging_level), INFO, logging_level)
log_threshold(logging_level)

I got an error because it doesn't recognize the logging_level.

Any idea ?

parallel processing and logger

Hi, do you have any recommandation for logging parallel processing ? I can't make your logger work in parallel which is a pity because it's a good logging solution !
Ideally, it would work with future (so with furrr) and log in the same file with thread information added to the timestamp.

add index and namespace to message/warnings/error handler hooks

Hello,

In my projects I log to console as well as to logfiles.

Now I want to use

logger::log_warnings()
logger::log_errors()

to see warnings and errors in my log files, too.

Now I see those messages twice in my console. I guess that logger cannot suppress the output of RStudio, but it is possible to restrict the logging to file while all other logging messages appear at both places?

Further I suggest to change the displayed "function" for those messages. For warnings it is:

function (m) { logger::log_warn(m$message) }

Example:

[13:29:46] WARN function (m) { logger::log_warn(m$message) }: the condition has length > 1 and only the first element will be used

and for errors it is simply h:

[13:29:47] ERROR h: let's stop execution here

Maybe it should be empty? (or maybe logger is able to display line number? that would be fantastic)

Syslog appender

Hey, I'm the author of the rsyslog package. I'm wondering if you're interested in including a syslog appender. If so, I'd be happy to write it.

drop glue dependency

logging users complained about the extra glue dependency, so let's make that optional.

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.