| Type: | Package |
| Title: | Log Rotation and Conditional Backups |
| Version: | 0.3.7 |
| Maintainer: | Stefan Fleck <stefan.b.fleck@gmail.com> |
| Description: | Conditionally rotate or back-up files based on their size or the date of the last backup; inspired by the 'Linux' utility 'logrotate'. |
| License: | MIT + file LICENSE |
| URL: | https://s-fleck.github.io/rotor/ |
| BugReports: | https://github.com/s-fleck/rotor/issues |
| Imports: | dint, R6, tools |
| Suggests: | covr, crayon, data.table, digest, rmarkdown, testthat, uuid,ulid, zip |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.2.1.9000 |
| NeedsCompilation: | no |
| Packaged: | 2022-10-11 12:35:11 UTC; stefan.fleck |
| Author: | Stefan Fleck |
| Repository: | CRAN |
| Date/Publication: | 2022-10-11 13:10:02 UTC |
rotor: Log Rotation and Conditional Backups
Description
Conditionally rotate or back-up files based on their size or the date of the last backup; inspired by the 'Linux' utility 'logrotate'.
Author(s)
Maintainer: Stefan Fleckstefan.b.fleck@gmail.com (ORCID)
See Also
Useful links:
An R6 Class for managing backups (abstract base class)
Description
BackupQueueis an abstract class not intended for direct usage, please refer toBackupQueueIndex,BackupQueueDateTime,BackupQueueDate instead.
Details
This class is part of theR6 API ofrotor which isintended for developers that want to extend this package. For normal usage,the simpler functional API is recommended (seerotate()).
Super class
rotor::DirectoryQueue ->BackupQueue
Public fields
dircharacterscalar. Directory in which to place the backups.nintegerscalar. The number of backups that exist forBackupQueue$origin
Active bindings
dircharacterscalar. Directory in which to place the backups.nintegerscalar. The number of backups that exist forBackupQueue$originfilecharacterscalar. The file to backup/rotate.compression(Optional) compression to use
compressionargument ofrotate().max_backupsMaximum number/size/age of backups. See
max_backupsargument ofrotate()has_backupsReturns
TRUEif at least one backup ofBackupQueue$originexistsAll backups of self$origin
Methods
Public methods
Inherited methods
Methodnew()
Usage
BackupQueue$new( origin, dir = dirname(origin), max_backups = Inf, compression = FALSE, backup_dir = NULL)
Methodprune()
Delete all backups exceptmax_backups. Seeprune_backups().
Usage
BackupQueue$prune(max_backups = self$max_backups)
Methodprune_identical()
Delete all identical backups. Usestools::md5sum() tocompare the files.Set the file to be backed up
Usage
BackupQueue$prune_identical()
Methodprint()
Usage
BackupQueue$print()
Methodpush_backup()
Usage
BackupQueue$push_backup(...)
Methodset_origin()
Usage
BackupQueue$set_origin(x)
Arguments
xa
characterscalar. Path to a fileSet the file to be backed up
Methodset_compression()
Usage
BackupQueue$set_compression(x)
Arguments
xa
characterscalar. Path to a file
Methodset_max_backups()
Usage
BackupQueue$set_max_backups(x)
Methodset_file()
Usage
BackupQueue$set_file(x)
Methodset_backup_dir()
Usage
BackupQueue$set_backup_dir(x)
See Also
Other R6 Classes:BackupQueueDateTime,BackupQueueDate,BackupQueueIndex,Cache,DirectoryQueue
An R6 class for managing datestamped backups
Description
A BackupQueue for date-stamped backups, e.g.foo.log,foo.2020-07-24.log
Details
This class is part of theR6 API ofrotor which isintended for developers that want to extend this package. For normal usage,the simpler functional API is recommended (seerotate()).
Super classes
rotor::DirectoryQueue ->rotor::BackupQueue ->rotor::BackupQueueDateTime ->BackupQueueDate
Methods
Public methods
Inherited methods
rotor::DirectoryQueue$set_dir()rotor::BackupQueue$print()rotor::BackupQueue$prune_identical()rotor::BackupQueue$push_backup()rotor::BackupQueue$set_backup_dir()rotor::BackupQueue$set_compression()rotor::BackupQueue$set_file()rotor::BackupQueue$set_origin()rotor::BackupQueueDateTime$prune()rotor::BackupQueueDateTime$push()rotor::BackupQueueDateTime$set_cache_backups()rotor::BackupQueueDateTime$set_max_backups()rotor::BackupQueueDateTime$should_rotate()rotor::BackupQueueDateTime$update_backups_cache()
Methodnew()
Usage
BackupQueueDate$new( origin, dir = dirname(origin), max_backups = Inf, compression = FALSE, fmt = "%Y-%m-%d", cache_backups = FALSE, backup_dir = NULL)
Methodset_fmt()
Usage
BackupQueueDate$set_fmt(x)
See Also
Other R6 Classes:BackupQueueDateTime,BackupQueueIndex,BackupQueue,Cache,DirectoryQueue
An R6 class for managing timestamped backups
Description
A BackupQueue for timestamped backups, e.g.foo.log,foo.2020-07-24_10-54-30.log
Details
This class is part of theR6 API ofrotor which isintended for developers that want to extend this package. For normal usage,the simpler functional API is recommended (seerotate()).
Super classes
rotor::DirectoryQueue ->rotor::BackupQueue ->BackupQueueDateTime
Active bindings
fmtSee
formatargument ofrotate_date()logicalscalar. IfTRUE(the default) the list of backups is cached,ifFALSEit is read from disk every time this appender triggers.Caching brings a significant speedup for checking whether to rotate ornot based on theageof the last backup, but is only safe if there areno other programs/functions interacting with the backups. This is onlyadvantageous for high frequency file rotation (i.e. several times persecond)POSIXctscalar. Timestamp of the last rotation (the last backup)
Methods
Public methods
Inherited methods
Methodnew()
Usage
BackupQueueDateTime$new( origin, dir = dirname(origin), max_backups = Inf, compression = FALSE, fmt = "%Y-%m-%d--%H-%M-%S", cache_backups = FALSE, backup_dir = NULL)
Methodpush()
Create a new time-stamped backup (e.g. ‘logfile.2020-07-22_12-26-29.log’)
Usage
BackupQueueDateTime$push(overwrite = FALSE, now = Sys.time())
Arguments
overwritelogicalscalar. Overwrite backups with the samefilename (i.e timestamp)?nowPOSIXctscalar. Can be used as an override mechanism forthe current system time if necessary.
Methodprune()
Usage
BackupQueueDateTime$prune(max_backups = self$max_backups)
Methodshould_rotate()
Should a file ofsize andage be rotated? Seesize andagearguments ofrotate_date().now overrides the current system time,'last_rotation“ overrides the date of the last rotation.
Usage
BackupQueueDateTime$should_rotate( size, age, now = Sys.time(), last_rotation = self$last_rotation %||% file.info(self$origin)$ctime, verbose = FALSE)
Returns
TRUE orFALSE
Methodupdate_backups_cache()
Force update of the backups cache (only if$cache_backups == TRUE).
Usage
BackupQueueDateTime$update_backups_cache()
Methodset_max_backups()
Usage
BackupQueueDateTime$set_max_backups(x)
Methodset_fmt()
Usage
BackupQueueDateTime$set_fmt(x)
Methodset_cache_backups()
Usage
BackupQueueDateTime$set_cache_backups(x)
See Also
Other R6 Classes:BackupQueueDate,BackupQueueIndex,BackupQueue,Cache,DirectoryQueue
An R6 class for managing indexed backups
Description
A BackupQueue for indexed backups, e.g.foo.log,foo.1.log,foo.2.log, ...
Details
This class is part of theR6 API ofrotor which isintended for developers that want to extend this package. For normal usage,the simpler functional API is recommended (seerotate()).
Super classes
rotor::DirectoryQueue ->rotor::BackupQueue ->BackupQueueIndex
Methods
Public methods
Inherited methods
Methodpush()
Create a new index-stamped backup (e.g. ‘logfile.1.log’)
Usage
BackupQueueIndex$push()
Methodprune()
Usage
BackupQueueIndex$prune(max_backups = self$max_backups)
Methodprune_identical()
Usage
BackupQueueIndex$prune_identical()
Methodshould_rotate()
Should a file ofsize be rotated? Seesize argument ofrotate()
Usage
BackupQueueIndex$should_rotate(size, verbose = FALSE)
Returns
TRUE orFALSE
Methodpad_index()
Pad the indices in the filenames of indexed backupsto the number of digits of the largest index. Usually does not have tobe called manually.
Usage
BackupQueueIndex$pad_index()
Methodincrement_index()
Increment die Indices of all backups byn Usually doesnot have to be called manually.
Usage
BackupQueueIndex$increment_index(n = 1)
Arguments
ninteger> 0
See Also
Other R6 Classes:BackupQueueDateTime,BackupQueueDate,BackupQueue,Cache,DirectoryQueue
An R6 class for managing a persistent file-based cache
Description
Cache provides anR6 API for managing an on-disk key-valuestore forR objects. The objects are serialized to a single folder as.rds files and the key of the object equals the name of the file.Cache supports automatic removal of old files if the cache folder exceeds apredetermined number of files, total size, or if the individual files exceeda certain age.
Details
This class is part of theR6 API ofrotor which isintended for developers that want to extend this package. For normal usage,the simpler functional API is recommended (seerotate()).
Super class
rotor::DirectoryQueue ->Cache
Public fields
dira
characterscalar. path of the directory in which to store the cache filesnintegerscalar: number of files in the cachemax_filessee the
compressargument ofbase::saveRDS().Note: this differs from the$compressargument ofrotate().max_filesintegerscalar: maximum number of files to keep inthe cache
Active bindings
dira
characterscalar. path of the directory in which to store the cache filesnintegerscalar: number of files in the cachemax_filessee the
compressargument ofbase::saveRDS().Note: this differs from the$compressargument ofrotate().max_filesintegerscalar: maximum number of files to keep inthe cachemax_sizescalar
integer,characterorInf. Deletecached files (starting with the oldest) until the total size of thecache is belowmax_size.Integersare interpreted as bytes. Youcan passcharactervectors that contain a file size suffix like1k(kilobytes),3M(megabytes),4G(gigabytes),5T(terabytes). Insteadof these short forms you can also be explicit and use the IEC suffixesKiB,MiB,GiB,TiB. In Both cases1kilobyte is1024bytes, 1megabyteis1024kilobytes, etc... .max_agea
Datescalar: Remove all backups before this datea
characterscalar representing a Date in ISO format (e.g."2019-12-31")a
characterscalar representing an Interval in the form"<number> <interval>"(seerotate())
hashfunNULLor afunctionto generate a unique hash from theobject to be cached (see example). The hashmust be a text stringthat is a valid filename on the target system. If$hashfunisNULL,a storage key must be supplied manually incache$push(). If a newobject is added with the same key as an existing object, the existingobject will be overwritten without warning.All cached files
Methods
Public methods
Inherited methods
Methodnew()
Usage
Cache$new( dir = dirname(file), max_files = Inf, max_size = Inf, max_age = Inf, compression = TRUE, hashfun = digest::digest, create_dir = TRUE)
Arguments
create_dirlogicalscalar. IfTRUEdiris created if itdoes not exist.
Examples
td <- file.path(tempdir(), "cache-test")# When using a real hash function as hashfun, identical objects will only# be added to the cache oncecache_hash <- Cache$new(td, hashfun = digest::digest)cache_hash$push(iris)cache_hash$push(iris)cache_hash$filescache_hash$purge()# To override this behaviour use a generator for unique ids, such as uuidif (requireNamespace("uuid")){ cache_uid <- Cache$new(td, hashfun = function(x) uuid::UUIDgenerate()) cache_uid$push(iris) cache_uid$push(iris) cache_uid$files cache_uid$purge()}unlink(td, recursive = TRUE)Methodpush()
push a new object to the cache
Usage
Cache$push(x, key = self$hashfun(x))
Arguments
xanyR object
keya
characterscalar. Key under which to store the cachedobject. Must be a valid filename. Defaults to being generated by$hashfun()but may also be supplied manually.
Returns
acharacter scalar: the key of the newly added object
Methodread()
read a cached file
Usage
Cache$read(key)
Arguments
keycharacterscalar. key of the cached file to read.
Methodremove()
remove a single file from the cache
Usage
Cache$remove(key)
Arguments
keycharacterscalar. key of the cached file to remove
Methodpop()
Read and remove a single file from the cache
Usage
Cache$pop(key)
Arguments
keycharacterscalar. key of the cached file to read/remove
Methodprune()
Prune the cache
Delete cached objects that match certain criteria.max_files andmax_size deletes the oldest cached objects first; however, this isdependent on accuracy of the file modification timestamps on your system.For example, ext3 only supports second-accuracy, and some windowsversion only support timestamps at a resolution of two seconds.
If two files have the same timestamp, they are deleted in the lexicalsort order of their key. This means that by using a function thatgenerates lexically sortable keys ashashfun (such asulid::generate()) you can enforce the correct deletion order. Thereis no such workaround if you use a real hash function.
Usage
Cache$prune( max_files = self$max_files, max_size = self$max_size, max_age = self$max_age, now = Sys.time())
Arguments
max_files, max_size, max_agesee section Active Bindings.
nowa
POSIXctdatetime scalar. The current time (for max_age)
Methodpurge()
purge the cache (remove all cached files)
Usage
Cache$purge()
Methoddestroy()
purge the cache (remove all cached files)
Usage
Cache$destroy()
Methodprint()
Usage
Cache$print()
Methodset_max_files()
Usage
Cache$set_max_files(x)
Methodset_max_age()
Usage
Cache$set_max_age(x)
Methodset_max_size()
Usage
Cache$set_max_size(x)
Methodset_compression()
Usage
Cache$set_compression(x)
Methodset_hashfun()
Usage
Cache$set_hashfun(x)
See Also
Other R6 Classes:BackupQueueDateTime,BackupQueueDate,BackupQueueIndex,BackupQueue,DirectoryQueue
Examples
## ------------------------------------------------## Method `Cache$new`## ------------------------------------------------td <- file.path(tempdir(), "cache-test")# When using a real hash function as hashfun, identical objects will only# be added to the cache oncecache_hash <- Cache$new(td, hashfun = digest::digest)cache_hash$push(iris)cache_hash$push(iris)cache_hash$filescache_hash$purge()# To override this behaviour use a generator for unique ids, such as uuidif (requireNamespace("uuid")){ cache_uid <- Cache$new(td, hashfun = function(x) uuid::UUIDgenerate()) cache_uid$push(iris) cache_uid$push(iris) cache_uid$files cache_uid$purge()}unlink(td, recursive = TRUE)An R6 class for managing persistent file-based queues (abstract base class)
Description
Abstract class from which all other classes inrotor inherit theirbasic fields and methods.
Details
This class is part of theR6 API ofrotor which isintended for developers that want to extend this package. For normal usage,the simpler functional API is recommended (seerotate()).
Active bindings
dira
characterscalar. path of the directory in which to storethe cache files
Methods
Public methods
Methodnew()
Usage
DirectoryQueue$new(...)
Methodpush()
Usage
DirectoryQueue$push(x, ...)
Methodprune()
Usage
DirectoryQueue$prune(x, ...)
Methodset_dir()
Usage
DirectoryQueue$set_dir(x, create = TRUE)
See Also
Other R6 Classes:BackupQueueDateTime,BackupQueueDate,BackupQueueIndex,BackupQueue,Cache
Discover existing backups
Description
These function return information on the backups of a file (if any exist)
Usage
backup_info(file, dir = dirname(file))list_backups(file, dir = dirname(file))n_backups(file, dir = dirname(file))newest_backup(file, dir = dirname(file))oldest_backup(file, dir = dirname(file))Arguments
file |
|
dir |
|
Value
backup_info() returns adata.frame similar to the output offile.info()
list_backups() returns the paths to all backups offile
n_backups() returns the number of backups offile as anintegerscalar
newest_backup() andoldest_backup() return the paths to thenewest or oldest backup offile (or an emptycharacter vector if none exist)
Intervals
Inrotor, an interval is a character string in the form"<number> <interval>". The following intervals are possible:"day(s)","week(s)","month(s)","quarter(s)","year(s)".The plural"s" is optional (so"2 weeks" and"2 week" are equivalent).Please be aware that weeks areISOweeksand start on Monday (not Sunday as in some countries).
Interval strings can be used as arguments when backing up or rotating files,or for pruning backup queues (i.e. limiting the number of backups of asingle) file.
When rotating/backing up"1 months" means "make a new backup if the lastbackup is from the preceding month". E.g if the last backup ofmyfileis from2019-02-01 thenbackup_time(myfile, age = "1 month") will onlycreate a backup if the current date is at least2019-03-01.
When pruning/limiting backup queues,"1 year" means "keep at least mostone year worth of backups". So if you callbackup_time(myfile, max_backups = "1 year") on2019-03-01, it will createa backup and then remove all backups ofmyfile before2019-01-01.
See Also
Examples
# setup example filestf <- tempfile("test", fileext = ".rds")saveRDS(cars, tf)backup(tf)backup(tf)backup_info(tf)list_backups(tf)n_backups(tf)newest_backup(tf)oldest_backup(tf)# cleanupprune_backups(tf, 0)n_backups(tf)file.remove(tf)Rotate or backup files
Description
Functions starting withbackup create backups of afile, while functionsstarting withrotate do the same but also replace the originalfilewith an empty one (this is useful for log rotation)
Note::rotate() and co will not work reliable on filenames that containdots but have no file extension (e.g.my.holiday.picture.jpg is OK butmy.holiday.picture is not)
prune_backups() physically deletes all backups of a filebased onmax_backups
prune_backups() physically deletes all backups of a filebased onmax_backups
Usage
rotate( file, size = 1, max_backups = Inf, compression = FALSE, dir = dirname(file), create_file = TRUE, dry_run = FALSE, verbose = dry_run)backup( file, size = 0, max_backups = Inf, compression = FALSE, dir = dirname(file), dry_run = FALSE, verbose = dry_run)prune_backups( file, max_backups, dir = dirname(file), dry_run = FALSE, verbose = dry_run)prune_identical_backups( file, dir = dirname(file), dry_run = FALSE, verbose = dry_run)rotate_date( file, age = 1, size = 1, max_backups = Inf, compression = FALSE, format = "%Y-%m-%d", dir = dirname(file), overwrite = FALSE, create_file = TRUE, now = Sys.Date(), dry_run = FALSE, verbose = dry_run)backup_date( file, age = 1, size = 1, max_backups = Inf, compression = FALSE, format = "%Y-%m-%d", dir = dirname(file), overwrite = FALSE, now = Sys.Date(), dry_run = FALSE, verbose = dry_run)rotate_time( file, age = -1, size = 1, max_backups = Inf, compression = FALSE, format = "%Y-%m-%d--%H-%M-%S", dir = dirname(file), overwrite = FALSE, create_file = TRUE, now = Sys.time(), dry_run = FALSE, verbose = dry_run)backup_time( file, age = -1, size = 1, max_backups = Inf, compression = FALSE, format = "%Y-%m-%d--%H-%M-%S", dir = dirname(file), overwrite = FALSE, now = Sys.time(), dry_run = FALSE, verbose = dry_run)Arguments
file |
|
size | scalar (if |
max_backups | maximum number of backups to keep
In addition for timestamped backups the following value are supported:
|
compression | Whether or not backups should be compressed |
dir |
|
create_file |
|
dry_run |
|
verbose |
|
age | minimum age after which to backup/rotate a file; can be
(if |
format | a scalar
|
overwrite |
|
now | The current |
Value
file as acharacter scalar (invisibly)
Side Effects
backup(),backup_date(), andbackup_time() may create files (if thespecified conditions are met). They may also delete backups, based onmax_backup.
rotate(),rotate_date() androtate_time() do the same, but inaddition delete the inputfile, or replace it with an empty file ifcreate_file == TRUE (the default).
prune_backups() may delete files, depending onmax_backups.
prune_backups() may delete files, depending onmax_backups.
Intervals
Inrotor, an interval is a character string in the form"<number> <interval>". The following intervals are possible:"day(s)","week(s)","month(s)","quarter(s)","year(s)".The plural"s" is optional (so"2 weeks" and"2 week" are equivalent).Please be aware that weeks areISOweeksand start on Monday (not Sunday as in some countries).
Interval strings can be used as arguments when backing up or rotating files,or for pruning backup queues (i.e. limiting the number of backups of asingle) file.
When rotating/backing up"1 months" means "make a new backup if the lastbackup is from the preceding month". E.g if the last backup ofmyfileis from2019-02-01 thenbackup_time(myfile, age = "1 month") will onlycreate a backup if the current date is at least2019-03-01.
When pruning/limiting backup queues,"1 year" means "keep at least mostone year worth of backups". So if you callbackup_time(myfile, max_backups = "1 year") on2019-03-01, it will createa backup and then remove all backups ofmyfile before2019-01-01.
See Also
Examples
# setup example filetf <- tempfile("test", fileext = ".rds")saveRDS(cars, tf)# create two backups of `tf``backup(tf)backup(tf)list_backups(tf) # find all backups of a file# If `size` is set, a backup is only created if the target file is at least# that big. This is more useful for log rotation than for backups.backup(tf, size = "100 mb") # no backup becuase `tf` is to smalllist_backups(tf)# If `dry_run` is TRUE, backup() only shows what would happen without# actually creating or deleting filesbackup(tf, size = "0.1kb", dry_run = TRUE)# rotate() is the same as backup(), but replaces `tf`` with an empty filerotate(tf)list_backups(tf)file.size(tf)file.size(list_backups(tf))# prune_backups() can remove old backupsprune_backups(tf, 1) # keep only one backuplist_backups(tf)# rotate/backup_date() adds a date instead of an index# you should not mix index backups and timestamp backups# so we clean up firstprune_backups(tf, 0)saveRDS(cars, tf)# backup_date() adds the date instead of an index to the filenamebackup_date(tf)# `age` sets the minimum age of the last backup before creating a new one.# the example below creates no new backup since it's less than a week# since the last.backup_date(tf, age = "1 week")# `now` overrides the current date.backup_date(tf, age = "1 year", now = "2999-12-31")list_backups(tf)# backup_time() creates backups with a full timestampbackup_time(tf)# It's okay to mix backup_date() and backup_time()list_backups(tf)# cleanupprune_backups(tf, 0)file.remove(tf)Serialize R objects to disk (with backup)
Description
Therotate_rds*() functions are wrappers aroundbase::saveRDS() thatcreate a backup of the destination file (if it exists) instead of justoverwriting it.
Usage
rotate_rds( object, file = "", ascii = FALSE, version = NULL, compress = TRUE, refhook = NULL, ..., on_change_only = FALSE)rotate_rds_date( object, file = "", ascii = FALSE, version = NULL, compress = TRUE, refhook = NULL, ..., age = -1L, on_change_only = FALSE)rotate_rds_time( object, file = "", ascii = FALSE, version = NULL, compress = TRUE, refhook = NULL, ..., age = -1L, on_change_only = FALSE)Arguments
object | R object to serialize. |
file | aconnection or the name of the file where theR objectis saved to or read from. |
ascii | a logical. If |
version | the workspace format version to use. |
compress | a logical specifying whether saving to a named file isto use |
refhook | a hook function for handling reference objects. |
... | Arguments passed on to
|
on_change_only |
|
age | minimum age after which to backup/rotate a file; can be
(if |
Value
the path tofile (invisibly)
Note
The default value forage is different forrotate_rds_date() (-1)than forrotate_date() (1) to make it a bit safer. This means if youexecuterotate_date() twice on the same file on a given day it willsilently not rotate the file, whilerotate_rds_date() will throw anerror.
Examples
dest <- tempfile()rotate_rds(iris, dest)rotate_rds(iris, dest)rotate_rds(iris, dest)list_backups(dest)# cleanupunlink(list_backups(dest))unlink(dest)