| Title: | A Fully Featured Logging Framework |
|---|---|
| Description: | A flexible, light-weight logging framework based on 'R6' classes. It supports hierarchical loggers, structured logging, output to plaintext, 'JSON', (rotating) files, and memory buffers. Additional appenders for 'Elasticsearch', 'Dynatrace', databases, email and push notifications, and more are available in the 'lgrExtra' package. |
| Authors: | Stefan Fleck [aut, cre] (ORCID: <https://orcid.org/0000-0003-3344-9851>) |
| Maintainer: | Stefan Fleck <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.5.2.9000 |
| Built: | 2026-06-03 09:36:59 UTC |
| Source: | https://github.com/s-fleck/lgr |
An Appender that Buffers LogEvents in-memory and and redirects them to other Appenders once certain conditions are met.
appenders, set_appenders()
Like for a Logger. Buffered events will be passed on to these Appenders once a flush is triggered
flush_on_exit, set_flush_on_exit(x)TRUE or FALSE: Whether the
buffer should be flushed when the Appender is garbage collected (f.e when
you close R)
flush_on_rotate, set_flush_on_rotateTRUE or FALSE: Whether
the buffer should be flushed when the Buffer is full (f.e when you close
R). Setting this to off can have slightly negative performance impacts.
lgr::Filterable -> lgr::Appender -> lgr::AppenderMemory -> AppenderBuffer
lgr::Filterable$add_filter()lgr::Filterable$filter()lgr::Filterable$remove_filter()lgr::Filterable$set_filters()lgr::Appender$set_layout()lgr::Appender$set_threshold()lgr::AppenderMemory$append()lgr::AppenderMemory$set_buffer_size()lgr::AppenderMemory$set_flush_on_exit()lgr::AppenderMemory$set_flush_on_rotate()lgr::AppenderMemory$set_flush_threshold()lgr::AppenderMemory$set_should_flush()lgr::AppenderMemory$show()new()
The Layout for this Appender is used only to format console output of
its $show() method.
AppenderBuffer$new(
threshold = NA_integer_,
layout = LayoutFormat$new(fmt = "%L [%t] %m", timestamp_fmt = "%H:%M:%S", colors
= getOption("lgr.colors")),
appenders = NULL,
buffer_size = 1000,
flush_threshold = NULL,
flush_on_exit = TRUE,
flush_on_rotate = TRUE,
should_flush = NULL,
filters = NULL
)flush()
Sends the buffer's contents to all attached Appenders and then clears the Buffer
AppenderBuffer$flush()
clear()
Clears the buffer, discarding all buffered Events
AppenderBuffer$clear()
set_appenders()
Exactly like A Logger, an AppenderBuffer can have an arbitrary amount of Appenders attached. When the buffer is flushed, the buffered events are dispatched to these Appenders.
AppenderBuffer$set_appenders(x)
xsingle Appender or a list thereof. Appenders control the
output of a Logger. Be aware that a Logger also inherits the Appenders
of its ancestors (see vignette("lgr", package = "lgr") for more info
about Logger inheritance).
add_appender()
Add an Appender to the AppenderBuffer
Add or remove an Appender. Supplying a name is optional but
recommended. After adding an Appender with
appender$add_appender(AppenderConsole$new(), name = "console") you can
refer to it via appender$appenders$console. remove_appender() can
remove an Appender by position or name.
AppenderBuffer$add_appender(appender, name = NULL)
appendera single Appender
namea character scalar. Optional but recommended.
remove_appender()
remove an appender
AppenderBuffer$remove_appender(pos)
posinteger index or character name of the Appender(s) to
remove
format()
AppenderBuffer$format(...)
Other Appenders:
Appender,
AppenderConsole,
AppenderFile,
AppenderFileRotating,
AppenderFileRotatingDate,
AppenderFileRotatingTime,
AppenderTable
An Appender that outputs to the R console. If you have the package crayon installed log levels will be coloured by default (but you can modify this behaviour by passing a custom Layout).
lgr::Filterable -> lgr::Appender -> AppenderConsole
new()
AppenderConsole$new(
threshold = NA_integer_,
layout = LayoutFormat$new(fmt = "%L [%t] %m %f", timestamp_fmt = "%H:%M:%OS3",
colors = getOption("lgr.colors", list())),
filters = NULL,
connection = NULL
)append()
AppenderConsole$append(event)
set_connection()
AppenderConsole$set_connection(connection)
Other Appenders:
Appender,
AppenderBuffer,
AppenderFile,
AppenderFileRotating,
AppenderFileRotatingDate,
AppenderFileRotatingTime,
AppenderTable
# create a new logger with propagate = FALSE to prevent routing to the root # logger. Please look at the section "Logger Hirarchies" in the package # vignette for more info. lg <- get_logger("test")$set_propagate(FALSE) lg$add_appender(AppenderConsole$new()) lg$add_appender(AppenderConsole$new( layout = LayoutFormat$new("[%t] %c(): [%n] %m", colors = getOption("lgr.colors")))) # Will output the message twice because we attached two console appenders lg$warn("A test message") lg$config(NULL) # reset config# create a new logger with propagate = FALSE to prevent routing to the root # logger. Please look at the section "Logger Hirarchies" in the package # vignette for more info. lg <- get_logger("test")$set_propagate(FALSE) lg$add_appender(AppenderConsole$new()) lg$add_appender(AppenderConsole$new( layout = LayoutFormat$new("[%t] %c(): [%n] %m", colors = getOption("lgr.colors")))) # Will output the message twice because we attached two console appenders lg$warn("A test message") lg$config(NULL) # reset config
A simple Appender that outputs to a file in the file system. If you plan
to log to text files, consider logging to JSON files and take a look at
AppenderJson, which is a shortcut for AppenderFile preconfigured with
LayoutJson.
lgr::Filterable -> lgr::Appender -> AppenderFile
filecharacter scalar. path to the log file
datadata.frame. Contents of file parsed to a
data.frame if used with a Layout that supports parsing of log
file data (notably LayoutJson). Will throw an error if Layout does
not support parsing.
datacharacter scalar. Like $data, but returns a data.table
instead (requires the data.table package).
new()
AppenderFile$new( file, threshold = NA_integer_, layout = LayoutFormat$new(), filters = NULL )
append()
AppenderFile$append(event)
set_file()
Set a log file
AppenderFile$set_file(file)
filecharacter scalar. Path to the log file. If file does not
exist it will be created.
show()
Display the contents of the log file.
AppenderFile$show(threshold = NA_integer_, n = 20L)
thresholdcharacter or integer scalar. The minimum log level
that should be displayed.
ninteger scalar. Show only the last n log entries that match
threshold.
lgr::Filterable -> lgr::Appender -> lgr::AppenderFile -> AppenderJson
new()
AppenderJson$new( file, threshold = NA_integer_, layout = LayoutJson$new(), filters = NULL )
Other Appenders:
Appender,
AppenderBuffer,
AppenderConsole,
AppenderFileRotating,
AppenderFileRotatingDate,
AppenderFileRotatingTime,
AppenderTable
Other Appenders:
Appender,
AppenderBuffer,
AppenderConsole,
AppenderFileRotating,
AppenderFileRotatingDate,
AppenderFileRotatingTime,
AppenderTable
lg <- get_logger("test") default <- tempfile() fancy <- tempfile() json <- tempfile() lg$add_appender(AppenderFile$new(default), "default") lg$add_appender( AppenderFile$new(fancy, layout = LayoutFormat$new("[%t] %c(): %L %m")), "fancy" ) lg$add_appender( AppenderFile$new(json, layout = LayoutJson$new()), "json" ) lg$info("A test message") readLines(default) readLines(fancy) readLines(json) # cleanup lg$config(NULL) unlink(default) unlink(fancy) unlink(json) tf <- tempfile() lg <- get_logger("test")$ set_appenders(AppenderJson$new(tf))$ set_propagate(FALSE) lg$info("A test message") lg$info("A test message %s strings", "with format strings", and = "custom_fields") lg$appenders[[1]]$show() lg$appenders[[1]]$data # cleanup lg$config(NULL) unlink(tf)lg <- get_logger("test") default <- tempfile() fancy <- tempfile() json <- tempfile() lg$add_appender(AppenderFile$new(default), "default") lg$add_appender( AppenderFile$new(fancy, layout = LayoutFormat$new("[%t] %c(): %L %m")), "fancy" ) lg$add_appender( AppenderFile$new(json, layout = LayoutJson$new()), "json" ) lg$info("A test message") readLines(default) readLines(fancy) readLines(json) # cleanup lg$config(NULL) unlink(default) unlink(fancy) unlink(json) tf <- tempfile() lg <- get_logger("test")$ set_appenders(AppenderJson$new(tf))$ set_propagate(FALSE) lg$info("A test message") lg$info("A test message %s strings", "with format strings", and = "custom_fields") lg$appenders[[1]]$show() lg$appenders[[1]]$data # cleanup lg$config(NULL) unlink(tf)
Log to a rotating file
Log to a rotating file
An extension of AppenderFile that rotates logfiles based on certain
conditions. Please refer to the documentation of rotor::rotate() for
the meanings of the extra arguments
lgr::Filterable -> lgr::Appender -> lgr::AppenderFile -> AppenderFileRotating
backupsA data.frame containing information on path, file size,
etc... on the available backups of file.
new()
AppenderFileRotating$new( file, threshold = NA_integer_, layout = LayoutFormat$new(), filters = NULL, size = Inf, max_backups = Inf, compression = FALSE, backup_dir = dirname(file), create_file = NULL )
size, max_backups, compression, backup_dir, fmtsee rotor::rotate() for the meaning of these arguments. Note that
fmt corresponds to format and backup_dir to dir.
append()
AppenderFileRotating$append(event)
rotate()
AppenderFileRotating$rotate(force = FALSE)
prune()
AppenderFileRotating$prune(max_backups = self$max_backups)
set_file()
AppenderFileRotating$set_file(file)
set_size()
AppenderFileRotating$set_size(x)
set_max_backups()
AppenderFileRotating$set_max_backups(x)
set_compression()
AppenderFileRotating$set_compression(x)
set_create_file()
AppenderFileRotating$set_create_file(x)
set_backup_dir()
AppenderFileRotating$set_backup_dir(x)
format()
AppenderFileRotating$format(color = false, ...)
clone()
The objects of this class are cloneable with this method.
AppenderFileRotating$clone(deep = FALSE)
deepWhether to make a deep clone.
AppenderFileRotatingDate, AppenderFileRotatingTime, rotor::rotate()
Other Appenders:
Appender,
AppenderBuffer,
AppenderConsole,
AppenderFile,
AppenderFileRotatingDate,
AppenderFileRotatingTime,
AppenderTable
Log to a date-stamped rotating file
Log to a date-stamped rotating file
This is a simpler version of AppenderFileRotatingTime when the timestamps do not need to include sub-day accuracy.
lgr::Filterable -> lgr::Appender -> lgr::AppenderFile -> lgr::AppenderFileRotating -> lgr::AppenderFileRotatingTime -> AppenderFileRotatingDate
lgr::Filterable$add_filter()lgr::Filterable$filter()lgr::Filterable$remove_filter()lgr::Filterable$set_filters()lgr::Appender$set_layout()lgr::Appender$set_threshold()lgr::AppenderFile$show()lgr::AppenderFileRotating$append()lgr::AppenderFileRotating$prune()lgr::AppenderFileRotating$set_backup_dir()lgr::AppenderFileRotating$set_compression()lgr::AppenderFileRotating$set_create_file()lgr::AppenderFileRotating$set_file()lgr::AppenderFileRotating$set_max_backups()lgr::AppenderFileRotating$set_size()lgr::AppenderFileRotatingTime$format()lgr::AppenderFileRotatingTime$rotate()lgr::AppenderFileRotatingTime$set_age()lgr::AppenderFileRotatingTime$set_cache_backups()lgr::AppenderFileRotatingTime$set_fmt()lgr::AppenderFileRotatingTime$set_overwrite()new()
AppenderFileRotatingDate$new( file, threshold = NA_integer_, layout = LayoutFormat$new(), filters = NULL, age = Inf, size = -1, max_backups = Inf, compression = FALSE, backup_dir = dirname(file), fmt = "%Y-%m-%d", overwrite = FALSE, cache_backups = TRUE, create_file = NULL )
size, age, max_backups, compression, backup_dir, fmt, overwrite, cache_backupssee rotor::rotate_date() for the meaning of these arguments. Note that
fmt corresponds to format (because $format has a special meaning
for R6 classes).
clone()
The objects of this class are cloneable with this method.
AppenderFileRotatingDate$clone(deep = FALSE)
deepWhether to make a deep clone.
AppenderFileRotatingTime, AppenderFileRotating, rotor::rotate()
Other Appenders:
Appender,
AppenderBuffer,
AppenderConsole,
AppenderFile,
AppenderFileRotating,
AppenderFileRotatingTime,
AppenderTable
Log to a time-stamped rotating file
Log to a time-stamped rotating file
An extension of AppenderFile that rotates logfiles based on certain
conditions. Please refer to the documentation of rotor::rotate_time() for
the meanings of the extra arguments
lgr::Filterable -> lgr::Appender -> lgr::AppenderFile -> lgr::AppenderFileRotating -> AppenderFileRotatingTime
cache_backupsTRUE or FALSE. If TRUE (the default) the list of backups is cached,
if FALSE it is read from disk every time this appender triggers.
Caching brings a significant speedup for checking whether to rotate or
not based on the age of the last backup, but is only safe if
there are no other programs/functions (except this appender) interacting
with the backups.
lgr::Filterable$add_filter()lgr::Filterable$filter()lgr::Filterable$remove_filter()lgr::Filterable$set_filters()lgr::Appender$set_layout()lgr::Appender$set_threshold()lgr::AppenderFile$show()lgr::AppenderFileRotating$append()lgr::AppenderFileRotating$prune()lgr::AppenderFileRotating$set_backup_dir()lgr::AppenderFileRotating$set_compression()lgr::AppenderFileRotating$set_create_file()lgr::AppenderFileRotating$set_file()lgr::AppenderFileRotating$set_max_backups()lgr::AppenderFileRotating$set_size()new()
AppenderFileRotatingTime$new( file, threshold = NA_integer_, layout = LayoutFormat$new(), filters = NULL, age = Inf, size = -1, max_backups = Inf, compression = FALSE, backup_dir = dirname(file), fmt = "%Y-%m-%d--%H-%M-%S", overwrite = FALSE, cache_backups = TRUE, create_file = NULL )
size, age, max_backups, compression, backup_dir, fmt, overwrite, cache_backupssee rotor::rotate_time() for the meaning of these arguments. Note that
fmt corresponds to format and backup_dir to dir.
rotate()
AppenderFileRotatingTime$rotate(force = FALSE, now = Sys.time())
set_age()
AppenderFileRotatingTime$set_age(x)
set_fmt()
AppenderFileRotatingTime$set_fmt(x)
set_overwrite()
AppenderFileRotatingTime$set_overwrite(x)
set_cache_backups()
set the cache_backups flag.
AppenderFileRotatingTime$set_cache_backups(x)
xa logical scalar
format()
AppenderFileRotatingTime$format(color = FALSE, ...)
clone()
The objects of this class are cloneable with this method.
AppenderFileRotatingTime$clone(deep = FALSE)
deepWhether to make a deep clone.
AppenderFileRotatingDate, AppenderFileRotating, rotor::rotate()
Other Appenders:
Appender,
AppenderBuffer,
AppenderConsole,
AppenderFile,
AppenderFileRotating,
AppenderFileRotatingDate,
AppenderTable
NOTE: This is an abstract class. Abstract classes cannot be instantiated directly, but are exported for package developers that want to extend lgr - for example by creating their own Appenders or Layouts. Please refer to the see also section for actual implementations of this class.
AppenderMemory is extended by Appenders that retain an in-memory event
buffer, such as AppenderBuffer and AppenderPushbullet from the
lgrExtra package.
lgr::Filterable -> lgr::Appender -> AppenderMemory
flush_on_exitA logical scalar. Should the buffer be flushed if
the Appender is destroyed (e.g. because the R session is terminated)?
flush_on_rotateA logical scalar. Should the buffer be flushed when it is
rotated because $buffer_size is exceeded?
should_flushA function with exactly one arguments: event.
$append() calls this function internally on the current LogEvent
and flushes the buffer if it evaluates to TRUE.
buffer_sizeinteger scalar >= 0. Maximum number of LogEvents
to buffer.
flush_thresholdA numeric or character threshold. LogEvents
with a log_level equal to or lower than this threshold trigger
flushing the buffer.
buffer_eventsA list of LogEvents. Contents of the buffer.
buffer_eventsA data.frame. Contents of the buffer converted
to a data.frame.
buffer_eventsA data.frame. Contents of the buffer converted
to a data.table.
new()
AppenderMemory$new(...)
append()
AppenderMemory$append(event)
flush()
Sends the buffer's contents to all attached Appenders and then clears the Buffer
AppenderMemory$flush()
clear()
Clears the buffer, discarding all buffered Events
AppenderMemory$clear()
set_buffer_size()
Set the maximum size of the buffer
AppenderMemory$set_buffer_size(x)
xan integer scalar >= 0. Number of LogEvents to buffer.
set_should_flush()
Set function that can trigger flushing the buffer
AppenderMemory$set_should_flush(x)
xA function with the single argument event. Setting x to
NULL is a shortcut for function(event) FALSE. See active bindings.
set_flush_on_exit()
Should the buffer be flushed when the Appender is destroyed?
AppenderMemory$set_flush_on_exit(x)
xA logical scalar. See active bindings.
set_flush_on_rotate()
Should the buffer be flushed if buffer_size is exceeded?
AppenderMemory$set_flush_on_rotate(x)
xA logical scalar. See active bindings.
set_flush_threshold()
Set threshold that triggers flushing
AppenderMemory$set_flush_threshold(level)
levelA numeric or character threshold. See
active bindings.
show()
Display the contents of the log table. Relies on the
$format_event method of the Layout attached to this Appender.
AppenderMemory$show(threshold = NA_integer_, n = 20L)
thresholdcharacter or integer scalar. The minimum log level
that should be displayed.
ninteger scalar. Show only the last n log entries that match
threshold.
format()
AppenderMemory$format(color = FALSE, ...)
Other abstract classes:
Appender,
AppenderTable,
Filterable
NOTE: This is an abstract class. Abstract classes cannot be instantiated directly, but are exported for package developers that want to extend lgr - for example by creating their own Appenders or Layouts. Please refer to the see also section for actual implementations of this class.
AppenderTable is extended by Appenders that write to a data
source that can be interpreted as tables, (usually a data.frame). Examples
are AppenderDbi, AppenderRjdbc and AppenderDt from the
lgrExtra package.
lgr::Filterable -> lgr::Appender -> AppenderTable
datacharacter scalar. Contents of the table, parsed to a
data.frame.
datacharacter scalar. Like $data, but returns a data.table
instead (requires the data.table package).
new()
AppenderTable$new(...)
show()
Show recent log entries
AppenderTable$show(threshold = NA_integer_, n = 20L)
thresholdan integer or character threshold.
Only show events with a log level at or below this threshold.
na positive integer scalar. Show at most that many entries
format()
AppenderTable$format(color = FALSE, ...)
Other abstract classes:
Appender,
AppenderMemory,
Filterable
Other Appenders:
Appender,
AppenderBuffer,
AppenderConsole,
AppenderFile,
AppenderFileRotating,
AppenderFileRotatingDate,
AppenderFileRotatingTime
Smartly coerce R objects that look like LogEvents to LogEvents. Mainly useful for developing Appenders.
as_LogEvent(x, ...) ## S3 method for class 'list' as_LogEvent(x, ...) ## S3 method for class 'data.frame' as_LogEvent(x, ...)as_LogEvent(x, ...) ## S3 method for class 'list' as_LogEvent(x, ...) ## S3 method for class 'data.frame' as_LogEvent(x, ...)
x |
any supported R object |
... |
currently ignored |
Note: as_LogEvent.data.frame() only supports single-row data.frames
a LogEvent
Other docs relevant for extending lgr:
LogEvent,
event_list(),
standardize_threshold()
Coerce LogEvents to data.frames, data.tables,
or tibbles.
## S3 method for class 'LogEvent' as.data.frame( x, row.names = NULL, optional = FALSE, stringsAsFactors = FALSE, ..., box_if = function(.) !(is.atomic(.) && identical(length(.), 1L)), cols_expand = NULL ) as.data.table.LogEvent( x, ..., box_if = function(.) !(is.atomic(.) && identical(length(.), 1L)), cols_expand = "msg" ) as_tibble.LogEvent( x, ..., box_if = function(.) !(is.atomic(.) && identical(length(.), 1L)), cols_expand = "msg" )## S3 method for class 'LogEvent' as.data.frame( x, row.names = NULL, optional = FALSE, stringsAsFactors = FALSE, ..., box_if = function(.) !(is.atomic(.) && identical(length(.), 1L)), cols_expand = NULL ) as.data.table.LogEvent( x, ..., box_if = function(.) !(is.atomic(.) && identical(length(.), 1L)), cols_expand = "msg" ) as_tibble.LogEvent( x, ..., box_if = function(.) !(is.atomic(.) && identical(length(.), 1L)), cols_expand = "msg" )
x |
any R object. |
row.names |
|
optional |
currently ignored and only included for compatibility. |
stringsAsFactors |
|
... |
passed on to |
box_if |
a |
cols_expand |
|
data.table::data.table, tibble::tibble
lg <- get_logger("test") lg$info("lorem ipsum") as.data.frame(lg$last_event) lg$info("LogEvents can store any custom log values", df = iris) as.data.frame(lg$last_event) head(as.data.frame(lg$last_event)$df[[1]]) # how boxing works # by default non-scalars are boxed lg$info("letters", letters = letters) as.data.frame(lg$last_event) # this behaviour can be modified by supplying a custom boxing function as.data.frame(lg$last_event, box_if = function(.) FALSE) as.data.frame(lg$last_event, cols_expand = "letters") # The `msg` argument of a log event is always vectorized lg$info(c("a vectorized", "log message")) as.data.frame(lg$last_event) lg$config(NULL)lg <- get_logger("test") lg$info("lorem ipsum") as.data.frame(lg$last_event) lg$info("LogEvents can store any custom log values", df = iris) as.data.frame(lg$last_event) head(as.data.frame(lg$last_event)$df[[1]]) # how boxing works # by default non-scalars are boxed lg$info("letters", letters = letters) as.data.frame(lg$last_event) # this behaviour can be modified by supplying a custom boxing function as.data.frame(lg$last_event, box_if = function(.) FALSE) as.data.frame(lg$last_event, cols_expand = "letters") # The `msg` argument of a log event is always vectorized lg$info(c("a vectorized", "log message")) as.data.frame(lg$last_event) lg$config(NULL)
A quick and easy way to configure the root logger. This is less powerful
then using lgr$config() or lgr$set_*() (see Logger), but reduces the
most common configurations to a single line of code.
basic_config( file = NULL, fmt = "%L [%t] %m", timestamp_fmt = "%Y-%m-%d %H:%M:%OS3", threshold = "info", appenders = NULL, console = if (is.null(appenders)) "all" else FALSE, console_fmt = "%L [%t] %m %f", console_timestamp_fmt = "%H:%M:%OS3", console_connection = NULL, memory = FALSE )basic_config( file = NULL, fmt = "%L [%t] %m", timestamp_fmt = "%Y-%m-%d %H:%M:%OS3", threshold = "info", appenders = NULL, console = if (is.null(appenders)) "all" else FALSE, console_fmt = "%L [%t] %m %f", console_timestamp_fmt = "%H:%M:%OS3", console_connection = NULL, memory = FALSE )
file |
|
fmt |
|
timestamp_fmt |
see |
threshold |
|
appenders |
a single Appender or a list thereof. |
console |
|
console_fmt |
|
console_timestamp_fmt |
|
console_connection |
see |
memory |
|
the root Logger (lgr)
# log to a file basic_config(file = tempfile()) unlink(lgr$appenders$file$file) # cleanup basic_config(file = tempfile(fileext = "jsonl")) unlink(lgr$appenders$file$file) # cleanup # log debug messages to a memory buffer basic_config(threshold = "all", memory = "all", console = "info") lgr$info("an info message") lgr$debug("a hidden message") show_log() # reset to default config basic_config()# log to a file basic_config(file = tempfile()) unlink(lgr$appenders$file$file) # cleanup basic_config(file = tempfile(fileext = "jsonl")) unlink(lgr$appenders$file$file) # cleanup # log debug messages to a memory buffer basic_config(threshold = "all", memory = "all", console = "info") lgr$info("an info message") lgr$debug("a hidden message") show_log() # reset to default config basic_config()
Logger Error Conditions
CannotInitializeAbstractClassError(class = parent.frame(2)[["classes"]])CannotInitializeAbstractClassError(class = parent.frame(2)[["classes"]])
class |
|
a condition object
Colorize Levels
colorize_levels( x, colors = getOption("lgr.colors", NULL), transform = identity )colorize_levels( x, colors = getOption("lgr.colors", NULL), transform = identity )
x |
|
colors |
A |
transform |
a |
a character vector wit color ANSI codes
Other formatting utils:
label_levels()
cat(colorize_levels(c(100, 200))) cat(colorize_levels(c("trace", "warn ", "DEBUG"))) cat(colorize_levels(c("trace", "warn ", "DEBUG"), transform = function(x) strtrim(x, 1) ))cat(colorize_levels(c(100, 200))) cat(colorize_levels(c("trace", "warn ", "DEBUG"))) cat(colorize_levels(c("trace", "warn ", "DEBUG"), transform = function(x) strtrim(x, 1) ))
Throws a timestamped warning instead of stopping the program. This is the default exception handler used by Loggers.
default_exception_handler(e)default_exception_handler(e)
e |
an |
The warning as character vector
tryCatch(stop("an error has occurred"), error = default_exception_handler)tryCatch(stop("an error has occurred"), error = default_exception_handler)
An event_list is a class for list()s whose only elements are LogEvents.
This structure is occasionally used internally in lgr (for example by
AppenderBuffer) and can be useful for developers that want to write
their own Appenders.
event_list(...) as_event_list(x, ...) ## S3 method for class 'list' as_event_list(x, ..., scalarize = FALSE) ## S3 method for class 'LogEvent' as_event_list(x, ..., scalarize = FALSE) ## S3 method for class 'data.frame' as_event_list(x, na.rm = TRUE, ...) as.data.table.event_list(x, na.rm = TRUE) ## S3 method for class 'event_list' as.data.frame( x, row.names = NULL, optional = FALSE, stringsAsFactors = FALSE, na.rm = TRUE, ... )event_list(...) as_event_list(x, ...) ## S3 method for class 'list' as_event_list(x, ..., scalarize = FALSE) ## S3 method for class 'LogEvent' as_event_list(x, ..., scalarize = FALSE) ## S3 method for class 'data.frame' as_event_list(x, na.rm = TRUE, ...) as.data.table.event_list(x, na.rm = TRUE) ## S3 method for class 'event_list' as.data.frame( x, row.names = NULL, optional = FALSE, stringsAsFactors = FALSE, na.rm = TRUE, ... )
... |
for |
x |
any |
scalarize |
|
na.rm |
remove |
row.names |
|
optional |
currently ignored and only included for compatibility. |
stringsAsFactors |
|
For convenience, as.data.frame() and as.data.table() methods
exist for event lists.
an event_list() and as_event_list() return a flat list
of LogEvents. Nested lists get automatically flattened.
as.data.frame and as.data.table return a data.frame or data.table
respectively
Other docs relevant for extending lgr:
LogEvent,
as_LogEvent(),
standardize_threshold()
e <- LogEvent$new(level = 300, msg = "a", logger = lgr) as_event_list(e) as_event_list(c(e, e)) # nested lists get automatically unnested as_event_list(c(e, list(nested_event = e))) # scalarize = TRUE "unpacks" events with vector log messages e <- LogEvent$new(level = 300, msg = c("A", "B"), logger = lgr) as_event_list(e, scalarize = FALSE) as_event_list(e, scalarize = TRUE)e <- LogEvent$new(level = 300, msg = "a", logger = lgr) as_event_list(e) as_event_list(c(e, e)) # nested lists get automatically unnested as_event_list(c(e, list(nested_event = e))) # scalarize = TRUE "unpacks" events with vector log messages e <- LogEvent$new(level = 300, msg = c("A", "B"), logger = lgr) as_event_list(e, scalarize = FALSE) as_event_list(e, scalarize = TRUE)
EventFilters specify arbitrarily complex logic for whether or
not a LogEvent should be processed by a Logger or Appender. They are
attached to Loggers/Appenders via their $set_filter() or $add_filter()
methods. If any EventFilter evaluates to FALSE for a given event, that
event is ignored - similarly to when it does not pass the objects'
threshold.
Usually you do not need to instantiate a formal EventFilter object as you
can just use any function that has the single argument event instead.
If you need to implement more complex filter logic - for example a filter
that is dependent on a dataset - it might be desirable to subclass
EventFilter, as R6::R6 objects can store data and functions together.
.obj() is a special function that can only be used within the
$filter() methods of EventFilters. It returns the Logger
or Appender that the EventFilter is attached to.
.obj().obj()
Since LogEvents are R6 objects with reference semantics, EventFilters can be
abused to modify events before passing them on. lgr comes with a few
preset filters that use this property: FilterInject (similar to
with_log_level()) and FilterForceLevel (similar to with_log_value()).
NOTE: The base class for Filters is called EventFilter so that it
doesn't conflict with base::Filter(). The recommended convention for
Filter subclasses is to call them FilterSomething and leave out the
Event prefix.
new()
Initialize a new EventFilter
EventFilter$new(fun = function(event) TRUE)
funa function with a single argument event that must return
either TRUE or FALSE. Any non-FALSE will be interpreted as
TRUE (= no filtering takes place) and a warning will be thrown.
clone()
The objects of this class are cloneable with this method.
EventFilter$clone(deep = FALSE)
deepWhether to make a deep clone.
lg <- get_logger("test") f <- function(event) { cat("via event$.logger:", event$.logger$threshold, "\n") # works for loggers only cat("via .obj(): ",.obj()$threshold, "\n") # works for loggers and appenders TRUE } lg$add_filter(f) lg$fatal("test") lg$config(NULL)lg <- get_logger("test") f <- function(event) { cat("via event$.logger:", event$.logger$threshold, "\n") # works for loggers only cat("via .obj(): ",.obj()$threshold, "\n") # works for loggers and appenders TRUE } lg$add_filter(f) lg$fatal("test") lg$config(NULL)
Superclass for classes that have a $filter() method such as
Appenders and Loggers. See EventFilter for details.
NOTE: This is an abstract class. Abstract classes cannot be instantiated directly, but are exported for package developers that want to extend lgr - for example by creating their own Appenders or Layouts. Please refer to the see also section for actual implementations of this class.
filtersa list of all attached Filters.
filter()
Determine whether the LogEvent x should be passed on to
Appenders (TRUE) or not (FALSE). See also the active binding
filters.
Filterable$filter(event)
eventa LogEvent
add_filter()
Attach a filter
Filterable$add_filter(filter, name = NULL)
filter a function with the single argument event that returns TRUE
or FALSE;
an EventFilter R6::R6 object; or
any R object with a $filter() method.
If a Filter returns a non-FALSE value, will be interpreted as TRUE
(= no filtering takes place) and a warning will be thrown.
namecharacter scalar or NULL. An optional
name which makes it easier to access (or remove) the filter
remove_filter()
Remove a filter
Filterable$remove_filter(pos)
poscharacter or integer scalar. The name or index of the
Filter to be removed.
set_filters()
Set or replace (all) Filters of parent object. See EventFilter for how Filters work.
Filterable$set_filters(filters)
filtersa list (named or unnamed) of EventFilters
or predicate functions. See is_filter().
Other abstract classes:
Appender,
AppenderMemory,
AppenderTable
Overrides the log level of the Appender/Logger that this filter
is attached to to with level. See also with_log_level(). It is
recommended to use filters that modify LogEvents only with Loggers, but
they will also work with Appenders.
lgr::EventFilter -> FilterForceLevel
new()
Initialize a new FilterForceLevel
FilterForceLevel$new(level)
levelan integer or character log level
clone()
The objects of this class are cloneable with this method.
FilterForceLevel$clone(deep = FALSE)
deepWhether to make a deep clone.
lg <- get_logger("test") analyse <- function(){ lg$add_filter(FilterForceLevel$new("info"), "force") on.exit(lg$remove_filter("force")) lg$error("an error with forced log level INFO") } analyse() lg$error("an normal error") lg$config(NULL) # reset configlg <- get_logger("test") analyse <- function(){ lg$add_filter(FilterForceLevel$new("info"), "force") on.exit(lg$remove_filter("force")) lg$error("an error with forced log level INFO") } analyse() lg$error("an normal error") lg$config(NULL) # reset config
Inject arbitrary values into all LogEvents processed by a Logger/Appender. It is recommended to use filters that modify LogEvents only with Loggers, but they will also work with Appenders.
lgr::EventFilter -> FilterInject
valuesa named list of values to be injected into each
LogEvent processed by this filter
new()
Initialize a new FilterInject
FilterInject$new(..., .list = list())
..., .listany number of named R objects that will be injected as
custom fields into all LogEvents processed by the
Appender/Logger that this filter is attached to. See also
with_log_value().
clone()
The objects of this class are cloneable with this method.
FilterInject$clone(deep = FALSE)
deepWhether to make a deep clone.
lg <- get_logger("test") analyse <- function(){ lg$add_filter(FilterInject$new(type = "analysis"), "inject") on.exit(lg$remove_filter("inject")) lg$error("an error with forced custom 'type'-field") } analyse() lg$error("an normal error") lg$config(NULL) # reset configlg <- get_logger("test") analyse <- function(){ lg$add_filter(FilterInject$new(type = "analysis"), "inject") on.exit(lg$remove_filter("inject")) lg$error("an error with forced custom 'type'-field") } analyse() lg$error("an normal error") lg$config(NULL) # reset config
get_caller() Tries to determine the calling functions based on where.
get_caller(where = -1L) get_user(fallback = "unknown user")get_caller(where = -1L) get_user(fallback = "unknown user")
where |
|
fallback |
A fallback in case the user name could not be determined |
a character scalar.
foo <- function() get_caller(-1L) foo() get_user()foo <- function() get_caller(-1L) foo() get_user()
Display, add and remove character labels for log levels.
get_log_levels() add_log_levels(levels) remove_log_levels(level_names)get_log_levels() add_log_levels(levels) remove_log_levels(level_names)
levels |
a named |
level_names |
a |
a named character vector of the globally available log levels
(add_log_levels() and remove_log_levels() return invisibly).
lgr comes with the following predefined log levels that are identical to the log levels of log4j.
| Level | Name | Description |
0 |
off | A log level of 0/off tells a Logger or Appender to suspend all logging |
100 |
fatal | Critical error that leads to program abort. Should always indicate a stop() or similar |
200 |
error | A severe error that does not trigger program abort |
300 |
warn | A potentially harmful situation, like warning()
|
400 |
info | An informational message on the progress of the application |
500 |
debug | Finer grained informational messages that are mostly useful for debugging |
600 |
trace | An even finer grained message than debug |
NA |
all | A log level of NA/all tells a Logger or Appender to process all log events |
get_log_levels() add_log_levels(c(errorish = 250)) get_log_levels() remove_log_levels("errorish") get_log_levels()get_log_levels() add_log_levels(c(errorish = 250)) get_log_levels() remove_log_levels("errorish") get_log_levels()
Get/Create a Logger
get_logger(name, class = Logger, reset = FALSE) get_logger_glue(name)get_logger(name, class = Logger, reset = FALSE) get_logger_glue(name)
name |
a |
class |
An R6ClassGenerator object. Usually |
reset |
a |
a Logger
lg <- get_logger("log/ger/test") # equivalent to lg <- get_logger(c("log", "ger", "test")) lg$warn("a %s message", "warning") lg lg$parent if (requireNamespace('glue')){ lg <- get_logger_glue("log/ger") } lg$warn("a {.text} message", .text = "warning") # completely reset 'glue' to an unconfigured vanilla Logger get_logger("log/ger", reset = TRUE) # WARNING: this invalidates existing references to the Logger try(lg$info("lg has been invalidated an no longer works")) lg <- get_logger("log/ger") lg$info("now all is well again")lg <- get_logger("log/ger/test") # equivalent to lg <- get_logger(c("log", "ger", "test")) lg$warn("a %s message", "warning") lg lg$parent if (requireNamespace('glue')){ lg <- get_logger_glue("log/ger") } lg$warn("a {.text} message", .text = "warning") # completely reset 'glue' to an unconfigured vanilla Logger get_logger("log/ger", reset = TRUE) # WARNING: this invalidates existing references to the Logger try(lg$info("lg has been invalidated an no longer works")) lg <- get_logger("log/ger") lg$info("now all is well again")
Returns TRUE for any R object that can be used as a Filter
for Loggers or, Appenders:
a function with the single argument event;
an EventFilter R6::R6 object; or
any object with a $filter(event) method.
Note: A Filter must return a scalar TRUE or FALSE, but this
property cannot be checked by is_filter().
is_filter(x)is_filter(x)
x |
any R Object |
TRUE or FALSE
Label/Unlabel Log Levels
label_levels(levels, log_levels = getOption("lgr.log_levels")) unlabel_levels(labels, log_levels = getOption("lgr.log_levels"))label_levels(levels, log_levels = getOption("lgr.log_levels")) unlabel_levels(labels, log_levels = getOption("lgr.log_levels"))
levels |
an |
log_levels |
named |
labels |
a |
a character vector for label_levels() and an integer vector for
unlabel_levels
Other formatting utils:
colorize_levels()
x <- label_levels(c(seq(0, 600, by = 100), NA)) print(x) unlabel_levels(x)x <- label_levels(c(seq(0, 600, by = 100), NA)) print(x) unlabel_levels(x)
Abstract Class for Layouts
Abstract Class for Layouts
Appenders pass LogEvents to a Layout which formats it for
output. For the Layouts included in lgr that means turning the LogEvent
into a character string.
For each Appender exist one more more possible Layouts, but not every Layout
will work with every Appender. See the package lgrExtra for examples
for Layouts that return different data types (such as data.frames) and
Appenders that can handle them.
Layouts may have an additional $read(file, threshold, n) method that returns
a character vector, and/or an $parse(file) method that
returns a data.frame. These can be used by Appenders to $show() methods
and $data active bindings respectively (see source code of AppenderFile).
excluded_fieldsfields to exclude from the final log
format_event()
Format a log event
Function that the Layout uses to transform a LogEvent into something that an Appender can write to an output destination.
Layout$format_event(event)
eventa LogEvent
toString()
Layout$toString()
set_excluded_fields()
Layout$set_excluded_fields(x)
clone()
The objects of this class are cloneable with this method.
Layout$clone(deep = FALSE)
deepWhether to make a deep clone.
Other Layouts:
LayoutFormat,
LayoutGlue,
LayoutJson
Format Log Events as Text
Format Log Events as Text
Format a LogEvent as human readable text using format.LogEvent(), which
provides a quick and easy way to customize log messages. If you need
more control and flexibility, consider using LayoutGlue instead.
see Fields
see Fields
see Fields
see Fields
Convert Layout to a character string
Read a log file written using LayoutFormat
This is the same list of format tokens as for format.LogEvent()
%tThe timestamp of the message, formatted according to
timestamp_fmt)
%lthe log level, lowercase character representation
%Lthe log level, uppercase character representation
%kthe log level, first letter of lowercase character representation
%Kthe log level, first letter of uppercase character representation
%nthe log level, integer representation
%gthe name of the logger
%pthe PID (process ID). Useful when logging code that uses multiple threads.
%cthe calling function
%mthe log message
%rthe raw log message (without string interpolation)
%fall custom fields of x in a pseudo-JSON like format that is
optimized for human readability and console output
%jall custom fields of x in proper JSON. This requires that you
have jsonlite installed and does not support colors as opposed to
%f
lgr::Layout -> LayoutFormat
fmta character scalar containing format tokens. See format.LogEvent().
timestamp_fmta character scalar. See base::format.POSIXct().
colorsa named list of functions (like the ones provided by
the package crayon) passed on on format.LogEvent().
pad_levels"right", "left" or NULL. See format.LogEvent().
new()
LayoutFormat$new( fmt = "%L [%t] %m %j", timestamp_fmt = "%Y-%m-%d %H:%M:%OS3", colors = NULL, pad_levels = "right", excluded_fields = NULL )
format_event()
Format a LogEvent
LayoutFormat$format_event(event)
eventa LogEvent
set_fmt()
LayoutFormat$set_fmt(x)
set_timestamp_fmt()
LayoutFormat$set_timestamp_fmt(x)
set_colors()
LayoutFormat$set_colors(x)
set_pad_levels()
LayoutFormat$set_pad_levels(x)
toString()
LayoutFormat$toString()
read()
LayoutFormat$read(file, threshold = NA_integer_, n = 20L)
thresholda character or integer threshold
nnumber of log entries to display
clone()
The objects of this class are cloneable with this method.
LayoutFormat$clone(deep = FALSE)
deepWhether to make a deep clone.
Other Layouts:
Layout,
LayoutGlue,
LayoutJson
# setup a dummy LogEvent event <- LogEvent$new( logger = Logger$new("dummy logger"), level = 200, timestamp = Sys.time(), caller = NA_character_, msg = "a test message" ) lo <- LayoutFormat$new() lo$format_event(event)# setup a dummy LogEvent event <- LogEvent$new( logger = Logger$new("dummy logger"), level = 200, timestamp = Sys.time(), caller = NA_character_, msg = "a test message" ) lo <- LayoutFormat$new() lo$format_event(event)
Format a LogEvent as human readable text using glue::glue. The function is evaluated in an environment in which it has access to all elements of the LogEvent (see examples). This is more flexible than LayoutFormat, but also more complex and slightly less performant.
lgr::Layout -> LayoutGlue
fmtA string that will be interpreted by glue::glue()
new()
LayoutGlue$new(
fmt = "{pad_right(colorize_levels(toupper(level_name)), 5)} [{timestamp}] {msg}"
)format_event()
LayoutGlue$format_event(event)
set_fmt()
LayoutGlue$set_fmt(x)
set_colors()
LayoutGlue$set_colors(x)
toString()
LayoutGlue$toString()
clone()
The objects of this class are cloneable with this method.
LayoutGlue$clone(deep = FALSE)
deepWhether to make a deep clone.
lgr exports a number of formatting utility functions that are
useful for layout glue: colorize_levels(), pad_left(), pad_right().
Other Layouts:
Layout,
LayoutFormat,
LayoutJson
lg <- get_logger("test")$ set_appenders(AppenderConsole$new())$ set_propagate(FALSE) lg$appenders[[1]]$set_layout(LayoutGlue$new()) lg$fatal("test") # All fields of the LogEvent are available, even custom ones lg$appenders[[1]]$layout$set_fmt( "{logger} {level_name}({level}) {caller}: {toupper(msg)} {{custom: {custom}}}" ) lg$fatal("test", custom = "foobar") lg$config(NULL) # reset logger configlg <- get_logger("test")$ set_appenders(AppenderConsole$new())$ set_propagate(FALSE) lg$appenders[[1]]$set_layout(LayoutGlue$new()) lg$fatal("test") # All fields of the LogEvent are available, even custom ones lg$appenders[[1]]$layout$set_fmt( "{logger} {level_name}({level}) {caller}: {toupper(msg)} {{custom: {custom}}}" ) lg$fatal("test", custom = "foobar") lg$config(NULL) # reset logger config
A format for formatting LogEvents as jsonlines log files. This provides a nice balance between human- an machine-readability.
lgr::Layout -> LayoutJson
toJSON_argsa list
timestamp_fmta character scalar or a function that accepts a POSIXct
as its single argument
transform_eventa function that accepts a LogEvent as its single argument
transform_event_namesa named character vector or a function that accepts a
character vector of field names as its single argument.
new()
Creates a new instance of this R6 class.
LayoutJson$new( toJSON_args = list(auto_unbox = TRUE), timestamp_fmt = NULL, transform_event = function(event) event[["values"]], transform_event_names = NULL, excluded_fields = "rawMsg" )
toJSON_argsa list of arguments passed to jsonlite::toJSON(),
timestamp_fmtFormat to be applied to the timestamp. This is
applied after transform_event but before transform_event_names
NULL: formatting of the timestamp is left to jsonlite::toJSON(),
a character scalar as for format.POSIXct(), or
a function that returns a vector of the same length as its
(POSIXct) input. The returned vector can be of any type
supported by jsonlite::toJSON().
transform_eventa function with a single argument that
takes a LogEvent object and returns a list of values.
transform_event_namesNULL: don't process names
a named character vector of the format new_name = old_name
or a function with a single mandatory argument that accepts a
character vector of field names. Applied after transform_event.
excluded_fieldsA character vector of field names to exclude
from the final output. Applied after transform_event_names.
format_event()
LayoutJson$format_event(event)
set_toJSON_args()
LayoutJson$set_toJSON_args(x)
xa list
set_timestamp_fmt()
LayoutJson$set_timestamp_fmt(x)
xa character scalar or a function that accepts a POSIXct
as its single argument
set_transform_event()
LayoutJson$set_transform_event(x)
xa function that accepts a LogEvent as its single argument
set_transform_event_names()
LayoutJson$set_transform_event_names(x)
xa named character vector or a function that accepts a
character vector of field names as its single argument.
toString()
Represent the LayoutJson class as a string
LayoutJson$toString()
parse()
Read and parse file written using this Layout
This can be used by the $data active binding of an Appender
LayoutJson$parse(file)
filecharacter scalar: path to a file
read()
Read a file written using this Layout (without parsing)
This can be used by the $show() method of an Appender
LayoutJson$read(file, threshold = NA_integer_, n = 20L)
filecharacter scalar: path to a file
thresholdcharacter Minimum log level to show. Requires parsing
of the log file (but will still display unparsed output)
ninteger number of lines to show
clone()
The objects of this class are cloneable with this method.
LayoutJson$clone(deep = FALSE)
deepWhether to make a deep clone.
read_json_lines(), https://jsonlines.org/
Other Layouts:
Layout,
LayoutFormat,
LayoutGlue
# setup a dummy LogEvent event <- LogEvent$new( logger = Logger$new("dummy logger"), level = 200, timestamp = Sys.time(), caller = NA_character_, msg = "a test message", custom_field = "LayoutJson can handle arbitrary fields" ) lo <- LayoutJson$new() lo$format_event(event) lo <- LayoutJson$new( transform_event_names = toupper, excluded_fields = c("RAWMSG", "CALLER")) lo$format_event(event) lo <- LayoutJson$new( transform_event = function(e) { values <- e$values values$msg <- toupper(values$msg) values }, timestamp_fmt = "%a %b %d %H:%M:%S %Y", excluded_fields = c("RAWMSG", "CALLER")) lo$format_event(event)# setup a dummy LogEvent event <- LogEvent$new( logger = Logger$new("dummy logger"), level = 200, timestamp = Sys.time(), caller = NA_character_, msg = "a test message", custom_field = "LayoutJson can handle arbitrary fields" ) lo <- LayoutJson$new() lo$format_event(event) lo <- LayoutJson$new( transform_event_names = toupper, excluded_fields = c("RAWMSG", "CALLER")) lo$format_event(event) lo <- LayoutJson$new( transform_event = function(e) { values <- e$values values$msg <- toupper(values$msg) values }, timestamp_fmt = "%a %b %d %H:%M:%S %Y", excluded_fields = c("RAWMSG", "CALLER")) lo$format_event(event)
A LogEvent is a single unit of data that should be logged. LogEvents are
usually created by a Logger, and then processed by one more Appenders.
They do not need to be instantiated manually except for testing and
experimentation; however, if you plan on writing your own Appenders or
Layouts you need to understand LogEvents.
levelinteger. The log_level / priority of the LogEvent. Use the
active binding level_name to get the character representation
instead.
timestampPOSIXct. The time when then the
LogEvent was created.
callercharacter. The name of the calling function.
msgcharacter. The log message.
.loggerLogger. A reference to the Logger that created the
event (equivalent to get_logger(event$logger)).
rawMsgcharacter. The raw log message without string
interpolation.
valueslist. All values stored in the LogEvent, including
all custom fields, but not including event$.logger.
level_namecharacter. The log_level / priority of the LogEvent labelled
according to getOption("lgr.log_levels")
loggercharacter scalar. The name of the Logger that
created this event, equivalent to event$.logger$name)
new()
The arguments to LogEvent$new() directly translate to the fields stored
in the LogEvent. Usually these values will be scalars, but (except for
"logger") they can also be vectors if they are all of the same length (or
scalars that will be recycled). In this case the event will be treated by
the Appenders and Layouts as if several separate events.
LogEvent$new( logger, level = 400, timestamp = Sys.time(), caller = NA, msg = NA, rawMsg = msg, ... )
logger, level, timestamp, caller, msgsee Public fields.
...All named arguments in ... will be added to the LogEvent
as custom fields. You can store arbitrary R objects in LogEvents
this way, but not all Appenders will support them. See AppenderJson for
clone()
The objects of this class are cloneable with this method.
LogEvent$clone(deep = FALSE)
deepWhether to make a deep clone.
Other docs relevant for extending lgr:
as_LogEvent(),
event_list(),
standardize_threshold()
lg <- get_logger("test") lg$error("foo bar") # The last LogEvent produced by a Logger is stored in its `last_event` field lg$last_event # formatted console output lg$last_event$values # values stored in the event # Also contains the Logger that created it as .logger lg$last_event$logger # equivalent to lg$last_event$.logger$name # This is really a reference to the complete Logger, so the following is # possible (though nonsensical) lg$last_event$.logger$last_event$msg identical(lg, lg$last_event$.logger) lg$config(NULL) # reset logger configlg <- get_logger("test") lg$error("foo bar") # The last LogEvent produced by a Logger is stored in its `last_event` field lg$last_event # formatted console output lg$last_event$values # values stored in the event # Also contains the Logger that created it as .logger lg$last_event$logger # equivalent to lg$last_event$.logger$name # This is really a reference to the complete Logger, so the following is # possible (though nonsensical) lg$last_event$.logger$last_event$msg identical(lg, lg$last_event$.logger) lg$config(NULL) # reset logger config
A Logger produces a LogEvent that contains a log message along with
metadata (timestamp, calling function, ...) and dispatches it to one or
more Appenders which are responsible for the output (console, file, ...)
of the event. lgr comes with a single pre-configured Logger called the
root Logger that can be accessed via lgr$<...>. Instantiation of new
Loggers is done with get_logger(). It is advisable to instantiate a
separate Logger with a descriptive name for each package/script in which
you use lgr.
lgr::Filterable -> Logger
nameA character scalar. The unique name of each logger,
which also includes the names of its ancestors (separated by /).
thresholdinteger scalar. The threshold of the Logger, or if it
NULL the threshold it inherits from its closest ancestor with a
non-NULL threshold
propagateA TRUE or FALSE. Should a Logger propagate events
to the Appenders of its ancestors?
ancestryA named logical vector of containing the propagate value
of each Logger upper the inheritance tree. The names are the names of
the appenders. ancestry is an S3 class with a custom
format()/print() method, so if you want to use the plain logical
vector use unclass(lg$ancestry)
parenta Logger. The direct ancestor of the Logger.
last_eventThe last LogEvent produced by the current Logger
appendersa list of all Appenders of the Logger
inherited_appendersA list of all appenders that the Logger
inherits from its ancestors
exception_handlera function. See $set_exception_handler and
$handle_exception
new()
Loggers should never be instantiated directly with Logger$new() but
rather via get_logger("name"). This way new Loggers are
registered in a global namespace which ensures uniqueness and
facilitates inheritance between Loggers. If "name" does not exist, a
new Logger with that name will be created, otherwise the function returns
a Reference to the existing Logger.
name is potentially a "/" separated hierarchical value like
foo/bar/baz. Loggers further down the hierarchy are descendants of the
loggers above and (by default) inherit threshold and Appenders from
their ancestors.
Logger$new( name = "(unnamed logger)", appenders = list(), threshold = NULL, filters = list(), exception_handler = default_exception_handler, propagate = TRUE, replace_empty = "<NULL>" )
name, appenders, threshold, filters, exception_handler, propagateSee section Active bindings.
log()
Log an event.
If level passes the Logger's threshold a new LogEvent with level,
msg, timestamp and caller is created. If the new LogEvent also
passes the Loggers Filters, it is be dispatched to the
relevant Appenders.
Logger$log(level, msg, ..., timestamp = Sys.time(), caller = get_caller(-7))
levela character or integer scalar. See log_levels.
msgcharacter. A log message. If unnamed arguments are supplied
in ..., msg is passed on to base::sprintf() (which means "%" have
to be escaped), otherwise msg is left as-is.
...unnamed arguments in ... must be character scalars and
are passed to base::sprintf(). Named arguments must have unique names
but can be arbitrary R objects that are passed to LogEvent$new() and
will be turned into custom fields.
timestampPOSIXct. Timestamp of the event.
callera character scalar. The name of the calling function.
fatal()
Log an Event fatal priority
Logger$fatal(msg, ..., caller = get_caller(-8L))
msg, ..., callersee $log()
error()
Log an Event error priority
Logger$error(msg, ..., caller = get_caller(-8L))
msg, ..., callersee $log()
warn()
Log an Event warn priority
Logger$warn(msg, ..., caller = get_caller(-8L))
msg, ..., callersee $log()
info()
Log an Event info priority
Logger$info(msg, ..., caller = get_caller(-8L))
msg, ..., callersee $log()
debug()
Log an Event debug priority
Logger$debug(msg, ..., caller = get_caller(-8L))
msg, ..., callersee $log()
trace()
Log an Event trace priority
Logger$trace(msg, ..., caller = get_caller(-8L))
msg, ..., callersee $log()
list_log()
list_log() is a shortcut for do.call(Logger$log, x).
See https://github.com/s-fleck/joblog for an R package that
leverages this feature to create custom log event types for tracking
the status of cron jobs.
Logger$list_log(x)
xa named list that must at least contain the named elements
level and timestamp
lg <- get_logger("test")
lg$list_log(list(level = 400, msg = "example"))
config()
Load a Logger configuration.
Logger$config(cfg, file, text, list)
cfg a special list object with any or all of the the following elements:
appenders, threshold, filters, propagate, exception_handler,
the path to a YAML/JSON config file,
a character scalar containing YAML/JSON,
NULL (to reset the logger config to the default/unconfigured state)
file, text, listcan be used as an alternative to
cfg that enforces that the supplied argument is of the specified
type. See logger_config for details.
add_appender()
Add an Appender to the Logger
Logger$add_appender(appender, name = NULL)
appendera single Appender
namea character scalar. Optional but recommended.
lg <- get_logger("test")
lg$add_appender(AppenderConsole$new(), name = "myconsole")
lg$appenders[[1]]
lg$appenders$myconsole
lg$remove_appender("myconsole")
lg$config(NULL) # reset config
remove_appender()
remove an appender
Logger$remove_appender(pos)
posinteger index or character name of the Appender(s) to
remove
handle_exception()
To prevent errors in the logging logic from crashing the whole script,
Loggers pass errors they encounter to an exception handler. The default
behaviour is to demote errors to warnings. See also
set_exception_handler().
Logger$handle_exception(expr)
exprexpression to be evaluated.
set_exception_handler()
Set the exception handler of a logger
Logger$set_exception_handler(fun)
funa function with the single argument e (an error condition)
lgr$info(stop("this produces a warning instead of an error"))
set_propagate()
Should a Logger propagate events to the Appenders of its ancestors?
Logger$set_propagate(x)
xTRUE or FALSE. Should LogEvents be passed on to the appenders
of the ancestral Loggers?
set_threshold()
Set the minimum log level of events that a Logger should process
Logger$set_threshold(level)
levelcharacter or integer scalar. The minimum
log level that triggers this Logger
set_appenders()
Set the Logger's Appenders
Logger$set_appenders(x)
xsingle Appender or a list thereof. Appenders control the
output of a Logger. Be aware that a Logger also inherits the Appenders
of its ancestors (see vignette("lgr", package = "lgr") for more info
about Logger inheritance).
set_replace_empty()
Set the replacement for empty values (NULL or empty
vectors)
Logger$set_replace_empty(x)
xshould be a character vector, but other types of values are
supported. use wisely.
spawn()
Spawn a child Logger.
This is very similar to using get_logger(), but
can be useful in some cases where Loggers are created programmatically
Logger$spawn(name)
namecharacter vector. Name of the child logger
get_logger("foo/bar")$spawn("baz") is equivalent
to get_logger("foo/bar/baz")
If you are a package developer you should define a new Logger for each package, but you do not need to configure it. The user of the package should decide how and where to output logging, usually by configuring the root Logger (new Appenders added/removed, Layouts modified, etc...).
# lgr::lgr is the root logger that is always available lgr$info("Today is a good day") lgr$fatal("This is a serious error") # Loggers use sprintf() for string formatting by default lgr$info("Today is %s", Sys.Date() ) # If no unnamed `...` are present, msg is not passed through sprintf() lgr$fatal("100% bad") # so this works lgr$fatal("%s%% bad", 100) # if you use unnamed arguments, you must escape % # You can create new loggers with get_logger() tf <- tempfile() lg <- get_logger("mylogger")$set_appenders(AppenderFile$new(tf)) # The new logger passes the log message on to the appenders of its parent # logger, which is by default the root logger. This is why the following # writes not only the file 'tf', but also to the console. lg$fatal("blubb") readLines(tf) # This logger's print() method depicts this relationship. child <- get_logger("lg/child") print(child) print(child$name) # use formatting strings and custom fields tf2 <- tempfile() lg$add_appender(AppenderFile$new(tf2, layout = LayoutJson$new())) lg$info("Not all %s support custom fields", "appenders", type = "test") cat(readLines(tf), sep = "\n") cat(readLines(tf2), sep = "\n") # cleanup unlink(c(tf, tf2)) lg$config(NULL) # reset logger config # LoggerGlue # You can also create a new logger that uses the awesome glue library for # string formatting instead of sprintf if (requireNamespace("glue")){ lg <- get_logger_glue("glue") lg$fatal("blah ", "fizz is set to: {fizz}", foo = "bar", fizz = "buzz") # prevent creation of custom fields with prefixing a dot lg$fatal("blah ", "fizz is set to: {.fizz}", foo = "bar", .fizz = "buzz") #' # completely reset 'glue' to an unconfigured vanilla Logger get_logger("glue", reset = TRUE) } # Configuring a Logger lg <- get_logger("test") lg$config(NULL) # resets logger to unconfigured state # With setters lg$ set_threshold("error")$ set_propagate(FALSE)$ set_appenders(AppenderConsole$new(threshold = "info")) lg$config(NULL) # With a list lg$config(list( threshold = "error", propagate = FALSE, appenders = list(AppenderConsole$new(threshold = "info")) )) lg$config(NULL) # resets logger to unconfigured state # Via YAML cfg <- " Logger: threshold: error propagate: false appenders: AppenderConsole: threshold: info " lg$config(cfg) lg$config(NULL) ## ------------------------------------------------ ## Method `Logger$list_log` ## ------------------------------------------------ lg <- get_logger("test") lg$list_log(list(level = 400, msg = "example")) ## ------------------------------------------------ ## Method `Logger$add_appender` ## ------------------------------------------------ lg <- get_logger("test") lg$add_appender(AppenderConsole$new(), name = "myconsole") lg$appenders[[1]] lg$appenders$myconsole lg$remove_appender("myconsole") lg$config(NULL) # reset config ## ------------------------------------------------ ## Method `Logger$set_exception_handler` ## ------------------------------------------------ lgr$info(stop("this produces a warning instead of an error"))# lgr::lgr is the root logger that is always available lgr$info("Today is a good day") lgr$fatal("This is a serious error") # Loggers use sprintf() for string formatting by default lgr$info("Today is %s", Sys.Date() ) # If no unnamed `...` are present, msg is not passed through sprintf() lgr$fatal("100% bad") # so this works lgr$fatal("%s%% bad", 100) # if you use unnamed arguments, you must escape % # You can create new loggers with get_logger() tf <- tempfile() lg <- get_logger("mylogger")$set_appenders(AppenderFile$new(tf)) # The new logger passes the log message on to the appenders of its parent # logger, which is by default the root logger. This is why the following # writes not only the file 'tf', but also to the console. lg$fatal("blubb") readLines(tf) # This logger's print() method depicts this relationship. child <- get_logger("lg/child") print(child) print(child$name) # use formatting strings and custom fields tf2 <- tempfile() lg$add_appender(AppenderFile$new(tf2, layout = LayoutJson$new())) lg$info("Not all %s support custom fields", "appenders", type = "test") cat(readLines(tf), sep = "\n") cat(readLines(tf2), sep = "\n") # cleanup unlink(c(tf, tf2)) lg$config(NULL) # reset logger config # LoggerGlue # You can also create a new logger that uses the awesome glue library for # string formatting instead of sprintf if (requireNamespace("glue")){ lg <- get_logger_glue("glue") lg$fatal("blah ", "fizz is set to: {fizz}", foo = "bar", fizz = "buzz") # prevent creation of custom fields with prefixing a dot lg$fatal("blah ", "fizz is set to: {.fizz}", foo = "bar", .fizz = "buzz") #' # completely reset 'glue' to an unconfigured vanilla Logger get_logger("glue", reset = TRUE) } # Configuring a Logger lg <- get_logger("test") lg$config(NULL) # resets logger to unconfigured state # With setters lg$ set_threshold("error")$ set_propagate(FALSE)$ set_appenders(AppenderConsole$new(threshold = "info")) lg$config(NULL) # With a list lg$config(list( threshold = "error", propagate = FALSE, appenders = list(AppenderConsole$new(threshold = "info")) )) lg$config(NULL) # resets logger to unconfigured state # Via YAML cfg <- " Logger: threshold: error propagate: false appenders: AppenderConsole: threshold: info " lg$config(cfg) lg$config(NULL) ## ------------------------------------------------ ## Method `Logger$list_log` ## ------------------------------------------------ lg <- get_logger("test") lg$list_log(list(level = 400, msg = "example")) ## ------------------------------------------------ ## Method `Logger$add_appender` ## ------------------------------------------------ lg <- get_logger("test") lg$add_appender(AppenderConsole$new(), name = "myconsole") lg$appenders[[1]] lg$appenders$myconsole lg$remove_appender("myconsole") lg$config(NULL) # reset config ## ------------------------------------------------ ## Method `Logger$set_exception_handler` ## ------------------------------------------------ lgr$info(stop("this produces a warning instead of an error"))
logger_config() is an S3 constructor for logger_config objects
that can be passed to the $config method of a Logger. You
can just pass a normal list instead, but using this constructor is
a more formal way that includes additional argument checking.
logger_config( appenders = NULL, threshold = NULL, filters = NULL, exception_handler = NULL, propagate = TRUE ) as_logger_config(x) ## S3 method for class 'list' as_logger_config(x) ## S3 method for class 'character' as_logger_config(x)logger_config( appenders = NULL, threshold = NULL, filters = NULL, exception_handler = NULL, propagate = TRUE ) as_logger_config(x) ## S3 method for class 'list' as_logger_config(x) ## S3 method for class 'character' as_logger_config(x)
appenders |
see Logger |
threshold |
see Logger |
filters |
see Logger |
exception_handler |
see Logger |
propagate |
see Logger |
x |
any R object. Especially:
|
a list with the subclass "logger_config"
a logger_config object
Return a data.frame of all registered loggers
logger_index()logger_index()
a logger_index data.frame
logger_tree() for a more visual representation of registered
loggers
get_logger("tree/leaf") get_logger("shrub/leaf") get_logger("plant/shrub/leaf") logger_index()get_logger("tree/leaf") get_logger("shrub/leaf") get_logger("plant/shrub/leaf") logger_index()
Displays a tree structure of all registered Loggers.
logger_tree()logger_tree()
data.frame with subclass "logger_tree"
unconfigured Loggers are displayed in gray (if your terminal supports colors and you have the package crayon installed).
If a logger's threshold is set, it is displayed in square brackets next
to its name (reminder: if the threshold is not set, it is inherited from
next logger up the logger tree).
If a logger's propagate field is set to FALSE an red hash (#) sign
is displayed in front of the logger name, to imply that it does not pass
LogEvents up the tree.
logger_index() for a tidy data.frame representation of
all registered loggers
get_logger("fancymodel") get_logger("fancymodel/shiny")$ set_propagate(FALSE) get_logger("fancymodel/shiny/ui")$ set_appenders(AppenderConsole$new()) get_logger("fancymodel/shiny/server")$ set_appenders(list(AppenderConsole$new(), AppenderConsole$new()))$ set_threshold("trace") get_logger("fancymodel/plumber") if (requireNamespace("cli")){ print(logger_tree()) }get_logger("fancymodel") get_logger("fancymodel/shiny")$ set_propagate(FALSE) get_logger("fancymodel/shiny/ui")$ set_appenders(AppenderConsole$new()) get_logger("fancymodel/shiny/server")$ set_appenders(list(AppenderConsole$new(), AppenderConsole$new()))$ set_threshold("trace") get_logger("fancymodel/plumber") if (requireNamespace("cli")){ print(logger_tree()) }
LoggerGlue
LoggerGlue
LoggerGlue uses glue::glue() instead of base::sprintf() to construct
log messages. glue is a very well designed package for
string interpolation. It makes composing log messages
more flexible and comfortable at the price of an additional dependency and
slightly less performance than sprintf().
glue() lets you define temporary named variables inside the call.
As with the normal Logger, these named arguments get turned into custom
fields; however, you can suppress this behaviour by making named argument
start with a ".". Please refer to vignette("lgr", package = "lgr") for
examples.
lgr::Filterable -> lgr::Logger -> LoggerGlue
lgr::Filterable$add_filter()lgr::Filterable$filter()lgr::Filterable$remove_filter()lgr::Filterable$set_filters()lgr::Logger$add_appender()lgr::Logger$config()lgr::Logger$handle_exception()lgr::Logger$remove_appender()lgr::Logger$set_appenders()lgr::Logger$set_exception_handler()lgr::Logger$set_propagate()lgr::Logger$set_replace_empty()lgr::Logger$set_threshold()new()
LoggerGlue$new( name = "(unnamed logger)", appenders = list(), threshold = NULL, filters = list(), exception_handler = default_exception_handler, propagate = TRUE, replace_empty = "<NULL>", transformer = NULL )
fatal()
LoggerGlue$fatal(..., caller = get_caller(-8L), .envir = parent.frame())
error()
LoggerGlue$error(..., caller = get_caller(-8L), .envir = parent.frame())
warn()
LoggerGlue$warn(..., caller = get_caller(-8L), .envir = parent.frame())
info()
LoggerGlue$info(..., caller = get_caller(-8L), .envir = parent.frame())
debug()
LoggerGlue$debug(..., caller = get_caller(-8L), .envir = parent.frame())
trace()
LoggerGlue$trace(..., caller = get_caller(-8L), .envir = parent.frame())
log()
LoggerGlue$log( level, ..., timestamp = Sys.time(), caller = get_caller(-7), .envir = parent.frame() )
list_log()
LoggerGlue$list_log(x)
spawn()
LoggerGlue$spawn(name)
set_transformer()
Set the transformer for glue string interpolation
LoggerGlue$set_transformer(x)
xsingle function taking two arguments. See glue::glue().
Pad Character Vectors
x |
a |
width |
|
pad |
|
pad_left("foo", 5) pad_right("foo", 5, ".") pad_left(c("foo", "foooooo"), pad = ".")pad_left("foo", 5) pad_right("foo", 5, ".") pad_left(c("foo", "foooooo"), pad = ".")
The print() method for Loggers displays the most important aspects of
the Appender.
## S3 method for class 'Appender' print(x, color = requireNamespace("crayon", quietly = TRUE), ...)## S3 method for class 'Appender' print(x, color = requireNamespace("crayon", quietly = TRUE), ...)
x |
any R Object |
color |
|
... |
ignored |
print() returns x (invisibly), format() returns a character vector.
# print most important details of logger print(lgr$console)# print most important details of logger print(lgr$console)
Print or Format Logging Data
## S3 method for class 'LogEvent' print( x, fmt = "%L [%t] %m %f", timestamp_fmt = "%Y-%m-%d %H:%M:%S", colors = getOption("lgr.colors"), log_levels = getOption("lgr.log_levels"), pad_levels = "right", excluded_fields = NULL, ... ) ## S3 method for class 'LogEvent' format( x, fmt = "%L [%t] %m %f", timestamp_fmt = "%Y-%m-%d %H:%M:%S", colors = NULL, log_levels = getOption("lgr.log_levels"), pad_levels = "right", excluded_fields = NULL, ... )## S3 method for class 'LogEvent' print( x, fmt = "%L [%t] %m %f", timestamp_fmt = "%Y-%m-%d %H:%M:%S", colors = getOption("lgr.colors"), log_levels = getOption("lgr.log_levels"), pad_levels = "right", excluded_fields = NULL, ... ) ## S3 method for class 'LogEvent' format( x, fmt = "%L [%t] %m %f", timestamp_fmt = "%Y-%m-%d %H:%M:%S", colors = NULL, log_levels = getOption("lgr.log_levels"), pad_levels = "right", excluded_fields = NULL, ... )
x |
a LogEvent |
fmt |
A |
timestamp_fmt |
see |
colors |
A |
log_levels |
named |
pad_levels |
|
excluded_fields |
a |
... |
ignored |
x for print() and a character scalar for format()
%tThe timestamp of the message, formatted according to
timestamp_fmt)
%lthe log level, lowercase character representation
%Lthe log level, uppercase character representation
%kthe log level, first letter of lowercase character representation
%Kthe log level, first letter of uppercase character representation
%nthe log level, integer representation
%gthe name of the logger
%pthe PID (process ID). Useful when logging code that uses multiple threads.
%cthe calling function
%mthe log message
%rthe raw log message (without string interpolation)
%fall custom fields of x in a pseudo-JSON like format that is
optimized for human readability and console output
%jall custom fields of x in proper JSON. This requires that you
have jsonlite installed and does not support colors as opposed to
%f
# standard fields can be printed using special tokens x <- LogEvent$new( level = 300, msg = "a test event", caller = "testfun()", logger = lgr ) print(x) print(x, fmt = c("%t (%p) %c: %n - %m")) print(x, colors = NULL) # custom values y <- LogEvent$new( level = 300, msg = "a gps track", logger = lgr, waypoints = 10, location = "Austria" ) # default output with %f print(y) # proper JSON output with %j if (requireNamespace("jsonlite")){ print(y, fmt = "%L [%t] %m %j") }# standard fields can be printed using special tokens x <- LogEvent$new( level = 300, msg = "a test event", caller = "testfun()", logger = lgr ) print(x) print(x, fmt = c("%t (%p) %c: %n - %m")) print(x, colors = NULL) # custom values y <- LogEvent$new( level = 300, msg = "a gps track", logger = lgr, waypoints = 10, location = "Austria" ) # default output with %f print(y) # proper JSON output with %j if (requireNamespace("jsonlite")){ print(y, fmt = "%L [%t] %m %j") }
The print() method for Loggers displays the most important aspects of
the Logger.
You can also print just the ancestry of a Logger which can be accessed with
with logger$ancestry(). This returns a named character vector whose
names correspond to the names of the Loggers logger inherits from. The
TRUE/FALSE status of its elements correspond to the propagate values of
these Loggers.
## S3 method for class 'Logger' print(x, color = requireNamespace("crayon", quietly = TRUE), ...) ## S3 method for class 'Logger' format(x, color = FALSE, ...) ## S3 method for class 'ancestry' print(x, color = requireNamespace("crayon", quietly = TRUE), ...) ## S3 method for class 'ancestry' format(x, color = FALSE, ...)## S3 method for class 'Logger' print(x, color = requireNamespace("crayon", quietly = TRUE), ...) ## S3 method for class 'Logger' format(x, color = FALSE, ...) ## S3 method for class 'ancestry' print(x, color = requireNamespace("crayon", quietly = TRUE), ...) ## S3 method for class 'ancestry' format(x, color = FALSE, ...)
x |
any R Object |
color |
|
... |
ignored |
print() returns x (invisibly), format() returns a character vector.
# print most important details of logger print(lgr) # print only the ancestry of a logger lg <- get_logger("AegonV/Aerys/Rheagar/Aegon") get_logger("AegonV/Aerys/Rheagar")$set_propagate(FALSE) print(lg$ancestry) unclass(lg$ancestry)# print most important details of logger print(lgr) # print only the ancestry of a logger lg <- get_logger("AegonV/Aerys/Rheagar/Aegon") get_logger("AegonV/Aerys/Rheagar")$set_propagate(FALSE) print(lg$ancestry) unclass(lg$ancestry)
Print Logger Trees
## S3 method for class 'logger_tree' print(x, color = requireNamespace("crayon", quietly = TRUE), ...) ## S3 method for class 'logger_tree' format(x, color = FALSE, ...)## S3 method for class 'logger_tree' print(x, color = requireNamespace("crayon", quietly = TRUE), ...) ## S3 method for class 'logger_tree' format(x, color = FALSE, ...)
x |
|
color |
|
... |
passed on to |
x (invisibly)
Read a JSON logfile
read_json_lines(file, ...)read_json_lines(file, ...)
file |
|
... |
passed on to |
a data.frame
lgr provides convenience functions managing the root Logger. These are designed chiefly for interactive use and are less verbose than their R6 method counterparts.
threshold() sets or retrieves the threshold for an Appender or Logger
(the minimum level of log messages it processes). It's target defaults to
the root logger. (equivalent to lgr::lgr$threshold and
lgr::lgr$set_threshold)
console_threshold() is a shortcut to set the threshold of the root
loggers AppenderConsole, which is usually the only Appender that manages
console output for a given R session. (equivalent to
lgr::lgr$appenders$console$threshold and
lgr::lgr$appenders$console$set_threshold)
add_appender() and remove_appender() add Appenders to Loggers and other
Appenders. (equivalent to lgr::lgr$add_appender and
lgr::lgr$remove_appender)
show_log() displays the last n log entries of an Appender (or a Logger
with such an Appender attached) with a $show() method. Most, but not all
Appenders support this function (try AppenderFile or AppenderBuffer).
show_data() and show_dt() work similar to show_log(), except that
they return the log as data.frame or data.table respectively. Only
Appenders that log to formats that can easily be converted to data.frames
are supported (try AppenderJson or AppenderBuffer).
The easiest way to try out this features is by adding an AppenderBuffer
to the root logger with basic_config(memory = TRUE).
log_exception(code, logfun = lgr$fatal, caller = get_caller(-3)) threshold(level, target = lgr::lgr) console_threshold(level, target = lgr::lgr$appenders$console) add_appender(appender, name = NULL, target = lgr::lgr) remove_appender(pos, target = lgr::lgr) show_log(threshold = NA_integer_, n = 20L, target = lgr::lgr) show_dt(target = lgr::lgr) show_data(target = lgr::lgr)log_exception(code, logfun = lgr$fatal, caller = get_caller(-3)) threshold(level, target = lgr::lgr) console_threshold(level, target = lgr::lgr$appenders$console) add_appender(appender, name = NULL, target = lgr::lgr) remove_appender(pos, target = lgr::lgr) show_log(threshold = NA_integer_, n = 20L, target = lgr::lgr) show_dt(target = lgr::lgr) show_data(target = lgr::lgr)
code |
Any R code |
logfun |
a |
caller |
a |
level |
|
target |
a Logger or Appender or the name of a Logger as |
appender |
an |
name |
|
pos |
|
threshold |
|
n |
|
threshold() and console_threshold() return the log_level of target
as integer (invisibly)
add_appender() and remove_appender() return target.
show_log() prints to the console and returns whatever the target
Appender's $show() method returns, usually a character vector,
data.frame or data.table (invisibly).
show_data() always returns a data.frame and show_dt() always returns
a data.table.
# Get and set the threshold of the root logger threshold("error") threshold() lgr$info("this will be supressed") lgr$error("an important error message") # you can also specify a target to modify other loggers lg <- get_logger("test") threshold("fatal", target = lg) threshold(target = lg) # If a Logger's threshold is not set, the threshold is inherited from # its parent, in this case the root logger (that we set to error/200 before) threshold(NULL, target = lg) threshold(target = lg) # Alternative R6 API for getting/setting thresholds lg$set_threshold("info") lg$threshold lg$set_threshold(300) lg$threshold lg$set_threshold(NULL) lg$threshold # cleanup lgr$config(NULL) lg$config(NULL) # add Appenders to a Logger add_appender(AppenderConsole$new(), "second_console_appender") lgr$fatal("Multiple console appenders are a bad idea") remove_appender("second_console_appender") lgr$info("Good that we defined an appender name, so it's easy to remove") # Reconfigure the root logger basic_config(memory = TRUE) # log some messages lgr$info("a log message") lgr$info("another message with data", data = 1:3) show_log() show_data() # cleanup lgr$config(NULL)# Get and set the threshold of the root logger threshold("error") threshold() lgr$info("this will be supressed") lgr$error("an important error message") # you can also specify a target to modify other loggers lg <- get_logger("test") threshold("fatal", target = lg) threshold(target = lg) # If a Logger's threshold is not set, the threshold is inherited from # its parent, in this case the root logger (that we set to error/200 before) threshold(NULL, target = lg) threshold(target = lg) # Alternative R6 API for getting/setting thresholds lg$set_threshold("info") lg$threshold lg$set_threshold(300) lg$threshold lg$set_threshold(NULL) lg$threshold # cleanup lgr$config(NULL) lg$config(NULL) # add Appenders to a Logger add_appender(AppenderConsole$new(), "second_console_appender") lgr$fatal("Multiple console appenders are a bad idea") remove_appender("second_console_appender") lgr$info("Good that we defined an appender name, so it's easy to remove") # Reconfigure the root logger basic_config(memory = TRUE) # log some messages lgr$info("a log message") lgr$info("another message with data", data = 1:3) show_log() show_data() # cleanup lgr$config(NULL)
These are helper functions for verifying log levels and converting them from their character to their integer representations. This is primarily useful if you want to build your own Loggers, Appenders or Layouts and need to handle log levels in a way that is consistent with lgr .
standardize_threshold( x, log_levels = c(getOption("lgr.log_levels"), c(all = NA_integer_, off = 0L)) ) is_threshold(x) standardize_log_level(x, log_levels = getOption("lgr.log_levels")) is_log_level(x) standardize_log_levels(x, log_levels = getOption("lgr.log_levels")) is_log_levels(x)standardize_threshold( x, log_levels = c(getOption("lgr.log_levels"), c(all = NA_integer_, off = 0L)) ) is_threshold(x) standardize_log_level(x, log_levels = getOption("lgr.log_levels")) is_log_level(x) standardize_log_levels(x, log_levels = getOption("lgr.log_levels")) is_log_levels(x)
x |
a |
log_levels |
named |
An unnamed integer vector
Other docs relevant for extending lgr:
LogEvent,
as_LogEvent(),
event_list()
standardize_threshold("info") standardize_threshold("all") is_threshold("all") is_threshold("foobar") standardize_log_level("info") # all is a valid threshold, but not a valid log level try(is.na(standardize_log_level("all"))) is_log_level("all") # standardized_log_level intentionally only works with scalars, because many # functions require scalar log level inputs try(standardize_log_level(c("info", "fatal"))) # You can still use standardize_log_levels() (plural) to work with vectors standardize_log_levels(c("info", "fatal"))standardize_threshold("info") standardize_threshold("all") is_threshold("all") is_threshold("foobar") standardize_log_level("info") # all is a valid threshold, but not a valid log level try(is.na(standardize_log_level("all"))) is_log_level("all") # standardized_log_level intentionally only works with scalars, because many # functions require scalar log level inputs try(standardize_log_level(c("info", "fatal"))) # You can still use standardize_log_levels() (plural) to work with vectors standardize_log_levels(c("info", "fatal"))
This is inspired by the python function repr and produces a short
string representation of any R object that is suitable for logging and error
messages. It is a generic so you can implement methods for custom S3 objects.
string_repr(x, width = 32, ...) ## S3 method for class ''function'' string_repr(x, width = 32L, ...) ## S3 method for class 'data.frame' string_repr(x, width = 32L, ...) ## S3 method for class 'matrix' string_repr(x, width = 32L, ...) ## S3 method for class 'numeric' string_repr(x, width = 32L, ...) ## Default S3 method: string_repr(x, width = 32L, ...)string_repr(x, width = 32, ...) ## S3 method for class ''function'' string_repr(x, width = 32L, ...) ## S3 method for class 'data.frame' string_repr(x, width = 32L, ...) ## S3 method for class 'matrix' string_repr(x, width = 32L, ...) ## S3 method for class 'numeric' string_repr(x, width = 32L, ...) ## Default S3 method: string_repr(x, width = 32L, ...)
x |
Any R object. |
width |
a scalar integer |
... |
passed on to methods |
a scalar character
string_repr(iris) string_repr(LETTERS) string_repr(LETTERS, 10)string_repr(iris) string_repr(LETTERS) string_repr(LETTERS, 10)
Completely disable logging for all loggers. This is for example useful for
automated test code. suspend_logging() globally disables all logging with
lgr until unsuspend_logging() is invoked, while without_logging() and
with_logging() temporarily disable/enable logging.
suspend_logging() unsuspend_logging() without_logging(code) with_logging(code)suspend_logging() unsuspend_logging() without_logging(code) with_logging(code)
code |
Any R code |
suspend_logging() and unsuspend_logging() return NULL (invisibly),
without_logging() and with_logging() returns whatever code returns.
lg <- get_logger("test") # temporarily disable logging lg$fatal("foo") without_logging({ lg$info("everything in this codeblock will be suppressed") lg$fatal("bar") }) # globally disable logging suspend_logging() lg$fatal("bar") with_logging(lg$fatal("foo")) # log anyways # globally enable logging again unsuspend_logging() lg$fatal("foo")lg <- get_logger("test") # temporarily disable logging lg$fatal("foo") without_logging({ lg$info("everything in this codeblock will be suppressed") lg$fatal("bar") }) # globally disable logging suspend_logging() lg$fatal("bar") with_logging(lg$fatal("foo")) # log anyways # globally enable logging again unsuspend_logging() lg$fatal("foo")
Convert a LogEvent to a character string
## S3 method for class 'LogEvent' toString(x, ...)## S3 method for class 'LogEvent' toString(x, ...)
x |
a LogEvent |
... |
ignored |
a character scalar
toString(LogEvent$new(logger = lgr::lgr))toString(LogEvent$new(logger = lgr::lgr))
This gives you a minimal logger with no appenders that you can use inside
your package under the name lg (e.g. lg$fatal("test")). use_logger()
does not modify any files but only prints code for you to copy and paste.
use_logger( pkg = desc::desc_get("Package", rprojroot::find_package_root_file("DESCRIPTION"))[[1]] )use_logger( pkg = desc::desc_get("Package", rprojroot::find_package_root_file("DESCRIPTION"))[[1]] )
pkg |
|
a character scalar containing R code.
use_logger("testpkg")use_logger("testpkg")
with_log_level temporarily overrides the log level of all LogEvents
created by target Logger.
with_log_level(level, code, logger = lgr::lgr) with_log_value(values, code, logger = lgr::lgr)with_log_level(level, code, logger = lgr::lgr) with_log_value(values, code, logger = lgr::lgr)
level |
|
code |
Any R code |
logger |
a Logger or the name of one (see |
values |
a named |
These functions abuses lgr's filter mechanic to modify LogEvents in-place before they passed on the Appenders. Use with care as they can produce hard to reason about code.
whatever code would return
with_log_level("warn", { lgr$info("More important than it seems") lgr$fatal("Really not so bad") }) with_log_value( list(msg = "overriden msg"), { lgr$info("bar") lgr$fatal("FOO") })with_log_level("warn", { lgr$info("More important than it seems") lgr$fatal("Really not so bad") }) with_log_value( list(msg = "overriden msg"), { lgr$info("bar") lgr$fatal("FOO") })