Skip to content

Commit

Permalink
Polish the README
Browse files Browse the repository at this point in the history
* Convert to .Rmd so we can show live logger output
* Minimise the coloured output since the main goal is to show that it exists
* Update related work section since most of the GitHub packages haven't been update in ~7 years and I think you can be more explicit about the benefits of logger
* Fix a few typos and generally proofread the text.
* Hide the links to the pkgdown site on the pkgdown site :)
  • Loading branch information
hadley committed Jul 31, 2024
1 parent 1878fd0 commit f767d9c
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 96 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ dev-resources
^pkgdown$
^\.github$
revdep
^README\.Rmd$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
docs/
README.html
117 changes: 117 additions & 0 deletions README.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
output: github_document
---

<!-- README.md is generated from README.Rmd. Please edit that file -->

```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```

# logger

<!-- badges: start -->
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![CRAN](https://www.r-pkg.org/badges/version/logger)](https://cran.r-project.org/package=logger) [![Build Status](https://github.com/daroczig/logger/workflows/R-CMD-check/badge.svg)](https://github.com/daroczig/logger/actions) [![Code Coverage](https://codecov.io/gh/daroczig/logger/branch/master/graph/badge.svg)](https://app.codecov.io/gh/daroczig/logger) [![A Mikata Project](https://mikata.dev/img/badge.svg)](https://mikata.dev)
<!-- badges: end -->

A lightweight, modern and flexibly logging utility for R -- heavily inspired by the `futile.logger` R package and `logging` Python module.

## Installation

[![CRAN version](http://www.r-pkg.org/badges/version-ago/logger)](https://cran.r-project.org/package=logger)

```{r}
#| eval: false
install.packages('logger')
```

The most recent, development version of `logger` can also be installed from GitHub:

```{r}
#| eval: false
# install.packages("pak")
pak::pak('daroczig/logger')
```

## Quick example

Setting the log level threshold to something low and logging various messages in ad-hoc and programmatic ways:

```{r}
#| include: false
library(logger)
log_appender(appender_stdout)
```

```{r}
library(logger)
log_threshold(DEBUG)
log_info('Script starting up...')
pkgs <- available.packages()
log_info('There are {nrow(pkgs)} R packages hosted on CRAN!')
for (letter in letters) {
lpkgs <- sum(grepl(letter, pkgs[, 'Package'], ignore.case = TRUE))
log_level(
if (lpkgs < 5000) TRACE else DEBUG,
'{lpkgs} R packages including the {shQuote(letter)} letter'
)
}
log_warn('There might be many, like {1:2} or more warnings!!!')
```

You can even use a custom log layout to render the log records with colors, asyou can see in `demo(colors, package = 'logger', echo = FALSE)`:

<img src="man/figures/colors.png" alt="colored log output">

But you could set up any custom colors and layout, eg using custom colors only for the log levels, make it grayscale, include the calling function or R package namespace with specific colors etc. For more details, see `vignette("write_custom_extensions")`.

## Related work

There are many other logging packages available on CRAN:

- [`futile.logger`](https://cran.r-project.org/package=futile.logger): probably the most popular `log4j` variant (and I'm a big fan)
- [`logging`](https://cran.r-project.org/package=logging): just like Python's `logging` package
- [`lgr`](https://cran.r-project.org/package=lgr): built on top of R6.
- [`loggit`](https://cran.r-project.org/package=loggit): capture `message`, `warning` and `stop` function messages in a JSON file
- [`log4r`](https://cran.r-project.org/package=log4r): `log4j`-based, object-oriented logger
- [`rsyslog`](https://cran.r-project.org/package=rsyslog): logging to `syslog` on 'POSIX'-compatible operating systems
- [`lumberjack`](https://cran.r-project.org/package=lumberjack): provides a special operator to log changes in data

Why use logger? I decided to write the `n+1`th extensible `log4j` logger that fits my liking --- and hopefully yours as well --- the the aim to:

- Keep it close to `log4j`.
- Respect the modern function/variable naming conventions and general R coding style.
- By default, rely on `glue()` when it comes to formatting / rendering log messages, but keep it flexible if others prefer `sprintf()` (e.g. for performance reasons) or other functions.
- Support vectorization (eg passing a vector to be logged on multiple lines).
- Make it easy to extend with new features (e.g. custom layouts, message formats and output).
- Prepare for writing to various services, streams etc
- Provide support for namespaces, preferably automatically finding and creating a custom namespace for all R packages writing log messages, each with optionally configurable log level threshold, message and output formats.
- Allow stacking loggers to implement logger hierarchy -- even within a namespace, so that the very same `log` call can write all the `TRACE` log messages to the console, while only pushing `ERROR`s to DataDog and eg `INFO` messages to CloudWatch.
- Optionally colorize log message based on the log level.
- Make logging fun!

Welcome to the [Bazaar](https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar)! If you already use any of the above packages for logging, you might find `vignette("migration")` useful.

::: .pkgdown-hide

## Interested in more details?

Check out the main documentation site at <https://daroczig.github.io/logger> or the vignettes on the below topics:

* [Introduction to logger](https://daroczig.github.io/logger/articles/Intro.html)
* [The Anatomy of a Log Request](https://daroczig.github.io/logger/articles/anatomy.html)
* [Customizing the Format and the Destination of a Log Record](https://daroczig.github.io/logger/articles/customize_logger.html)
* [Writing Custom Logger Extensions](https://daroczig.github.io/logger/articles/write_custom_extensions.html)
* [Migration Guide from other logging packages](https://daroczig.github.io/logger/articles/migration.html)
* [Logging from R Packages](https://daroczig.github.io/logger/articles/r_packages.html)
* [Simple Benchmarks on Performance](https://daroczig.github.io/logger/articles/performance.html)

:::
222 changes: 126 additions & 96 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,133 +1,163 @@

<!-- README.md is generated from README.Rmd. Please edit that file -->

# logger

<!-- badges: start -->
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![CRAN](https://www.r-pkg.org/badges/version/logger)](https://cran.r-project.org/package=logger) [![Build Status](https://github.com/daroczig/logger/workflows/R-CMD-check/badge.svg)](https://github.com/daroczig/logger/actions) [![Code Coverage](https://codecov.io/gh/daroczig/logger/branch/master/graph/badge.svg)](https://app.codecov.io/gh/daroczig/logger) [![A Mikata Project](https://mikata.dev/img/badge.svg)](https://mikata.dev)

[![Project Status: Active – The project has reached a stable, usable
state and is being actively
developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![CRAN](https://www.r-pkg.org/badges/version/logger)](https://cran.r-project.org/package=logger)
[![Build
Status](https://github.com/daroczig/logger/workflows/R-CMD-check/badge.svg)](https://github.com/daroczig/logger/actions)
[![Code
Coverage](https://codecov.io/gh/daroczig/logger/branch/master/graph/badge.svg)](https://app.codecov.io/gh/daroczig/logger)
[![A Mikata
Project](https://mikata.dev/img/badge.svg)](https://mikata.dev)
<!-- badges: end -->

A lightweight, modern and flexibly logging utility for R -- heavily inspired by the `futile.logger` R package and `logging` Python module.
A lightweight, modern and flexibly logging utility for R – heavily
inspired by the `futile.logger` R package and `logging` Python module.

## Installation

[![CRAN version](http://www.r-pkg.org/badges/version-ago/logger)](https://cran.r-project.org/package=logger)
[![CRAN
version](http://www.r-pkg.org/badges/version-ago/logger)](https://cran.r-project.org/package=logger)

```r
``` r
install.packages('logger')
```

The most recent, development version of `logger` can also be installed from GitHub:
The most recent, development version of `logger` can also be installed
from GitHub:

```r
remotes::install_github('daroczig/logger')
``` r
# install.packages("pak")
pak::pak('daroczig/logger')
```

## Quick example

Setting the log level threshold to something low and logging various messages in ad-hoc and programmatic ways:
Setting the log level threshold to something low and logging various
messages in ad-hoc and programmatic ways:

```r
``` r
library(logger)
log_threshold(DEBUG)
log_info('Script starting up...')
#> INFO [2018-20-11 22:49:36] Script starting up...
#> INFO [2024-07-31 07:37:34] Script starting up...

pkgs <- available.packages()
log_info('There are {nrow(pkgs)} R packages hosted on CRAN!')
#> INFO [2018-20-11 22:49:37] There are 13433 R packages hosted on CRAN!
#> INFO [2024-07-31 07:37:34] There are 21122 R packages hosted on CRAN!

for (letter in letters) {
lpkgs <- sum(grepl(letter, pkgs[, 'Package'], ignore.case = TRUE))
log_level(if (lpkgs < 5000) TRACE else DEBUG,
'{lpkgs} R packages including the {shQuote(letter)} letter')
lpkgs <- sum(grepl(letter, pkgs[, 'Package'], ignore.case = TRUE))
log_level(
if (lpkgs < 5000) TRACE else DEBUG,
'{lpkgs} R packages including the {shQuote(letter)} letter'
)
}
#> DEBUG [2018-20-11 22:49:38] 6300 R packages including the 'a' letter
#> DEBUG [2018-20-11 22:49:38] 6772 R packages including the 'e' letter
#> DEBUG [2018-20-11 22:49:38] 5412 R packages including the 'i' letter
#> DEBUG [2018-20-11 22:49:38] 7014 R packages including the 'r' letter
#> DEBUG [2018-20-11 22:49:38] 6402 R packages including the 's' letter
#> DEBUG [2018-20-11 22:49:38] 5864 R packages including the 't' letter
#> DEBUG [2024-07-31 07:37:34] 10188 R packages including the 'a' letter
#> DEBUG [2024-07-31 07:37:34] 7013 R packages including the 'c' letter
#> DEBUG [2024-07-31 07:37:34] 5750 R packages including the 'd' letter
#> DEBUG [2024-07-31 07:37:34] 10902 R packages including the 'e' letter
#> DEBUG [2024-07-31 07:37:34] 8821 R packages including the 'i' letter
#> DEBUG [2024-07-31 07:37:34] 7055 R packages including the 'l' letter
#> DEBUG [2024-07-31 07:37:34] 7039 R packages including the 'm' letter
#> DEBUG [2024-07-31 07:37:34] 6661 R packages including the 'n' letter
#> DEBUG [2024-07-31 07:37:34] 7859 R packages including the 'o' letter
#> DEBUG [2024-07-31 07:37:34] 6579 R packages including the 'p' letter
#> DEBUG [2024-07-31 07:37:34] 11224 R packages including the 'r' letter
#> DEBUG [2024-07-31 07:37:34] 10292 R packages including the 's' letter
#> DEBUG [2024-07-31 07:37:34] 9526 R packages including the 't' letter

log_warn('There might be many, like {1:2} or more warnings!!!')
#> WARN [2018-20-11 22:49:39] There might be many, like 1 or more warnings!!!
#> WARN [2018-20-11 22:49:39] There might be many, like 2 or more warnings!!!
```

Setting a custom log layout to render the log records with colors:

```r
library(logger)
log_layout(layout_glue_colors)
log_threshold(TRACE)
log_info('Starting the script...')
log_debug('This is the second log line')
log_trace('Note that the 2nd line is being placed right after the 1st one.')
log_success('Doing pretty well so far!')
log_warn('But beware, as some errors might come :/')
log_error('This is a problem')
log_debug('Note that getting an error is usually bad')
log_error('This is another problem')
log_fatal('The last problem')
#> WARN [2024-07-31 07:37:34] There might be many, like 1 or more warnings!!!
#> WARN [2024-07-31 07:37:34] There might be many, like 2 or more warnings!!!
```

Or simply run the related demo:

```r
demo(colors, package = 'logger', echo = FALSE)
```
You can even use a custom log layout to render the log records with
colors, asyou can see in
`demo(colors, package = 'logger', echo = FALSE)`:

<img src="man/figures/colors.png" alt="colored log output">

But you could set up any custom colors and layout, eg using custom colors only for the log levels, make it grayscale, include the calling function or R package namespace with specific colors etc. For more details, see the related vignettes.

## Why yet another logging R package?

Although there are multiple pretty good options already hosted on CRAN when it comes to logging in R, such as

- [`futile.logger`](https://cran.r-project.org/package=futile.logger): probably the most popular `log4j` variant (and I'm a big fan)
- [`logging`](https://cran.r-project.org/package=logging): just like Python's `logging` package
- [`loggit`](https://cran.r-project.org/package=loggit): capture `message`, `warning` and `stop` function messages in a JSON file
- [`log4r`](https://cran.r-project.org/package=log4r): `log4j`-based, object-oriented logger
- [`rsyslog`](https://cran.r-project.org/package=rsyslog): logging to `syslog` on 'POSIX'-compatible operating systems
- [`lumberjack`](https://cran.r-project.org/package=lumberjack): provides a special operator to log changes in data

Also many more work-in-progress R packages hosted on eg GitHub, such as

- https://github.com/smbache/loggr
- https://github.com/nfultz/tron
- https://github.com/metrumresearchgroup/logrrr
- https://github.com/lorenzwalthert/drogger
- https://github.com/s-fleck/yog

But some/most of these packages are

- not actively maintained any more, and/or maintainers are not being open for new features / patches
- not being modular enough for extensions
- prone to scoping issues
- using strange syntax elements, eg dots in function names or object-oriented approaches not being very familiar to most R users
- requires a lot of typing and code repetitions

So based on all the above subjective opinions, I decided to write the `n+1`th extensible `log4j` logger that fits my liking -- and hopefully yours as well -- with the focus being on:

- keep it close to `log4j`
- respect the most recent function / variable naming conventions and general R coding style
- by default, rely on `glue` when it comes to formatting / rendering log messages, but keep it flexible if others prefer `sprintf` (eg for performance reasons) or other functions
- support vectorization (eg passing a vector to be logged on multiple lines)
- make it easy to extend with new features (eg custom layouts, message formats and output)
- prepare for writing to various services, streams etc
- provide support for namespaces, preferably automatically finding and creating a custom namespace for all R packages writing log messages, each with optionally configurable log level threshold, message and output formats
- allow stacking loggers to implement logger hierarchy -- even within a namespace, so that the very same `log` call can write all the `TRACE` log messages to the console, while only pushing `ERROR`s to DataDog and eg `INFO` messages to CloudWatch
- optionally colorize log message based on the log level
- make logging fun

Welcome to the [Bazaar](https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar), and if you have happened to already use any of the above mentioned R packages for logging, you might find useful the [Migration Guide](https://daroczig.github.io/logger/articles/migration.html).
But you could set up any custom colors and layout, eg using custom
colors only for the log levels, make it grayscale, include the calling
function or R package namespace with specific colors etc. For more
details, see `vignette("write_custom_extensions")`.

## Related work

There are many other logging packages available on CRAN:

- [`futile.logger`](https://cran.r-project.org/package=futile.logger):
probably the most popular `log4j` variant (and I’m a big fan)
- [`logging`](https://cran.r-project.org/package=logging): just like
Python’s `logging` package
- [`lgr`](https://cran.r-project.org/package=lgr): built on top of R6.
- [`loggit`](https://cran.r-project.org/package=loggit): capture
`message`, `warning` and `stop` function messages in a JSON file
- [`log4r`](https://cran.r-project.org/package=log4r): `log4j`-based,
object-oriented logger
- [`rsyslog`](https://cran.r-project.org/package=rsyslog): logging to
`syslog` on ‘POSIX’-compatible operating systems
- [`lumberjack`](https://cran.r-project.org/package=lumberjack):
provides a special operator to log changes in data

Why use logger? I decided to write the `n+1`th extensible `log4j` logger
that fits my liking — and hopefully yours as well — the the aim to:

- Keep it close to `log4j`.
- Respect the modern function/variable naming conventions and general R
coding style.
- By default, rely on `glue()` when it comes to formatting / rendering
log messages, but keep it flexible if others prefer `sprintf()`
(e.g. for performance reasons) or other functions.
- Support vectorization (eg passing a vector to be logged on multiple
lines).
- Make it easy to extend with new features (e.g. custom layouts, message
formats and output).
- Prepare for writing to various services, streams etc
- Provide support for namespaces, preferably automatically finding and
creating a custom namespace for all R packages writing log messages,
each with optionally configurable log level threshold, message and
output formats.
- Allow stacking loggers to implement logger hierarchy – even within a
namespace, so that the very same `log` call can write all the `TRACE`
log messages to the console, while only pushing `ERROR`s to DataDog
and eg `INFO` messages to CloudWatch.
- Optionally colorize log message based on the log level.
- Make logging fun!

Welcome to the
[Bazaar](https://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar)! If
you already use any of the above packages for logging, you might find
`vignette("migration")` useful.

<div class=".pkgdown-hide">

## Interested in more details?

Check out the main documentation site at https://daroczig.github.io/logger or the vignettes on the below topics:

* [Introduction to logger](https://daroczig.github.io/logger/articles/Intro.html)
* [The Anatomy of a Log Request](https://daroczig.github.io/logger/articles/anatomy.html)
* [Customizing the Format and the Destination of a Log Record](https://daroczig.github.io/logger/articles/customize_logger.html)
* [Writing Custom Logger Extensions](https://daroczig.github.io/logger/articles/write_custom_extensions.html)
* [Migration Guide from other logging packages](https://daroczig.github.io/logger/articles/migration.html)
* [Logging from R Packages](https://daroczig.github.io/logger/articles/r_packages.html)
* [Simple Benchmarks on Performance](https://daroczig.github.io/logger/articles/performance.html)
Check out the main documentation site at
<https://daroczig.github.io/logger> or the vignettes on the below
topics:

- [Introduction to
logger](https://daroczig.github.io/logger/articles/Intro.html)
- [The Anatomy of a Log
Request](https://daroczig.github.io/logger/articles/anatomy.html)
- [Customizing the Format and the Destination of a Log
Record](https://daroczig.github.io/logger/articles/customize_logger.html)
- [Writing Custom Logger
Extensions](https://daroczig.github.io/logger/articles/write_custom_extensions.html)
- [Migration Guide from other logging
packages](https://daroczig.github.io/logger/articles/migration.html)
- [Logging from R
Packages](https://daroczig.github.io/logger/articles/r_packages.html)
- [Simple Benchmarks on
Performance](https://daroczig.github.io/logger/articles/performance.html)

</div>

0 comments on commit f767d9c

Please sign in to comment.