Title: | Modern Logging for the R Ecosystem |
---|---|
Description: | An effortless 'ndjson' (newline-delimited 'JSON') logger, with two primary log-writing interfaces. It provides a set of wrappings for base R's message(), warning(), and stop() functions that maintain identical functionality, but also log the handler message to an 'ndjson' log file. 'loggit' also exports its internal 'loggit()' function for powerful and configurable custom logging. No change in existing code is necessary to use this package, and should only require additions to fully leverage the power of the logging system. 'loggit' also provides a log reader for reading an 'ndjson' log file into a data frame, log rotation, and live echo of the 'ndjson' log messages to terminal 'stdout' for log capture by external systems (like containers). 'loggit' is ideal for Shiny apps, data pipelines, modeling work flows, and more. Please see the vignettes for detailed example use cases. |
Authors: | Ryan Price [cre, aut] |
Maintainer: | Ryan Price <[email protected]> |
License: | MIT + file LICENSE |
Version: | 2.1.1.9999 |
Built: | 2025-02-02 05:41:24 UTC |
Source: | https://github.com/ryapric/loggit |
Return the log file that loggit will write to.
get_logfile()
get_logfile()
get_logfile()
get_logfile()
Get timestamp format for use in output logs.
get_timestamp_format()
get_timestamp_format()
get_timestamp_format()
get_timestamp_format()
These exception handlers are identical to base R's message,
warning, and stop, but with included logging
of the exception messages via loggit()
.
message(..., domain = NULL, appendLF = TRUE, .loggit = TRUE, echo = TRUE) warning( ..., call. = TRUE, immediate. = FALSE, noBreaks. = FALSE, domain = NULL, .loggit = TRUE, echo = TRUE ) stop(..., call. = TRUE, domain = NULL, .loggit = TRUE, echo = TRUE)
message(..., domain = NULL, appendLF = TRUE, .loggit = TRUE, echo = TRUE) warning( ..., call. = TRUE, immediate. = FALSE, noBreaks. = FALSE, domain = NULL, .loggit = TRUE, echo = TRUE ) stop(..., call. = TRUE, domain = NULL, .loggit = TRUE, echo = TRUE)
... |
zero or more objects which can be coerced to character
(and which are pasted together with no separator) or (for
|
domain |
see |
appendLF |
logical: should messages given as a character string have a newline appended? |
.loggit |
Should loggit function execute? Defaults to |
echo |
Should loggit's log entry be echoed to the console, as well?
Defaults to |
call. |
logical, indicating if the call should become part of the warning message. |
immediate. |
logical, indicating if the call should be output
immediately, even if |
noBreaks. |
logical, indicating as far as possible the message should
be output as a single line when |
if (2 < 1) message("Don't say such silly things!") if (2 < 1) warning("You may want to review that math, and so this is your warning") if (2 < 1) stop("This is a completely false condition, which throws an error")
if (2 < 1) message("Don't say such silly things!") if (2 < 1) warning("You may want to review that math, and so this is your warning") if (2 < 1) stop("This is a completely false condition, which throws an error")
This function executes immediately before the function definitions for the base handler functions (message, warning, and stop, and logs their timestamped output (a bit more verbosely) to a log file. The log file is an ndjson file, which is a portable, JSON-based format that is easily parsed by many line-processing systems.
loggit(log_lvl, log_msg, ..., echo = TRUE, custom_log_lvl = FALSE, sanitizer)
loggit(log_lvl, log_msg, ..., echo = TRUE, custom_log_lvl = FALSE, sanitizer)
log_lvl |
Level of log output. In actual practice, one of "DEBUG",
"INFO", "WARN", and "ERROR" are common, but any string may be supplied if
|
log_msg |
Main log message. Will be coerced to class |
... |
A named |
echo |
Should the log file entry be printed to the console as well?
Defaults to |
custom_log_lvl |
Allow log levels other than "DEBUG", "INFO", "WARN",
and "ERROR"? Defaults to |
sanitizer |
Sanitizer function to run over elements in log data. The
default sanitizer, if not specified, is |
loggit("INFO", "This is a message", but_maybe = "you want more fields?", sure = "why not?", like = 2, or = 10, what = "ever")
loggit("INFO", "This is a message", but_maybe = "you want more fields?", sure = "why not?", like = 2, or = 10, what = "ever")
This function returns a data.frame
containing all the logs in the provided
ndjson
log file. If no explicit log file is provided, calling this function
will return a data frame of the log file currently pointed to by the loggit
functions.
read_logs(logfile, unsanitizer)
read_logs(logfile, unsanitizer)
logfile |
Path to log file. Will default to currently-set log file. |
unsanitizer |
Unsanitizer function to use. For more info on sanitizers, please see the sanitizers section of the package documentation. |
A data.frame
.
set_logfile(file.path(tempdir(), "loggit.log"), confirm = FALSE) message("Test log message") read_logs()
set_logfile(file.path(tempdir(), "loggit.log"), confirm = FALSE) message("Test log message") read_logs()
Read ndJSON-formatted log file
read_ndjson(logfile, unsanitizer)
read_ndjson(logfile, unsanitizer)
logfile |
Log file to read from, and convert to a |
unsanitizer |
Unsanitizer function passed in from |
A data.frame
Truncates the log file to the line count provided as rotate_lines
.
rotate_logs(rotate_lines = 1e+05, logfile)
rotate_logs(rotate_lines = 1e+05, logfile)
rotate_lines |
The number of log entries to keep in the logfile. Defaults to 100,000. |
logfile |
Log file to truncate. Defaults to the currently-configured log file. |
loggit
makes no assumptions nor enforcement of calling this function; that
is to say, the onus of log rotation is up to the developer. You
# Truncate "default" log file to 100 lines set_logfile() for (i in 1:150) {loggit("INFO", i, echo = FALSE)} rotate_logs(100) # Truncate a different log file to 250 lines another_log <- file.path(tempdir(), "another.log") set_logfile(another_log) for (i in 1:300) {loggit("INFO", i, echo = FALSE)} set_logfile() # clears pointer to other log file rotate_logs(250, another_log)
# Truncate "default" log file to 100 lines set_logfile() for (i in 1:150) {loggit("INFO", i, echo = FALSE)} rotate_logs(100) # Truncate a different log file to 250 lines another_log <- file.path(tempdir(), "another.log") set_logfile(another_log) for (i in 1:300) {loggit("INFO", i, echo = FALSE)} set_logfile() # clears pointer to other log file rotate_logs(250, another_log)
This is the default ndJSON sanitizer function for log data being read into
the R session by read_logs()
. This type of function is needed because since
loggit
reimplements its own string-based JSON parser, and not a fancy one
built from an AST or something, it's very easy to have bad patterns break
your logs. You may also specify your own sanitizer function to pass to
loggit()
, which takes a single string and returns an
(optionally-transformed) string, where each string is an individual element
of the log data.
default_ndjson_sanitizer(string, sanitize = TRUE) default_ndjson_unsanitizer(string)
default_ndjson_sanitizer(string, sanitize = TRUE) default_ndjson_unsanitizer(string)
string |
Each element of the log data to operate on. Note that this is
each element, not each line in the logs. For example, each entry in the
|
sanitize |
Whether the operation will sanitize, or unsanitize the log
data. Defaults to |
The default string patterns and their replacements are currently mapped as follows:
Character | Replacement in log file |
{ |
__LEFTBRACE__ |
} |
__RIGHTBRACE__ |
" |
__DBLQUOTE__ |
, |
__COMMA__ |
\r |
__CR__ |
\n |
__LF__ |
A single string.
Set the log file that loggit will write to. No logs outside of a temporary
directory will be written until this is set explicitly, as per CRAN policy.
Therefore, the default behavior is to create a file named loggit.log
in
your system's temporary directory.
set_logfile(logfile = NULL, confirm = TRUE)
set_logfile(logfile = NULL, confirm = TRUE)
logfile |
Full or relative path to log file. If not provided, will write
to |
confirm |
Print confirmation of log file setting? Defaults to |
A suggested use of this function would be to call it early, to log to the
current working directory, as follows: set_logfile(paste0(getwd(), "/loggit.log"))
. If you are using loggit
in your package, you can wrap
this function in .onLoad()
so that the logfile is set when your package
loads.
set_logfile(file.path(tempdir(), "loggit.log"))
set_logfile(file.path(tempdir(), "loggit.log"))
Set timestamp format for use in output logs. This function performs no time format validations, but will echo out the current time in the provided format for manual validation.
set_timestamp_format(ts_format = "%Y-%m-%dT%H:%M:%S%z", confirm = TRUE)
set_timestamp_format(ts_format = "%Y-%m-%dT%H:%M:%S%z", confirm = TRUE)
ts_format |
ISO date format. Defaults to ISO-8601 (e.g. "2020-01-01T00:00:00+0000"). |
confirm |
Print confirmation message of timestamp format? Defaults to
|
This function provides no means of setting a timezone, and instead relies on the host system's time configuration to provide this. This is to enforce consistency across software running on the host.
set_timestamp_format("%Y-%m-%d %H:%M:%S")
set_timestamp_format("%Y-%m-%d %H:%M:%S")
Write ndJSON-formatted log file
write_ndjson(log_df, logfile, echo = TRUE, overwrite = FALSE)
write_ndjson(log_df, logfile, echo = TRUE, overwrite = FALSE)
log_df |
Data frame of log data. Rows are converted to |
logfile |
Log file to write to. Defaults to currently-configured log file. |
echo |
Echo the |
overwrite |
Overwrite previous log file data? Defaults to |