Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mnt: Switch to loggit2 #53

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Package: loggit
Package: loggit2
Title: Easy-to-Use, Dependencyless Logger for R
Description:
An easy-to-use 'ndjson' (newline-delimited 'JSON') logger.
Expand All @@ -18,8 +18,8 @@ Suggests:
knitr (>= 1.19),
rmarkdown (>= 1.8),
testthat (>= 3.0.0)
URL: https://github.com/MEO265/loggit
BugReports: https://github.com/MEO265/loggit/issues
URL: https://github.com/MEO265/loggit2
BugReports: https://github.com/MEO265/loggit2/issues
RoxygenNote: 7.3.0
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
Expand Down
146 changes: 6 additions & 140 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# loggit DEV
# loggit2 DEV

## New features
* `message()`, `warning()`, and `stop()` now accept conditions as input like their base R equivalents.
Expand Down Expand Up @@ -31,143 +31,9 @@
* Functions that were only for internal use (and were not exported) were marked as such
and are no longer visible in the index

## Other:
* The maintainership of `loggit` has been transferred from "Ryan Price" to "Matthias Ollech"
## Fork:
* The name changed from `loggit` to `loggit2`
* The maintainership has been transferred from "Ryan Price" to "Matthias Ollech"


# loggit 2.1.1

This is a small bugfix release for CRAN's sake that fixes two tests that would
sporadically fail; they relied on timestamps being equivalent between `want` and
`got` invocations.

# loggit 2.1.0

* Add `sanitizer` argument to `loggit()`, and an `unsanitizer` argument to
`read_logs()`. `loggit` chooses to reimplement basic JSON parsing
funcitonality instead of requiring a more full-featured external JSON library
like `jsonlite`. This reimplementation is string-pattern-based, and not based
on a more formal specification of JSON using an AST. As such, it isn't
brittle, per se, but it *is* weak to invalid JSON characters such as embedded
newlines, curly braces, double-quotes, some occurrences of commas or colons,
and the like.

Sanitizers are functions allow for custom replacements of invalid (nd)JSON
characters in the submitted log data. Unsanitizer functions perform the
opposite action: replacing sanitized output with their original values when
read back inttohe R session. If not provided, `loggit()` and `read_logs()`
will invoke the default sanitizer table, which (currently) maps string
replacements as follows:

| Character | Replacement in log file |
|:--------* | :---------------------* |
| `{` | `__LEFTBRACE__` |
| `}` | `__RIGHTBRACE__` |
| `"` | `__DBLQUOTE__` |
| `,` | `__COMMA__` |
| `\r` | `__CR__` |
| `\n` | `__LF__` |

Users may specify their own (un)sanitizers as functions that take & return
single strings, though they are regardless encouraged to not include invalid
characters in the logs in the first place. Please refer to the documentation
for more details.

* Removed `log_format` from `read_ndjson()`, because that was silly.

* Removed some erroneous functions as exports in the `NAMESPACE`.

# loggit 2.0.1

* Change behavior of handler masks to respect multiple arguments. Achieved by
changing explicit list indexing to `paste(..., collapse = "")` (#12).

* Remove `loggit::stopifnot` tests, since `stopifnot()` is not provided as a
handler mask by this package (`stopifnot()` has no custom messaging mechanic
to log).

# loggit 2.0.0

* `loggit()` now logs explicitly to `ndjson`-formatted log files. This is
handled internally by the `write_ndjson()` function. Each log entry is
self-contained on its own line, as its own JSON object. Previously, the log
files were each a single JSON *array*, with JSON objects as the elements. This
change provides several benefits over the old way of logging.

Please note that this change means that log entries should not contain any
embedded newline characters (`\r`, `\n`, or `\r\n`), as this will break the
logging format of the file. Your logs will still be written (with a
`base::warning`), but parsing the data with external tools or the included
`read_logs()` function may not behave correctly. `loggit` could one day
enforce these content rules internally, but the decision for now is to stay
out of the way of the user code generating the logs, and put the onus of
correction on the developer.

Note that despite the significant backend behavioral changes presented here,
the user-facing API for this package has changed very little (documented
below).

* Remove `dplyr` and `jsonlite` from `Imports`. This makes `loggit` entirely
free from external dependencies.

* Added `rotate_logs()`, which rotates the log file on disk based on its line
count. This is *not* an automated process, as depending on the size of your
log file, this could cause performance degradation if called on every *n*th
write. See function docs for more details.

* Added two vignettes: Getting Started, and Data Validation.

* `get_logs()` was renamed to `read_logs()`.

* Removed `log_detail` as an explicit argument to `loggit()`. This is a
non-breaking change, since `loggit()` will still pick up and log that field if
provided, but it is no longer a formal argument.

* `loggit()` no longer complains that a persistent log file is not set, and
instead relies on the user to take note of the logfile's location in the
assigned tempdir. This can be avoided entirely by setting the log file
explicitly at runtime, as has always been the case.

* All configuration `set` and `get` functions are all now in snake-case, e.g.
`set_logfile()` instead of `setLogFile()`.

* `set_timestamp_format()` now defaults to ISO-8601 time format, i.e.
`YYYY-MM-DDTHH:MM:SS+z`. The function itself still provides no means to set a
timezone, and this is deliberate. This ensures that all software on the host
reports identical timezone data by default.

* Removed package startup message; the previous message would have broken
formatting consistency if capturing logs via `stdout`/`stderr`.

# loggit 1.2.0

* Add error on calls to loggit(), indicating breaking changes upcoming in v2.0.
Users can suppress the error by running agree_to_upcoming_loggit_updates()
once anywhere in their script or package before making a call to loggit().

# loggit version 1.1.1

* Automatically coerce any entries for 'log_lvl' and 'log_msg' fields to be
character.

* (Github-only): loggit() no longer allows for a data frame to be passed as an
argument; the underlying code was not writen very well, and I got ahead of
myself in throwing it in there. loggit() is, however, still vectorized by
nature, so users can still pass vectors to, for example, the log_detail
argument, and values will be recycled according to R's usual recycling rules.

# loggit version 1.1.0

* Add get_logs(), which returns a data frame of a provided log file. Returns the
current log file by default.

* (Github-only): loggit() now allows for a data frame to be passed as the sole
argument, and have its results be logged. Required column names are the same
as the first two arguments to loggit(): "log_lvl" and "log_msg". Any
additional number of columns can be supplied.

# loggit version 1.0.0

* This is the first CRAN release of the loggit package. Included features are
the masking functions for base R's exception handlers (message, warning, and
stop), as well as the loggit() function, which is wrapped in those calls.
# Previous versions
For older versions, see Ryan Price's `loggit` package
2 changes: 1 addition & 1 deletion R/configurations.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
#' Set the log file that loggit will write to.
#'
#' @param logfile Absolut or relative path to log file.
#' An attempt is made to convert the path into a canonical absolute form using [normalizePath()].

Check warning on line 10 in R/configurations.R

View workflow job for this annotation

GitHub Actions / lint

file=R/configurations.R,line=10,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 97 characters.
#' If `NULL` will set to `<tmpdir>/loggit.log`.
#' @param confirm Print confirmation of log file setting? Defaults to `TRUE`.
#' @param create Create the log file if it does not exist? Defaults to `TRUE`.
#'
#' @details No logs outside of a temporary directory will be written until this is set explicitly, as per CRAN policy.

Check warning on line 15 in R/configurations.R

View workflow job for this annotation

GitHub Actions / lint

file=R/configurations.R,line=15,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 118 characters.
#' Therefore, the default behavior is to create a file named `loggit.log` in your system's temporary directory.

Check warning on line 16 in R/configurations.R

View workflow job for this annotation

GitHub Actions / lint

file=R/configurations.R,line=16,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 111 characters.
#'
#' @examples set_logfile(file.path(tempdir(), "loggit.log"))
#'
Expand All @@ -22,7 +22,7 @@
if (is.null(logfile)) {
logfile <- file.path(tempdir(), "loggit.log")
}
if(create && !file.exists(logfile)) file.create(logfile)

Check warning on line 25 in R/configurations.R

View workflow job for this annotation

GitHub Actions / lint

file=R/configurations.R,line=25,col=5,[spaces_left_parentheses_linter] Place a space before left parenthesis, except in a function call.
.config$logfile <- normalizePath(logfile, winslash = "/", mustWork = FALSE)
if (confirm) base::message("Log file set to ", .config$logfile)
}
Expand All @@ -30,7 +30,7 @@

#' Get Log File
#'
#' Return the log file that loggit will write to.
#' Return the log file that `loggit()` will write to.
#'
#' @examples get_logfile()
#'
Expand All @@ -44,7 +44,7 @@
#'
#' Set timestamp format for use in output logs.
#'
#' @details This function performs no time format validations, but will echo out the current time in

Check warning on line 47 in R/configurations.R

View workflow job for this annotation

GitHub Actions / lint

file=R/configurations.R,line=47,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 100 characters.
#' the provided format for manual validation.
#'
#' This function provides no means of setting a timezone, and instead relies on
Expand All @@ -59,7 +59,7 @@
#' @examples set_timestamp_format("%Y-%m-%d %H:%M:%S")
#'
#' @export
set_timestamp_format <- function(ts_format = "%Y-%m-%dT%H:%M:%S%z", confirm = TRUE) {

Check warning on line 62 in R/configurations.R

View workflow job for this annotation

GitHub Actions / lint

file=R/configurations.R,line=62,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 85 characters.
.config$ts_format <- ts_format
if (confirm) {
base::message(
Expand Down
10 changes: 5 additions & 5 deletions R/handlers.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#'
#' @inherit base::message params return
#'
#' @param .loggit Should loggit function execute? Defaults to `TRUE`.
#' @param echo Should loggit's log entry be echoed to the console, as well? Defaults to `TRUE`.
#' @param .loggit Should `loggit()` execute? Defaults to `TRUE`.
#' @param echo Should `loggit()`'s log entry be echoed to the console, as well? Defaults to `TRUE`.

Check warning on line 9 in R/handlers.R

View workflow job for this annotation

GitHub Actions / lint

file=R/handlers.R,line=9,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 99 characters.
#'
#' @family handlers
#'
Expand All @@ -14,10 +14,10 @@
#' if (2 < 1) message("Don't say such silly things!")
#'
#' @export
message <- function(..., domain = NULL, appendLF = TRUE, .loggit = TRUE, echo = TRUE) {

Check warning on line 17 in R/handlers.R

View workflow job for this annotation

GitHub Actions / lint

file=R/handlers.R,line=17,col=41,[object_name_linter] Variable and function name style should match snake_case or symbols.

Check warning on line 17 in R/handlers.R

View workflow job for this annotation

GitHub Actions / lint

file=R/handlers.R,line=17,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 87 characters.
# If the input is a condition, the base function does not allow additional input

Check warning on line 18 in R/handlers.R

View workflow job for this annotation

GitHub Actions / lint

file=R/handlers.R,line=18,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 82 characters.
# If the input is not a condition, the call of the message must be set manually
# to avoid loggit::message being displayed as a call
# to avoid loggit2::message being displayed as a call
is_condition <- (...length() == 1L && inherits(..1, "condition"))
call <- sys.call()

Expand Down Expand Up @@ -60,7 +60,7 @@
domain = NULL, .loggit = TRUE, echo = TRUE) {
# If the input is a condition, the base function does not allow additional input
# If the input is not a condition, the call of the warning must be set manually
# to avoid loggit::warning being displayed as a call
# to avoid loggit2::warning being displayed as a call
is_condition <- (...length() == 1L && inherits(..1, "condition"))
call <- find_call()

Expand Down Expand Up @@ -101,7 +101,7 @@
stop <- function(..., call. = TRUE, domain = NULL, .loggit = TRUE, echo = TRUE) {
# If the input is a condition, the base function does not allow additional input
# If the input is not a condition, the call of the error must be set manually
# to avoid loggit::stop being displayed as a call
# to avoid loggit2::stop being displayed as a call
is_condition <- (...length() == 1L && inherits(..1, "condition"))
call <- find_call()

Expand Down
2 changes: 1 addition & 1 deletion R/json.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ sanitizer_map <- list(
#' | `\n` | `__LF__` |
#'
#' This type of function is needed because because some characters in a JSON cannot appear unescaped and
#' since `loggit` reimplements its own very simple string-based JSON parser.
#' since `loggit2` reimplements its own very simple string-based JSON parser.
#'
#' @param string A character vector
#'
Expand Down
60 changes: 30 additions & 30 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,47 +20,47 @@ options(width = 150)
Easy-to-use, dependencyless Logger for R
==================================
<!-- badges: start -->
[![CRAN\_Status\_Badge](http://www.r-pkg.org/badges/version/loggit)](https://cran.r-project.org/package=loggit)
[![Downloads](https://cranlogs.r-pkg.org/badges/grand-total/loggit)](https://cran.r-project.org/package=loggit)
[![R-CMD-check](https://github.com/MEO265/loggit/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/MEO265/loggit/actions/workflows/R-CMD-check.yaml)
[![codecov](https://codecov.io/gh/MEO265/loggit/graph/badge.svg)](https://codecov.io/gh/MEO265/loggit)
[![CRAN\_Status\_Badge](http://www.r-pkg.org/badges/version/loggit2)](https://cran.r-project.org/package=loggit2)
[![Downloads](https://cranlogs.r-pkg.org/badges/grand-total/loggit2)](https://cran.r-project.org/package=loggit2)
[![R-CMD-check](https://github.com/MEO265/loggit2/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/MEO265/loggit2/actions/workflows/R-CMD-check.yaml)
[![codecov](https://codecov.io/gh/MEO265/loggit2/graph/badge.svg)](https://codecov.io/gh/MEO265/loggit2)
<!-- badges: end -->

------------------------------------------------------------------------

`loggit` is an easy-to-use [`ndJSON`](https://github.com/ndjson/ndjson-spec) logging library for R software,
`loggit2` is an easy-to-use [`ndJSON`](https://github.com/ndjson/ndjson-spec) logging library for R software,
with _zero_ external dependencies.

Please see below for some quick examples, and read the [vignettes](https://cran.r-project.org/web/packages/loggit/vignettes/) for the
Please see below for some quick examples, and read the [vignettes](https://cran.r-project.org/web/packages/loggit2/vignettes/) for the
Getting Started guide.

Why use `loggit`?
Why use `loggit2`?
-----------------

`loggit` takes a modern approach to logging in R:
`loggit2` takes a modern approach to logging in R:

- Opting to use the JSON format
- Highly flexible log streams
- Enables log data analysis on the same host
- _Zero_ external dependencies

Additionally, the boilerplate to get going with `loggit` is minimal at worst.
No need to write custom formatters, handlers, levels, etc. -- ***just loggit!***
Additionally, the boilerplate to get going with `loggit2` is minimal at worst.
No need to write custom formatters, handlers, levels, etc. -- ***just loggit2!***

Usage
--------------

The quickest way to get up & running with `loggit` is to do nearly nothing.
The quickest way to get up & running with `loggit2` is to do nearly nothing.

`loggit` provides a set of wrappings for base R's `message()`, `warning()`, and
`loggit2` provides a set of wrappings for base R's `message()`, `warning()`, and
`stop()` functions that maintain identical functionality, making it sufficient to
import the `loggit` namespace, for example by using `library("loggit")`, or by
prefixing `loggit::` at the desired locations.
import the `loggit2` namespace, for example by using `library("loggit2")`, or by
prefixing `loggit2::` at the desired locations.

```{r, error = TRUE}
loggit::message("This is a message")
loggit::warning("This is a warning")
loggit::stop("This is an error")
loggit2::message("This is a message")
loggit2::warning("This is a warning")
loggit2::stop("This is an error")
```

You can suppress the additional console output by using `echo = FALSE` and
Expand All @@ -69,42 +69,42 @@ will be filled in the background).

```{r, error = TRUE}
base::message("This is another message")
loggit::message("This is another message", echo = FALSE)
loggit2::message("This is another message", echo = FALSE)

base::warning("This is another warning")
loggit::warning("This is another warning", echo = FALSE)
loggit2::warning("This is another warning", echo = FALSE)

base::stop("This is another error")
loggit::stop("This is another error", echo = FALSE)
loggit2::stop("This is another error", echo = FALSE)
```

You can also use `loggit()` directly to compose much more custom
logs, including ***entirely custom fields*** (and prevent throwing actual conditions).
`loggit` doesn't require that you set custom logger objects or anything like that:
`loggit2` doesn't require that you set custom logger objects or anything like that:
just throw whatever you want at it, and it'll become a structured log.

```{r loggit}
loggit::loggit("ERROR", "This will log an error", anything_else = "you want to include")
```{r loggit2}
loggit2::loggit("ERROR", "This will log an error", anything_else = "you want to include")

# Read log file into data frame to implement logic based on entries
loggit::read_logs()
loggit2::read_logs()
```

Check out the [vignettes](https://cran.r-project.org/web/packages/loggit/vignettes/) for more details.
Check out the [vignettes](https://cran.r-project.org/web/packages/loggit2/vignettes/) for more details.

Installation
------------

You can install the latest CRAN release of `loggit` via
You can install the latest CRAN release of `loggit2` via

install.packages("loggit")
install.packages("loggit2")

or, get the latest development version from GitHub via

devtools::install_github("MEO265/loggit")
devtools::install_github("MEO265/loggit2")

Acknowledgments
-----------
This package is based on the [eponymous package by Ryan Price](https://github.com/ryapric/loggit), specifically version 2.1.1.
This package is based on the [eponymous package by Ryan Price](https://github.com/ryapric/loggit2), specifically version 2.1.1.

Due to technical reasons, this repository is not a GitHub fork of [Ryan's repository](https://github.com/ryapric/loggit).
Due to technical reasons, this repository is not a GitHub fork of [Ryan's repository](https://github.com/ryapric/loggit2).
Loading