s-fleck/lgr

How can I print level character string instead of integer in file?

Closed this issue · 3 comments

I am using a rotating appender like so:

lg <- get_logger("test")$set_propagate(FALSE)$set_appenders(list(
  rotating = AppenderFileRotatingTime$new(
    file = "./logs/gen_evtrip.log",
    age = "1 day",
    layout = LayoutJson$new()
  )
))

When I use the following to print log to a file:
lg$log(level = "info", "This is an important message about %s going wrong", "->something<-", "IP" = get_ip())

I get:

{"level":400,"timestamp":"2019-11-23 18:10:36","logger":"(unnamed logger)","caller":"(shell)","msg":"This is an important message about ->something<- going wrong","IP":"71.212.154.194"}

I want to print the string "info" instead of 400. Also, somehow (due to some experiments with config probably), the "logger" is now "(unnamed logger)" when it was "test" before.

text log levels:

Writing the text log levels is currently only supported for plaintext logging. This is intentional since it makes filtering the logs (for example in the $show and $data methods of appenders) for loggers that treat log events as "data" much more straight forward.

If you still want text log levels in your JSON file, you can use lgr's flexible filter system to achieve that. Filters can modify every aspect of a log event in a slightly hackish way.

  library(lgr)
  
  lg <- get_logger("test")$set_propagate(FALSE)$set_appenders(list(
    rotating = AppenderFileRotatingTime$new(
      file = "~gen_evtrip.log",
      age = "1 day",
      layout = LayoutJson$new()
    )
  ))
    
  lg$add_filter(function(event) {
    event$level <- lgr::label_levels(event$level)
    TRUE  # filters must return TRUE or FALSE, but the event stays modified
  }, name = "label_level")  # setting a name is optional
    
  lg$info("test")
  lg$fatal("test2")
  
  lg$appenders$rotating$show()
  lg$appenders$rotating$show("fatal")  # wont work anymore because of the filter :(

This will cause (lg$appenders$rotating$show("fatal")) to not work anymore because that function expects numeric log levels. It might also cause problems if you want to log to several destinations at the same time (such as a JSON file and a database). So use this power with care :)

edit: I will think about adding a similar feature to LayoutJson() that would have less side effects, might be a while before I come around to it.

(unnamed logger)
I don't know why your logger transforms into an "unnamed logger", but this is potentially very bad. Can you provide a reproducible example for that (possibly in a sepparate issue)? If I run your example I get the correct logger names.

I hope this was helpful, if you have any more questions please ask.

Thanks, the suggested method works perfectly. Just as an aside, does adding a filter to the appender affect the main program's performance? I don't think it should since the appender is a separate process but just wanted to confirm.

Sadly logging will impact the main programs performance as everything here is single-threaded (and I didn't find a nice solution to get multi-threaded logging working in R). Adding the filter will not influence the performance noticably- it just adds a few simple function calls. If performance is critical you should try benchmark your program with and without logging.