Skip to contents

Log messages are written to a file with basic log rotation: when max number of lines or bytes is defined to be other than Inf, then the log file is renamed with a .1 suffix and a new log file is created. The renaming happens recursively (eg logfile.1 renamed to logfile.2) until the specified max_files, then the oldest file (logfile.{max_files-1}) is deleted.

Usage

appender_file(
  file,
  append = TRUE,
  max_lines = Inf,
  max_bytes = Inf,
  max_files = 1L
)

Arguments

file

path

append

boolean passed to cat defining if the file should be overwritten with the most recent log message instead of appending

max_lines

numeric specifying the maximum number of lines allowed in a file before rotating

max_bytes

numeric specifying the maximum number of bytes allowed in a file before rotating

max_files

integer specifying the maximum number of files to be used in rotation

Value

function taking lines argument

Examples

## ##########################################################################
## simple example logging to a file
t <- tempfile()
log_appender(appender_file(t))
for (i in 1:25) log_info(i)
readLines(t)
#>  [1] "INFO [2024-10-21 07:31:11] 1"  "INFO [2024-10-21 07:31:11] 2" 
#>  [3] "INFO [2024-10-21 07:31:11] 3"  "INFO [2024-10-21 07:31:11] 4" 
#>  [5] "INFO [2024-10-21 07:31:11] 5"  "INFO [2024-10-21 07:31:11] 6" 
#>  [7] "INFO [2024-10-21 07:31:11] 7"  "INFO [2024-10-21 07:31:11] 8" 
#>  [9] "INFO [2024-10-21 07:31:11] 9"  "INFO [2024-10-21 07:31:11] 10"
#> [11] "INFO [2024-10-21 07:31:11] 11" "INFO [2024-10-21 07:31:11] 12"
#> [13] "INFO [2024-10-21 07:31:11] 13" "INFO [2024-10-21 07:31:11] 14"
#> [15] "INFO [2024-10-21 07:31:11] 15" "INFO [2024-10-21 07:31:11] 16"
#> [17] "INFO [2024-10-21 07:31:11] 17" "INFO [2024-10-21 07:31:11] 18"
#> [19] "INFO [2024-10-21 07:31:11] 19" "INFO [2024-10-21 07:31:11] 20"
#> [21] "INFO [2024-10-21 07:31:11] 21" "INFO [2024-10-21 07:31:11] 22"
#> [23] "INFO [2024-10-21 07:31:11] 23" "INFO [2024-10-21 07:31:11] 24"
#> [25] "INFO [2024-10-21 07:31:11] 25"

## ##########################################################################
## more complex example of logging to file
## rotated after every 3rd line up to max 5 files

## create a folder storing the log files
t <- tempfile()
dir.create(t)
f <- file.path(t, "log")

## define the file logger with log rotation enabled
log_appender(appender_file(f, max_lines = 3, max_files = 5L))

## enable internal logging to see what's actually happening in the logrotate steps
log_threshold(TRACE, namespace = ".logger")
## log 25 messages
for (i in 1:25) log_info(i)
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 1' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 2' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 3' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 87, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 4' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 5' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 6' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 87, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 7' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 8' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 9' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 87, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.3
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 10' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 11' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 12' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 90, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.3 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.4
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.3
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 13' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 14' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 15' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 90, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.3 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.4
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.3
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 16' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 17' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 18' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 90, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.3 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.4
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.3
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 19' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 20' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 21' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 90, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.3 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.4
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.3
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 22' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 23' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 24' to /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] lines: 3, max_lines: 3, bytes: 90, max_bytes: Inf
#> TRACE [2024-10-21 07:31:11] lines >= max_lines || bytes >= max_bytes: TRUE
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.3 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.4
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.3
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 to /tmp/RtmpCKqxnR/file1ff0181889b8/log.2
#> TRACE [2024-10-21 07:31:11] renaming /tmp/RtmpCKqxnR/file1ff0181889b8/log to /tmp/RtmpCKqxnR/file1ff0181889b8/log.1
#> TRACE [2024-10-21 07:31:11] killing the main file: /tmp/RtmpCKqxnR/file1ff0181889b8/log
#> TRACE [2024-10-21 07:31:11] logging 'INFO [2024-10-21 07:31:11] 25' to /tmp/RtmpCKqxnR/file1ff0181889b8/log

## see what was logged
lapply(list.files(t, full.names = TRUE), function(t) {
  cat("\n##", t, "\n")
  cat(readLines(t), sep = "\n")
})
#> 
#> ## /tmp/RtmpCKqxnR/file1ff0181889b8/log 
#> INFO [2024-10-21 07:31:11] 25
#> 
#> ## /tmp/RtmpCKqxnR/file1ff0181889b8/log.1 
#> INFO [2024-10-21 07:31:11] 22
#> INFO [2024-10-21 07:31:11] 23
#> INFO [2024-10-21 07:31:11] 24
#> 
#> ## /tmp/RtmpCKqxnR/file1ff0181889b8/log.2 
#> INFO [2024-10-21 07:31:11] 19
#> INFO [2024-10-21 07:31:11] 20
#> INFO [2024-10-21 07:31:11] 21
#> 
#> ## /tmp/RtmpCKqxnR/file1ff0181889b8/log.3 
#> INFO [2024-10-21 07:31:11] 16
#> INFO [2024-10-21 07:31:11] 17
#> INFO [2024-10-21 07:31:11] 18
#> 
#> ## /tmp/RtmpCKqxnR/file1ff0181889b8/log.4 
#> INFO [2024-10-21 07:31:11] 13
#> INFO [2024-10-21 07:31:11] 14
#> INFO [2024-10-21 07:31:11] 15
#> [[1]]
#> NULL
#> 
#> [[2]]
#> NULL
#> 
#> [[3]]
#> NULL
#> 
#> [[4]]
#> NULL
#> 
#> [[5]]
#> NULL
#>