├── docs
├── CNAME
├── reference
│ ├── Rplot001.png
│ ├── index.html
│ ├── log_info.html
│ ├── log_debug.html
│ ├── log_fatal.html
│ ├── log_trace.html
│ ├── log_error.html
│ └── log_warn.html
├── pkgdown.yml
├── sitemap.xml
├── link.svg
├── bootstrap-toc.css
├── docsearch.js
├── pkgdown.js
├── authors.html
├── bootstrap-toc.js
├── LICENSE-text.html
├── 404.html
├── news
│ └── index.html
├── LICENSE.html
├── pkgdown.css
├── docsearch.css
└── index.html
├── .github
├── .gitignore
└── workflows
│ ├── rspm-merge.yml
│ ├── R-CMD-check.yaml
│ └── rhub.yaml
├── _pkgdown.yml
├── LICENSE
├── .gitignore
├── tests
├── testthat.R
└── testthat
│ └── test-helpers.R
├── CRAN-RELEASE
├── .Rbuildignore
├── NAMESPACE
├── NEWS.md
├── rlog.Rproj
├── man
├── log_info.Rd
├── log_debug.Rd
├── log_fatal.Rd
├── log_trace.Rd
├── log_warn.Rd
└── log_error.Rd
├── cran-comments.md
├── DESCRIPTION
├── R
├── log_msg.R
└── helpers.R
├── LICENSE.md
└── README.md
/docs/CNAME:
--------------------------------------------------------------------------------
1 | rlog.sellorm.com
--------------------------------------------------------------------------------
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/_pkgdown.yml:
--------------------------------------------------------------------------------
1 | url: https://rlog.sellorm.com
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2021
2 | COPYRIGHT HOLDER: rlog authors
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(rlog)
3 |
4 | test_check("rlog")
5 |
--------------------------------------------------------------------------------
/docs/reference/Rplot001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sellorm/rlog/HEAD/docs/reference/Rplot001.png
--------------------------------------------------------------------------------
/CRAN-RELEASE:
--------------------------------------------------------------------------------
1 | This package was submitted to CRAN on 2021-02-22.
2 | Once it is accepted, delete this file and tag the release (commit 8888830).
3 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^rlog\.Rproj$
2 | ^\.Rproj\.user$
3 | ^LICENSE\.md$
4 | ^_pkgdown\.yml$
5 | ^docs$
6 | ^pkgdown$
7 | ^cran-comments\.md$
8 | ^CRAN-RELEASE$
9 | ^\.github$
10 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export(log_debug)
4 | export(log_error)
5 | export(log_fatal)
6 | export(log_info)
7 | export(log_trace)
8 | export(log_warn)
9 |
--------------------------------------------------------------------------------
/docs/pkgdown.yml:
--------------------------------------------------------------------------------
1 | pandoc: 2.11.4
2 | pkgdown: 1.6.1
3 | pkgdown_sha: ~
4 | articles: {}
5 | last_built: 2021-02-21T20:07Z
6 | urls:
7 | reference: https://rlog.sellorm.com/reference
8 | article: https://rlog.sellorm.com/articles
9 |
10 |
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | # rlog (development version)
2 |
3 | * The "log_" functions ("log_error", "log_info", etc) now accepts any number of
4 | arguments via ... in the function call.
5 |
6 | # rlog 0.1.0
7 |
8 | * Prepare for CRAN submission
9 |
10 | # rlog 0.0.0.9000
11 |
12 | * Added a `NEWS.md` file to track changes to the package.
13 |
--------------------------------------------------------------------------------
/rlog.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 |
3 | RestoreWorkspace: No
4 | SaveWorkspace: No
5 | AlwaysSaveHistory: Default
6 |
7 | EnableCodeIndexing: Yes
8 | UseSpacesForTab: Yes
9 | NumSpacesForTab: 2
10 | Encoding: UTF-8
11 |
12 | RnwWeave: Sweave
13 | LaTeX: pdfLaTeX
14 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 | LineEndingConversion: Posix
18 |
19 | BuildType: Package
20 | PackageUseDevtools: Yes
21 | PackageInstallArgs: --no-multiarch --with-keep.source
22 | PackageRoxygenize: rd,collate,namespace
23 |
--------------------------------------------------------------------------------
/man/log_info.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/helpers.R
3 | \name{log_info}
4 | \alias{log_info}
5 | \title{Log an info message}
6 | \usage{
7 | log_info(message, ...)
8 | }
9 | \arguments{
10 | \item{message}{your message to log}
11 |
12 | \item{...}{more elements of the message, to be concatenated with the message}
13 | }
14 | \value{
15 | invisibly returns TRUE/FALSE
16 | }
17 | \description{
18 | Log messages will only be emitted if the log priority matches or is higher
19 | than the priority of your message
20 | }
21 | \examples{
22 | \dontrun{
23 | log_info("This is an info message")
24 | Sys.setenv("LOG_LEVEL" = "TRACE")
25 | log_info("This is an info message")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/man/log_debug.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/helpers.R
3 | \name{log_debug}
4 | \alias{log_debug}
5 | \title{Log a debug message}
6 | \usage{
7 | log_debug(message, ...)
8 | }
9 | \arguments{
10 | \item{message}{your message to log}
11 |
12 | \item{...}{more elements of the message, to be concatenated with the message}
13 | }
14 | \value{
15 | invisibly returns TRUE/FALSE
16 | }
17 | \description{
18 | Log messages will only be emitted if the log priority matches or is higher
19 | than the priority of your message
20 | }
21 | \examples{
22 | \dontrun{
23 | log_debug("This is a debug message")
24 | Sys.setenv("LOG_LEVEL" = "TRACE")
25 | log_debug("This is a debug message")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/man/log_fatal.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/helpers.R
3 | \name{log_fatal}
4 | \alias{log_fatal}
5 | \title{Log a fatal message}
6 | \usage{
7 | log_fatal(message, ...)
8 | }
9 | \arguments{
10 | \item{message}{your message to log}
11 |
12 | \item{...}{more elements of the message, to be concatenated with the message}
13 | }
14 | \value{
15 | invisibly returns TRUE/FALSE
16 | }
17 | \description{
18 | Log messages will only be emitted if the log priority matches or is higher
19 | than the priority of your message
20 | }
21 | \examples{
22 | \dontrun{
23 | log_fatal("This is a fatal message")
24 | Sys.setenv("LOG_LEVEL" = "TRACE")
25 | log_fatal("This is a fatal message")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/man/log_trace.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/helpers.R
3 | \name{log_trace}
4 | \alias{log_trace}
5 | \title{Log a trace message}
6 | \usage{
7 | log_trace(message, ...)
8 | }
9 | \arguments{
10 | \item{message}{your message to log}
11 |
12 | \item{...}{more elements of the message, to be concatenated with the message}
13 | }
14 | \value{
15 | invisibly returns TRUE/FALSE
16 | }
17 | \description{
18 | Log messages will only be emitted if the log priority matches or is higher
19 | than the priority of your message
20 | }
21 | \examples{
22 | \dontrun{
23 | log_trace("This is a trace message")
24 | Sys.setenv("LOG_LEVEL" = "TRACE")
25 | log_trace("This is a trace message")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/man/log_warn.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/helpers.R
3 | \name{log_warn}
4 | \alias{log_warn}
5 | \title{Log a warning message}
6 | \usage{
7 | log_warn(message, ...)
8 | }
9 | \arguments{
10 | \item{message}{your message to log}
11 |
12 | \item{...}{more elements of the message, to be concatenated with the message}
13 | }
14 | \value{
15 | invisibly returns TRUE/FALSE
16 | }
17 | \description{
18 | Log messages will only be emitted if the log priority matches or is higher
19 | than the priority of your message
20 | }
21 | \examples{
22 | \dontrun{
23 | log_warn("This is a warning message")
24 | Sys.setenv("LOG_LEVEL" = "TRACE")
25 | log_warn("This is a warning message")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/man/log_error.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/helpers.R
3 | \name{log_error}
4 | \alias{log_error}
5 | \title{Log an error message}
6 | \usage{
7 | log_error(message, ...)
8 | }
9 | \arguments{
10 | \item{message}{your message to log}
11 |
12 | \item{...}{more elements of the message, to be concatenated with the message}
13 | }
14 | \value{
15 | invisibly returns TRUE/FALSE
16 | }
17 | \description{
18 | Log messages will only be emitted if the log priority matches or is higher
19 | than the priority of your message
20 | }
21 | \examples{
22 | \dontrun{
23 | log_error("This is an error message")
24 | Sys.setenv("LOG_LEVEL" = "TRACE")
25 | log_error("This is an error message")
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/cran-comments.md:
--------------------------------------------------------------------------------
1 | ## Resumbmission
2 |
3 | This is a resubmission to mitigate the previous note about the misspelling of
4 | the package name in the description. Per CRAN advice, this is now enclosed in
5 | single quotes and resumbitted for consideration.
6 |
7 | ## Original submission test environments
8 | * local R installation, MacOS 11.1, R 4.0.3
9 | * Fedora Linux, R-devel, clang, gfortran (R-hub)
10 | * Ubuntu Linux 20.04.1 LTS, R-release, GCC (R-hub)
11 | * Windows Server 2008 R2 SP1, R-devel, 32/64 bit (R-hub)
12 | * win-builder (devel)
13 |
14 | ## Original R CMD check results
15 |
16 | 0 errors | 0 warnings | 1 note
17 |
18 | The note relates to a possible misspelling, but it's of the package name, 'rlog'.
19 |
20 | * This is a new release.
21 |
--------------------------------------------------------------------------------
/docs/sitemap.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | https://rlog.sellorm.com/index.html
5 |
6 |
7 | https://rlog.sellorm.com/reference/log_debug.html
8 |
9 |
10 | https://rlog.sellorm.com/reference/log_error.html
11 |
12 |
13 | https://rlog.sellorm.com/reference/log_fatal.html
14 |
15 |
16 | https://rlog.sellorm.com/reference/log_info.html
17 |
18 |
19 | https://rlog.sellorm.com/reference/log_trace.html
20 |
21 |
22 | https://rlog.sellorm.com/reference/log_warn.html
23 |
24 |
25 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: rlog
2 | Title: A Simple, Opinionated Logging Utility
3 | Version: 0.1.0.9999
4 | Authors@R:
5 | person(given = "Mark",
6 | family = "Sellors",
7 | role = c("aut", "cre"),
8 | email = "rstats@5vcc.com")
9 | Description: A very lightweight package that writes out log messages in an opinionated way.
10 | Simpler and lighter than other logging packages, 'rlog' provides a compact feature set that
11 | focuses on getting the job done in a Unix-like way.
12 | URL: https://github.com/sellorm/rlog
13 | BugReports: https://github.com/sellorm/rlog/issues
14 | License: MIT + file LICENSE
15 | Encoding: UTF-8
16 | LazyData: true
17 | Roxygen: list(markdown = TRUE)
18 | RoxygenNote: 7.3.2
19 | Suggests:
20 | testthat (>= 3.0.0)
21 | Config/testthat/edition: 3
22 |
--------------------------------------------------------------------------------
/docs/link.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/.github/workflows/rspm-merge.yml:
--------------------------------------------------------------------------------
1 | name: rspm-merge
2 |
3 | on:
4 | workflow_run:
5 | types:
6 | - completed
7 | workflows:
8 | # List all required workflow names here.
9 | - 'R-CMD-check'
10 |
11 | jobs:
12 | rspm-merge:
13 | name: rspm-merge
14 | runs-on: ubuntu-latest
15 | env:
16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
17 | R_KEEP_PKG_SOURCE: yes
18 |
19 | steps:
20 | - uses: actions/checkout@v2
21 | - # It is often a desired behavior to merge only when a workflow execution
22 | # succeeds. This can be changed as needed.
23 | if: ${{ github.event.workflow_run.conclusion == 'success' }}
24 | name: Merge me!
25 | run: |
26 | git config --global user.email "nobody@example.com"
27 | git config --global user.name "GHA auto-commit"
28 | git checkout -B rspm
29 | git rebase main
30 | git push -u origin rspm
31 | shell: bash
32 |
33 |
--------------------------------------------------------------------------------
/R/log_msg.R:
--------------------------------------------------------------------------------
1 | # Main log writing function
2 | log_msg <- function(msg_level = "INFO", message, ...) {
3 | level <- Sys.getenv("LOG_LEVEL", "INFO")
4 | levels <- list(
5 | "all" = 0,
6 | "trace" = 1,
7 | "debug" = 2,
8 | "info" = 3,
9 | "warn" = 4,
10 | "error" = 5,
11 | "fatal" = 6,
12 | "off" = 7
13 | )
14 | if (is.null(levels[tolower(level)])) {
15 | stop("The LOG_LEVEL environment variable is incorrectly set")
16 | }
17 | if (as.integer(levels[tolower(level)]) <= as.integer(levels[tolower(msg_level)])) {
18 | log_text <- paste0(Sys.time(),
19 | " [", msg_level, "] ",
20 | paste(c(message, list(...)), sep = " ", collapse = " "),
21 | "\n",
22 | sep = "",
23 | collapse = ""
24 | )
25 | if (as.integer(levels[tolower(msg_level)]) > 3) {
26 | cat(log_text, file = stderr())
27 | } else {
28 | cat(log_text, file = stdout())
29 | }
30 | invisible(TRUE)
31 | } else {
32 | invisible(FALSE)
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2021 rlog authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 |
9 | name: R-CMD-check
10 |
11 | jobs:
12 | R-CMD-check:
13 | runs-on: ${{ matrix.config.os }}
14 |
15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
16 |
17 | strategy:
18 | fail-fast: false
19 | matrix:
20 | config:
21 | - {os: ubuntu-latest, r: 'release'}
22 | - {os: ubuntu-latest, r: 'oldrel-1'}
23 |
24 | env:
25 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
26 | R_KEEP_PKG_SOURCE: yes
27 |
28 | steps:
29 | - uses: actions/checkout@v2
30 | - uses: r-lib/actions/setup-r@v2
31 | with:
32 | r-version: ${{ matrix.config.r }}
33 | http-user-agent: ${{ matrix.config.http-user-agent }}
34 | use-public-rspm: true
35 |
36 | - uses: r-lib/actions/setup-r-dependencies@v2
37 | with:
38 | extra-packages: rcmdcheck
39 |
40 | - uses: r-lib/actions/check-r-package@v2
41 |
42 | - name: Show testthat output
43 | if: always()
44 | run: find check -name 'testthat.Rout*' -exec cat '{}' \; || true
45 | shell: bash
46 |
47 | - name: Upload check results
48 | if: failure()
49 | uses: actions/upload-artifact@main
50 | with:
51 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results
52 | path: check
53 |
--------------------------------------------------------------------------------
/tests/testthat/test-helpers.R:
--------------------------------------------------------------------------------
1 | test_that("basic functionality is working", {
2 | expect_true(log_info("info"))
3 | expect_false(log_trace("trace"))
4 | expect_output(log_info("INFO"))
5 | expect_silent(log_trace("TRACE"))
6 | })
7 |
8 | test_that("default functionality is OK", {
9 | Sys.unsetenv("LOG_LEVEL")
10 | expect_true(log_fatal("FATAL"))
11 | expect_true(log_error("ERROR"))
12 | expect_true(log_warn("WARN"))
13 | expect_output(log_info("INFO"))
14 | expect_silent(log_debug("DEBUG"))
15 | expect_silent(log_trace("TRACE"))
16 | })
17 |
18 | test_that("default functionality is OK", {
19 | Sys.setenv("LOG_LEVEL" = "TRACE")
20 | expect_true(log_fatal("FATAL"))
21 | expect_true(log_error("ERROR"))
22 | expect_true(log_warn("WARN"))
23 | expect_output(log_info("INFO"))
24 | expect_output(log_debug("DEBUG"))
25 | expect_output(log_trace("TRACE"))
26 | })
27 |
28 | test_that("output is going going to the correct stdout/stderr", {
29 | expect_match(capture.output(log_warn("warn"), type = "message"), "warn$")
30 | expect_match(capture.output(log_error("error"), type = "message"), "error$")
31 | expect_match(capture.output(log_fatal("fatal"), type = "message"), "fatal$")
32 | })
33 |
34 | test_that("multi-part messages render as expected", {
35 | test_var1 <- "hats"
36 | test_var2 <- "shoes"
37 | test_var3 <- c("trilby", "porkpie", "fez")
38 | expect_output(log_info("my message", test_var1, test_var2, "end"))
39 | expect_match(capture_output(log_info("my message", test_var1, test_var2, "end")), "my message hats shoes end$")
40 | expect_match(capture_output(log_info("my message", test_var3)), 'my message c[(]\"trilby\", \"porkpie\", \"fez\"[)]$')
41 | })
42 |
--------------------------------------------------------------------------------
/docs/bootstrap-toc.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
3 | * Copyright 2015 Aidan Feldman
4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
5 |
6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */
7 |
8 | /* All levels of nav */
9 | nav[data-toggle='toc'] .nav > li > a {
10 | display: block;
11 | padding: 4px 20px;
12 | font-size: 13px;
13 | font-weight: 500;
14 | color: #767676;
15 | }
16 | nav[data-toggle='toc'] .nav > li > a:hover,
17 | nav[data-toggle='toc'] .nav > li > a:focus {
18 | padding-left: 19px;
19 | color: #563d7c;
20 | text-decoration: none;
21 | background-color: transparent;
22 | border-left: 1px solid #563d7c;
23 | }
24 | nav[data-toggle='toc'] .nav > .active > a,
25 | nav[data-toggle='toc'] .nav > .active:hover > a,
26 | nav[data-toggle='toc'] .nav > .active:focus > a {
27 | padding-left: 18px;
28 | font-weight: bold;
29 | color: #563d7c;
30 | background-color: transparent;
31 | border-left: 2px solid #563d7c;
32 | }
33 |
34 | /* Nav: second level (shown on .active) */
35 | nav[data-toggle='toc'] .nav .nav {
36 | display: none; /* Hide by default, but at >768px, show it */
37 | padding-bottom: 10px;
38 | }
39 | nav[data-toggle='toc'] .nav .nav > li > a {
40 | padding-top: 1px;
41 | padding-bottom: 1px;
42 | padding-left: 30px;
43 | font-size: 12px;
44 | font-weight: normal;
45 | }
46 | nav[data-toggle='toc'] .nav .nav > li > a:hover,
47 | nav[data-toggle='toc'] .nav .nav > li > a:focus {
48 | padding-left: 29px;
49 | }
50 | nav[data-toggle='toc'] .nav .nav > .active > a,
51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a,
52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a {
53 | padding-left: 28px;
54 | font-weight: 500;
55 | }
56 |
57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */
58 | nav[data-toggle='toc'] .nav > .active > ul {
59 | display: block;
60 | }
61 |
--------------------------------------------------------------------------------
/docs/docsearch.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | // register a handler to move the focus to the search bar
4 | // upon pressing shift + "/" (i.e. "?")
5 | $(document).on('keydown', function(e) {
6 | if (e.shiftKey && e.keyCode == 191) {
7 | e.preventDefault();
8 | $("#search-input").focus();
9 | }
10 | });
11 |
12 | $(document).ready(function() {
13 | // do keyword highlighting
14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */
15 | var mark = function() {
16 |
17 | var referrer = document.URL ;
18 | var paramKey = "q" ;
19 |
20 | if (referrer.indexOf("?") !== -1) {
21 | var qs = referrer.substr(referrer.indexOf('?') + 1);
22 | var qs_noanchor = qs.split('#')[0];
23 | var qsa = qs_noanchor.split('&');
24 | var keyword = "";
25 |
26 | for (var i = 0; i < qsa.length; i++) {
27 | var currentParam = qsa[i].split('=');
28 |
29 | if (currentParam.length !== 2) {
30 | continue;
31 | }
32 |
33 | if (currentParam[0] == paramKey) {
34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20"));
35 | }
36 | }
37 |
38 | if (keyword !== "") {
39 | $(".contents").unmark({
40 | done: function() {
41 | $(".contents").mark(keyword);
42 | }
43 | });
44 | }
45 | }
46 | };
47 |
48 | mark();
49 | });
50 | });
51 |
52 | /* Search term highlighting ------------------------------*/
53 |
54 | function matchedWords(hit) {
55 | var words = [];
56 |
57 | var hierarchy = hit._highlightResult.hierarchy;
58 | // loop to fetch from lvl0, lvl1, etc.
59 | for (var idx in hierarchy) {
60 | words = words.concat(hierarchy[idx].matchedWords);
61 | }
62 |
63 | var content = hit._highlightResult.content;
64 | if (content) {
65 | words = words.concat(content.matchedWords);
66 | }
67 |
68 | // return unique words
69 | var words_uniq = [...new Set(words)];
70 | return words_uniq;
71 | }
72 |
73 | function updateHitURL(hit) {
74 |
75 | var words = matchedWords(hit);
76 | var url = "";
77 |
78 | if (hit.anchor) {
79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor;
80 | } else {
81 | url = hit.url + '?q=' + escape(words.join(" "));
82 | }
83 |
84 | return url;
85 | }
86 |
--------------------------------------------------------------------------------
/.github/workflows/rhub.yaml:
--------------------------------------------------------------------------------
1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at
2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml
3 | # You can update this file to a newer version using the rhub2 package:
4 | #
5 | # rhub::rhub_setup()
6 | #
7 | # It is unlikely that you need to modify this file manually.
8 |
9 | name: R-hub
10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}"
11 |
12 | on:
13 | workflow_dispatch:
14 | inputs:
15 | config:
16 | description: 'A comma separated list of R-hub platforms to use.'
17 | type: string
18 | default: 'linux,windows,macos'
19 | name:
20 | description: 'Run name. You can leave this empty now.'
21 | type: string
22 | id:
23 | description: 'Unique ID. You can leave this empty now.'
24 | type: string
25 |
26 | jobs:
27 |
28 | setup:
29 | runs-on: ubuntu-latest
30 | outputs:
31 | containers: ${{ steps.rhub-setup.outputs.containers }}
32 | platforms: ${{ steps.rhub-setup.outputs.platforms }}
33 |
34 | steps:
35 | # NO NEED TO CHECKOUT HERE
36 | - uses: r-hub/actions/setup@v1
37 | with:
38 | config: ${{ github.event.inputs.config }}
39 | id: rhub-setup
40 |
41 | linux-containers:
42 | needs: setup
43 | if: ${{ needs.setup.outputs.containers != '[]' }}
44 | runs-on: ubuntu-latest
45 | name: ${{ matrix.config.label }}
46 | strategy:
47 | fail-fast: false
48 | matrix:
49 | config: ${{ fromJson(needs.setup.outputs.containers) }}
50 | container:
51 | image: ${{ matrix.config.container }}
52 |
53 | steps:
54 | - uses: r-hub/actions/checkout@v1
55 | - uses: r-hub/actions/platform-info@v1
56 | with:
57 | token: ${{ secrets.RHUB_TOKEN }}
58 | job-config: ${{ matrix.config.job-config }}
59 | - uses: r-hub/actions/setup-deps@v1
60 | with:
61 | token: ${{ secrets.RHUB_TOKEN }}
62 | job-config: ${{ matrix.config.job-config }}
63 | - uses: r-hub/actions/run-check@v1
64 | with:
65 | token: ${{ secrets.RHUB_TOKEN }}
66 | job-config: ${{ matrix.config.job-config }}
67 |
68 | other-platforms:
69 | needs: setup
70 | if: ${{ needs.setup.outputs.platforms != '[]' }}
71 | runs-on: ${{ matrix.config.os }}
72 | name: ${{ matrix.config.label }}
73 | strategy:
74 | fail-fast: false
75 | matrix:
76 | config: ${{ fromJson(needs.setup.outputs.platforms) }}
77 |
78 | steps:
79 | - uses: r-hub/actions/checkout@v1
80 | - uses: r-hub/actions/setup-r@v1
81 | with:
82 | job-config: ${{ matrix.config.job-config }}
83 | token: ${{ secrets.RHUB_TOKEN }}
84 | - uses: r-hub/actions/platform-info@v1
85 | with:
86 | token: ${{ secrets.RHUB_TOKEN }}
87 | job-config: ${{ matrix.config.job-config }}
88 | - uses: r-hub/actions/setup-deps@v1
89 | with:
90 | job-config: ${{ matrix.config.job-config }}
91 | token: ${{ secrets.RHUB_TOKEN }}
92 | - uses: r-hub/actions/run-check@v1
93 | with:
94 | job-config: ${{ matrix.config.job-config }}
95 | token: ${{ secrets.RHUB_TOKEN }}
96 |
--------------------------------------------------------------------------------
/docs/pkgdown.js:
--------------------------------------------------------------------------------
1 | /* http://gregfranko.com/blog/jquery-best-practices/ */
2 | (function($) {
3 | $(function() {
4 |
5 | $('.navbar-fixed-top').headroom();
6 |
7 | $('body').css('padding-top', $('.navbar').height() + 10);
8 | $(window).resize(function(){
9 | $('body').css('padding-top', $('.navbar').height() + 10);
10 | });
11 |
12 | $('[data-toggle="tooltip"]').tooltip();
13 |
14 | var cur_path = paths(location.pathname);
15 | var links = $("#navbar ul li a");
16 | var max_length = -1;
17 | var pos = -1;
18 | for (var i = 0; i < links.length; i++) {
19 | if (links[i].getAttribute("href") === "#")
20 | continue;
21 | // Ignore external links
22 | if (links[i].host !== location.host)
23 | continue;
24 |
25 | var nav_path = paths(links[i].pathname);
26 |
27 | var length = prefix_length(nav_path, cur_path);
28 | if (length > max_length) {
29 | max_length = length;
30 | pos = i;
31 | }
32 | }
33 |
34 | // Add class to parent
, and enclosing if in dropdown
35 | if (pos >= 0) {
36 | var menu_anchor = $(links[pos]);
37 | menu_anchor.parent().addClass("active");
38 | menu_anchor.closest("li.dropdown").addClass("active");
39 | }
40 | });
41 |
42 | function paths(pathname) {
43 | var pieces = pathname.split("/");
44 | pieces.shift(); // always starts with /
45 |
46 | var end = pieces[pieces.length - 1];
47 | if (end === "index.html" || end === "")
48 | pieces.pop();
49 | return(pieces);
50 | }
51 |
52 | // Returns -1 if not found
53 | function prefix_length(needle, haystack) {
54 | if (needle.length > haystack.length)
55 | return(-1);
56 |
57 | // Special case for length-0 haystack, since for loop won't run
58 | if (haystack.length === 0) {
59 | return(needle.length === 0 ? 0 : -1);
60 | }
61 |
62 | for (var i = 0; i < haystack.length; i++) {
63 | if (needle[i] != haystack[i])
64 | return(i);
65 | }
66 |
67 | return(haystack.length);
68 | }
69 |
70 | /* Clipboard --------------------------*/
71 |
72 | function changeTooltipMessage(element, msg) {
73 | var tooltipOriginalTitle=element.getAttribute('data-original-title');
74 | element.setAttribute('data-original-title', msg);
75 | $(element).tooltip('show');
76 | element.setAttribute('data-original-title', tooltipOriginalTitle);
77 | }
78 |
79 | if(ClipboardJS.isSupported()) {
80 | $(document).ready(function() {
81 | var copyButton = " ";
82 |
83 | $(".examples, div.sourceCode").addClass("hasCopyButton");
84 |
85 | // Insert copy buttons:
86 | $(copyButton).prependTo(".hasCopyButton");
87 |
88 | // Initialize tooltips:
89 | $('.btn-copy-ex').tooltip({container: 'body'});
90 |
91 | // Initialize clipboard:
92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', {
93 | text: function(trigger) {
94 | return trigger.parentNode.textContent;
95 | }
96 | });
97 |
98 | clipboardBtnCopies.on('success', function(e) {
99 | changeTooltipMessage(e.trigger, 'Copied!');
100 | e.clearSelection();
101 | });
102 |
103 | clipboardBtnCopies.on('error', function() {
104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy');
105 | });
106 | });
107 | }
108 | })(window.jQuery || window.$)
109 |
--------------------------------------------------------------------------------
/R/helpers.R:
--------------------------------------------------------------------------------
1 | #' Log a trace message
2 | #'
3 | #' Log messages will only be emitted if the log priority matches or is higher
4 | #' than the priority of your message
5 | #'
6 | #' @param message your message to log
7 | #' @param ... more elements of the message, to be concatenated with the message
8 | #'
9 | #' @return invisibly returns TRUE/FALSE
10 | #' @examples
11 | #' \dontrun{
12 | #' log_trace("This is a trace message")
13 | #' Sys.setenv("LOG_LEVEL" = "TRACE")
14 | #' log_trace("This is a trace message")
15 | #' }
16 | #' @export
17 | log_trace <- function(message, ...) {
18 | log_msg("TRACE", message, ...)
19 | }
20 |
21 | #' Log a debug message
22 | #'
23 | #' Log messages will only be emitted if the log priority matches or is higher
24 | #' than the priority of your message
25 | #'
26 | #' @param message your message to log
27 | #' @param ... more elements of the message, to be concatenated with the message
28 | #'
29 | #' @return invisibly returns TRUE/FALSE
30 | #' @examples
31 | #' \dontrun{
32 | #' log_debug("This is a debug message")
33 | #' Sys.setenv("LOG_LEVEL" = "TRACE")
34 | #' log_debug("This is a debug message")
35 | #' }
36 | #' @export
37 | log_debug <- function(message, ...) {
38 | log_msg("DEBUG", message, ...)
39 | }
40 |
41 | #' Log an info message
42 | #'
43 | #' Log messages will only be emitted if the log priority matches or is higher
44 | #' than the priority of your message
45 | #'
46 | #' @param message your message to log
47 | #' @param ... more elements of the message, to be concatenated with the message
48 | #'
49 | #' @return invisibly returns TRUE/FALSE
50 | #' @examples
51 | #' \dontrun{
52 | #' log_info("This is an info message")
53 | #' Sys.setenv("LOG_LEVEL" = "TRACE")
54 | #' log_info("This is an info message")
55 | #' }
56 | #' @export
57 | log_info <- function(message, ...) {
58 | log_msg("INFO", message, ...)
59 | }
60 |
61 | #' Log a warning message
62 | #'
63 | #' Log messages will only be emitted if the log priority matches or is higher
64 | #' than the priority of your message
65 | #'
66 | #' @param message your message to log
67 | #' @param ... more elements of the message, to be concatenated with the message
68 | #'
69 | #' @return invisibly returns TRUE/FALSE
70 | #' @examples
71 | #' \dontrun{
72 | #' log_warn("This is a warning message")
73 | #' Sys.setenv("LOG_LEVEL" = "TRACE")
74 | #' log_warn("This is a warning message")
75 | #' }
76 | #' @export
77 | log_warn <- function(message, ...) {
78 | log_msg("WARN", message, ...)
79 | }
80 |
81 | #' Log an error message
82 | #'
83 | #' Log messages will only be emitted if the log priority matches or is higher
84 | #' than the priority of your message
85 | #'
86 | #' @param message your message to log
87 | #' @param ... more elements of the message, to be concatenated with the message
88 | #'
89 | #' @return invisibly returns TRUE/FALSE
90 | #' @examples
91 | #' \dontrun{
92 | #' log_error("This is an error message")
93 | #' Sys.setenv("LOG_LEVEL" = "TRACE")
94 | #' log_error("This is an error message")
95 | #' }
96 | #' @export
97 | log_error <- function(message, ...) {
98 | log_msg("ERROR", message, ...)
99 | }
100 |
101 |
102 | #' Log a fatal message
103 | #'
104 | #' Log messages will only be emitted if the log priority matches or is higher
105 | #' than the priority of your message
106 | #'
107 | #' @param message your message to log
108 | #' @param ... more elements of the message, to be concatenated with the message
109 | #'
110 | #' @return invisibly returns TRUE/FALSE
111 | #' @examples
112 | #' \dontrun{
113 | #' log_fatal("This is a fatal message")
114 | #' Sys.setenv("LOG_LEVEL" = "TRACE")
115 | #' log_fatal("This is a fatal message")
116 | #' }
117 | #' @export
118 | log_fatal <- function(message, ...) {
119 | log_msg("FATAL", message, ...)
120 | }
121 |
--------------------------------------------------------------------------------
/docs/authors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Authors • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
115 |
116 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/docs/bootstrap-toc.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
3 | * Copyright 2015 Aidan Feldman
4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
5 | (function() {
6 | 'use strict';
7 |
8 | window.Toc = {
9 | helpers: {
10 | // return all matching elements in the set, or their descendants
11 | findOrFilter: function($el, selector) {
12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/
13 | // http://stackoverflow.com/a/12731439/358804
14 | var $descendants = $el.find(selector);
15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])');
16 | },
17 |
18 | generateUniqueIdBase: function(el) {
19 | var text = $(el).text();
20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-');
21 | return anchor || el.tagName.toLowerCase();
22 | },
23 |
24 | generateUniqueId: function(el) {
25 | var anchorBase = this.generateUniqueIdBase(el);
26 | for (var i = 0; ; i++) {
27 | var anchor = anchorBase;
28 | if (i > 0) {
29 | // add suffix
30 | anchor += '-' + i;
31 | }
32 | // check if ID already exists
33 | if (!document.getElementById(anchor)) {
34 | return anchor;
35 | }
36 | }
37 | },
38 |
39 | generateAnchor: function(el) {
40 | if (el.id) {
41 | return el.id;
42 | } else {
43 | var anchor = this.generateUniqueId(el);
44 | el.id = anchor;
45 | return anchor;
46 | }
47 | },
48 |
49 | createNavList: function() {
50 | return $('');
51 | },
52 |
53 | createChildNavList: function($parent) {
54 | var $childList = this.createNavList();
55 | $parent.append($childList);
56 | return $childList;
57 | },
58 |
59 | generateNavEl: function(anchor, text) {
60 | var $a = $(' ');
61 | $a.attr('href', '#' + anchor);
62 | $a.text(text);
63 | var $li = $(' ');
64 | $li.append($a);
65 | return $li;
66 | },
67 |
68 | generateNavItem: function(headingEl) {
69 | var anchor = this.generateAnchor(headingEl);
70 | var $heading = $(headingEl);
71 | var text = $heading.data('toc-text') || $heading.text();
72 | return this.generateNavEl(anchor, text);
73 | },
74 |
75 | // Find the first heading level (``, then ``, etc.) that has more than one element. Defaults to 1 (for ``).
76 | getTopLevel: function($scope) {
77 | for (var i = 1; i <= 6; i++) {
78 | var $headings = this.findOrFilter($scope, 'h' + i);
79 | if ($headings.length > 1) {
80 | return i;
81 | }
82 | }
83 |
84 | return 1;
85 | },
86 |
87 | // returns the elements for the top level, and the next below it
88 | getHeadings: function($scope, topLevel) {
89 | var topSelector = 'h' + topLevel;
90 |
91 | var secondaryLevel = topLevel + 1;
92 | var secondarySelector = 'h' + secondaryLevel;
93 |
94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector);
95 | },
96 |
97 | getNavLevel: function(el) {
98 | return parseInt(el.tagName.charAt(1), 10);
99 | },
100 |
101 | populateNav: function($topContext, topLevel, $headings) {
102 | var $context = $topContext;
103 | var $prevNav;
104 |
105 | var helpers = this;
106 | $headings.each(function(i, el) {
107 | var $newNav = helpers.generateNavItem(el);
108 | var navLevel = helpers.getNavLevel(el);
109 |
110 | // determine the proper $context
111 | if (navLevel === topLevel) {
112 | // use top level
113 | $context = $topContext;
114 | } else if ($prevNav && $context === $topContext) {
115 | // create a new level of the tree and switch to it
116 | $context = helpers.createChildNavList($prevNav);
117 | } // else use the current $context
118 |
119 | $context.append($newNav);
120 |
121 | $prevNav = $newNav;
122 | });
123 | },
124 |
125 | parseOps: function(arg) {
126 | var opts;
127 | if (arg.jquery) {
128 | opts = {
129 | $nav: arg
130 | };
131 | } else {
132 | opts = arg;
133 | }
134 | opts.$scope = opts.$scope || $(document.body);
135 | return opts;
136 | }
137 | },
138 |
139 | // accepts a jQuery object, or an options object
140 | init: function(opts) {
141 | opts = this.helpers.parseOps(opts);
142 |
143 | // ensure that the data attribute is in place for styling
144 | opts.$nav.attr('data-toggle', 'toc');
145 |
146 | var $topContext = this.helpers.createChildNavList(opts.$nav);
147 | var topLevel = this.helpers.getTopLevel(opts.$scope);
148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel);
149 | this.helpers.populateNav($topContext, topLevel, $headings);
150 | }
151 | };
152 |
153 | $(function() {
154 | $('nav[data-toggle="toc"]').each(function(i, el) {
155 | var $nav = $(el);
156 | Toc.init($nav);
157 | });
158 | });
159 | })();
160 |
--------------------------------------------------------------------------------
/docs/LICENSE-text.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | License • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
115 |
116 |
YEAR: 2021
117 | COPYRIGHT HOLDER: rlog authors
118 |
119 |
120 |
121 |
122 |
127 |
128 |
129 |
130 |
131 |
132 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/docs/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Page not found (404) • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
115 |
116 | Content not found. Please use links in the navbar.
117 |
118 |
119 |
120 |
125 |
126 |
127 |
128 |
129 |
130 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # rlog
2 |
3 |
4 | [](https://github.com/sellorm/rlog/actions)
5 |
6 |
7 | rlog is an opinionated, lightweight logging package for R.
8 |
9 | It relies on long standing Unix traditions, to write simple log messages in a flexible way.
10 |
11 | Log message output looks like this:
12 |
13 | ```
14 | 2021-02-21 17:19:06 [INFO] This is my log message
15 | ```
16 |
17 | ## Installation
18 |
19 | Install rlog from GitHub with the following:
20 |
21 | ``` r
22 | devtools::install_github("sellorm/rlog")
23 | ```
24 |
25 | ## Does R _really_ need another logging package?
26 |
27 | We think so, yes!
28 |
29 | There are already loads of logging packages for R. Many are no longer maintained and of the remaining selection some are overly complex, making them less approachable for beginners.
30 |
31 | Since logging should be an essential part of any production application or pipeline I think it's important that as many people as possible are introduced to good logging practice.
32 |
33 | If rlog doesn't have enough features for you, I'd recommend the excellent "[logger](https://cran.r-project.org/package=logger)" instead.
34 |
35 | ## rlog philosophy
36 |
37 | The rlog philosophy is the [Unix philosophy](https://en.wikipedia.org/wiki/Unix_philosophy) and as such, we expect applications using rlog to be able to integrate with other enterprise software quickly and efficiently.
38 |
39 | rlog is simple by design and it relies on existing Unix/Linux norms to get the job done.
40 |
41 | * Log message format is intentionally not configurable
42 | * the log level can only be controlled by an environment variable
43 | * log messages are written to standard output and standard error
44 |
45 | ## Usage
46 |
47 | The best way to use rlog is to call the functions directly from within your applications.
48 |
49 | There is one function per log message level:
50 |
51 | ``` r
52 | rlog::log_fatal("my fatal message")
53 | rlog::log_error("my error message")
54 | rlog::log_warn("my warn message")
55 | rlog::log_info("my info message")
56 | rlog::log_debug("my debug message")
57 | rlog::log_trace("my trace message")
58 | ```
59 |
60 | If you run this code as-is without setting a custom `LOG_LEVEL` with the environment variable, you'll get output like this:
61 |
62 | ```
63 | 2021-02-21 17:19:06 [FATAL] fatal
64 | 2021-02-21 17:19:06 [ERROR] error
65 | 2021-02-21 17:19:06 [WARN] warn
66 | 2021-02-21 17:19:06 [INFO] info
67 | ```
68 |
69 | The "DEBUG" and "TRACE" message won't be printed, since the default `LOG_LEVEL` is "INFO" and those message have lower priority.
70 |
71 | Play around with setting the `LOG_LEVEL` directly in R and seeing what messages are emitted:
72 |
73 | ``` r
74 | Sys.setenv("LOG_LEVEL" = "ERROR")
75 | rlog::log_fatal("my fatal message")
76 | rlog::log_error("my error message")
77 | rlog::log_warn("my warn message")
78 | rlog::log_info("my info message")
79 | rlog::log_debug("my debug message")
80 | rlog::log_trace("my trace message")
81 | ```
82 |
83 | Gives us this output:
84 |
85 | ```
86 | 2021-02-21 17:19:06 [FATAL] fatal
87 | 2021-02-21 17:19:06 [ERROR] error
88 | ```
89 |
90 | Remember though, the best way to set the environment variable is outside of the app. That way it's easier to change at run-time.
91 |
92 | So in your terminal you can do something like this before you run your script:
93 |
94 | ``` sh
95 | $ export LOG_LEVEL=TRACE
96 | $ ./my_script.R
97 | ```
98 |
99 | Or you can even call your script with the appropriate value at run-time:
100 |
101 | ``` sh
102 | $ LOG_LEVEL=ERROR ./my_script.R
103 | ```
104 |
105 | If you're using RStudio Connect users can set an environment variable called `LOG_LEVEL` in the "Vars" tab of their apps control panel.
106 |
107 | ## Setting the log level
108 |
109 | rlog relies on an environment variable called `LOG_LEVEL` to control which log messages are emitted.
110 |
111 | If it's not set, it will default to "INFO".
112 |
113 | The available levels -- in decreasing order of severity -- are as follows:
114 |
115 | * fatal
116 | * error
117 | * warn
118 | * info
119 | * debug
120 | * trace
121 |
122 | When the `LOG_LEVEL` environment variable is set to "INFO", only messages at that level and above will be emitted.
123 |
124 | Another example:
125 |
126 | * fatal
127 | * error
128 | * warn
129 | * info
130 | * debug <= If we set the log level here only messages of debug and above will be emitted.
131 | * trace
132 |
133 | This is a really powerful way of only including the messages you want to see in the log files at any given time. For example, you may choose to set the `LOG_LEVEL` to "TRACE" while developing your application or if it runs into a problem in production, but you might choose to run the application with a `LOG_LEVEL` of "ERROR" under normal circumstances.
134 |
135 |
136 | ## I want to write to a log file, not the console
137 |
138 | rlog outputs it log messages into the console in the same way that most Unix/Linux tools do. Ordinary messages go to "standard output" ([stdout](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout))) and errors go to "standard error" ([stderr](https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr))).
139 |
140 | This means they can be captured in the standard Unix/Linux way:
141 |
142 | ```
143 | ./my_script.R > /path/to/file.log 2>&1
144 | ```
145 |
146 | This command redirects stderr to stdout and drops it all into the `/path/to/file.log` file.
147 |
148 | You can also keep the "normal" and error outputs separate:
149 |
150 | ```
151 | ./my_script.R > /path/to/file.log 2> /path/to/errors.log
152 | ```
153 |
154 | Many enterprise software products, such as RStudio Connect will capture this output automatically and save it for you.
155 |
--------------------------------------------------------------------------------
/docs/news/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Changelog • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
116 |
117 |
118 |
120 |
121 | Prepare for CRAN submission
122 |
123 |
124 |
125 |
127 |
128 | Added a NEWS.md file to track changes to the package.
129 |
130 |
131 |
132 |
133 |
138 |
139 |
140 |
141 |
142 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/docs/LICENSE.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | MIT License • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
115 |
116 |
117 |
118 |
Copyright (c) 2021 rlog authors
119 |
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
120 |
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
121 |
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
122 |
123 |
124 |
125 |
126 |
131 |
132 |
133 |
134 |
135 |
136 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/docs/reference/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Function reference • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | All functions
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 | log_debug()
140 |
141 | Log a debug message
142 |
143 |
144 |
145 | log_error()
146 |
147 | Log an error message
148 |
149 |
150 |
151 | log_fatal()
152 |
153 | Log a fatal message
154 |
155 |
156 |
157 | log_info()
158 |
159 | Log an info message
160 |
161 |
162 |
163 | log_trace()
164 |
165 | Log a trace message
166 |
167 |
168 |
169 | log_warn()
170 |
171 | Log a warning message
172 |
173 |
174 |
175 |
176 |
177 |
182 |
183 |
184 |
185 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/docs/reference/log_info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Log an info message — log_info • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
Log messages will only be emitted if the log priority matches or is higher
122 | than the priority of your message
123 |
124 |
125 |
log_info ( message )
126 |
127 |
Arguments
128 |
129 |
130 |
131 | message
132 | your message to log
133 |
134 |
135 |
136 |
Value
137 |
138 |
invisibly returns TRUE/FALSE
139 |
140 |
Examples
141 |
147 |
148 |
153 |
154 |
155 |
156 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/reference/log_debug.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Log a debug message — log_debug • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
Log messages will only be emitted if the log priority matches or is higher
122 | than the priority of your message
123 |
124 |
125 |
log_debug ( message )
126 |
127 |
Arguments
128 |
129 |
130 |
131 | message
132 | your message to log
133 |
134 |
135 |
136 |
Value
137 |
138 |
invisibly returns TRUE/FALSE
139 |
140 |
Examples
141 |
147 |
148 |
153 |
154 |
155 |
156 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/reference/log_fatal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Log a fatal message — log_fatal • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
Log messages will only be emitted if the log priority matches or is higher
122 | than the priority of your message
123 |
124 |
125 |
log_fatal ( message )
126 |
127 |
Arguments
128 |
129 |
130 |
131 | message
132 | your message to log
133 |
134 |
135 |
136 |
Value
137 |
138 |
invisibly returns TRUE/FALSE
139 |
140 |
Examples
141 |
147 |
148 |
153 |
154 |
155 |
156 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/reference/log_trace.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Log a trace message — log_trace • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
Log messages will only be emitted if the log priority matches or is higher
122 | than the priority of your message
123 |
124 |
125 |
log_trace ( message )
126 |
127 |
Arguments
128 |
129 |
130 |
131 | message
132 | your message to log
133 |
134 |
135 |
136 |
Value
137 |
138 |
invisibly returns TRUE/FALSE
139 |
140 |
Examples
141 |
147 |
148 |
153 |
154 |
155 |
156 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/reference/log_error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Log an error message — log_error • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
Log messages will only be emitted if the log priority matches or is higher
122 | than the priority of your message
123 |
124 |
125 |
log_error ( message )
126 |
127 |
Arguments
128 |
129 |
130 |
131 | message
132 | your message to log
133 |
134 |
135 |
136 |
Value
137 |
138 |
invisibly returns TRUE/FALSE
139 |
140 |
Examples
141 |
147 |
148 |
153 |
154 |
155 |
156 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/reference/log_warn.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Log a warning message — log_warn • rlog
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
Log messages will only be emitted if the log priority matches or is higher
122 | than the priority of your message
123 |
124 |
125 |
log_warn ( message )
126 |
127 |
Arguments
128 |
129 |
130 |
131 | message
132 | your message to log
133 |
134 |
135 |
136 |
Value
137 |
138 |
invisibly returns TRUE/FALSE
139 |
140 |
Examples
141 |
147 |
148 |
153 |
154 |
155 |
156 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/docs/pkgdown.css:
--------------------------------------------------------------------------------
1 | /* Sticky footer */
2 |
3 | /**
4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/
5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css
6 | *
7 | * .Site -> body > .container
8 | * .Site-content -> body > .container .row
9 | * .footer -> footer
10 | *
11 | * Key idea seems to be to ensure that .container and __all its parents__
12 | * have height set to 100%
13 | *
14 | */
15 |
16 | html, body {
17 | height: 100%;
18 | }
19 |
20 | body {
21 | position: relative;
22 | }
23 |
24 | body > .container {
25 | display: flex;
26 | height: 100%;
27 | flex-direction: column;
28 | }
29 |
30 | body > .container .row {
31 | flex: 1 0 auto;
32 | }
33 |
34 | footer {
35 | margin-top: 45px;
36 | padding: 35px 0 36px;
37 | border-top: 1px solid #e5e5e5;
38 | color: #666;
39 | display: flex;
40 | flex-shrink: 0;
41 | }
42 | footer p {
43 | margin-bottom: 0;
44 | }
45 | footer div {
46 | flex: 1;
47 | }
48 | footer .pkgdown {
49 | text-align: right;
50 | }
51 | footer p {
52 | margin-bottom: 0;
53 | }
54 |
55 | img.icon {
56 | float: right;
57 | }
58 |
59 | img {
60 | max-width: 100%;
61 | }
62 |
63 | /* Fix bug in bootstrap (only seen in firefox) */
64 | summary {
65 | display: list-item;
66 | }
67 |
68 | /* Typographic tweaking ---------------------------------*/
69 |
70 | .contents .page-header {
71 | margin-top: calc(-60px + 1em);
72 | }
73 |
74 | dd {
75 | margin-left: 3em;
76 | }
77 |
78 | /* Section anchors ---------------------------------*/
79 |
80 | a.anchor {
81 | margin-left: -30px;
82 | display:inline-block;
83 | width: 30px;
84 | height: 30px;
85 | visibility: hidden;
86 |
87 | background-image: url(./link.svg);
88 | background-repeat: no-repeat;
89 | background-size: 20px 20px;
90 | background-position: center center;
91 | }
92 |
93 | .hasAnchor:hover a.anchor {
94 | visibility: visible;
95 | }
96 |
97 | @media (max-width: 767px) {
98 | .hasAnchor:hover a.anchor {
99 | visibility: hidden;
100 | }
101 | }
102 |
103 |
104 | /* Fixes for fixed navbar --------------------------*/
105 |
106 | .contents h1, .contents h2, .contents h3, .contents h4 {
107 | padding-top: 60px;
108 | margin-top: -40px;
109 | }
110 |
111 | /* Navbar submenu --------------------------*/
112 |
113 | .dropdown-submenu {
114 | position: relative;
115 | }
116 |
117 | .dropdown-submenu>.dropdown-menu {
118 | top: 0;
119 | left: 100%;
120 | margin-top: -6px;
121 | margin-left: -1px;
122 | border-radius: 0 6px 6px 6px;
123 | }
124 |
125 | .dropdown-submenu:hover>.dropdown-menu {
126 | display: block;
127 | }
128 |
129 | .dropdown-submenu>a:after {
130 | display: block;
131 | content: " ";
132 | float: right;
133 | width: 0;
134 | height: 0;
135 | border-color: transparent;
136 | border-style: solid;
137 | border-width: 5px 0 5px 5px;
138 | border-left-color: #cccccc;
139 | margin-top: 5px;
140 | margin-right: -10px;
141 | }
142 |
143 | .dropdown-submenu:hover>a:after {
144 | border-left-color: #ffffff;
145 | }
146 |
147 | .dropdown-submenu.pull-left {
148 | float: none;
149 | }
150 |
151 | .dropdown-submenu.pull-left>.dropdown-menu {
152 | left: -100%;
153 | margin-left: 10px;
154 | border-radius: 6px 0 6px 6px;
155 | }
156 |
157 | /* Sidebar --------------------------*/
158 |
159 | #pkgdown-sidebar {
160 | margin-top: 30px;
161 | position: -webkit-sticky;
162 | position: sticky;
163 | top: 70px;
164 | }
165 |
166 | #pkgdown-sidebar h2 {
167 | font-size: 1.5em;
168 | margin-top: 1em;
169 | }
170 |
171 | #pkgdown-sidebar h2:first-child {
172 | margin-top: 0;
173 | }
174 |
175 | #pkgdown-sidebar .list-unstyled li {
176 | margin-bottom: 0.5em;
177 | }
178 |
179 | /* bootstrap-toc tweaks ------------------------------------------------------*/
180 |
181 | /* All levels of nav */
182 |
183 | nav[data-toggle='toc'] .nav > li > a {
184 | padding: 4px 20px 4px 6px;
185 | font-size: 1.5rem;
186 | font-weight: 400;
187 | color: inherit;
188 | }
189 |
190 | nav[data-toggle='toc'] .nav > li > a:hover,
191 | nav[data-toggle='toc'] .nav > li > a:focus {
192 | padding-left: 5px;
193 | color: inherit;
194 | border-left: 1px solid #878787;
195 | }
196 |
197 | nav[data-toggle='toc'] .nav > .active > a,
198 | nav[data-toggle='toc'] .nav > .active:hover > a,
199 | nav[data-toggle='toc'] .nav > .active:focus > a {
200 | padding-left: 5px;
201 | font-size: 1.5rem;
202 | font-weight: 400;
203 | color: inherit;
204 | border-left: 2px solid #878787;
205 | }
206 |
207 | /* Nav: second level (shown on .active) */
208 |
209 | nav[data-toggle='toc'] .nav .nav {
210 | display: none; /* Hide by default, but at >768px, show it */
211 | padding-bottom: 10px;
212 | }
213 |
214 | nav[data-toggle='toc'] .nav .nav > li > a {
215 | padding-left: 16px;
216 | font-size: 1.35rem;
217 | }
218 |
219 | nav[data-toggle='toc'] .nav .nav > li > a:hover,
220 | nav[data-toggle='toc'] .nav .nav > li > a:focus {
221 | padding-left: 15px;
222 | }
223 |
224 | nav[data-toggle='toc'] .nav .nav > .active > a,
225 | nav[data-toggle='toc'] .nav .nav > .active:hover > a,
226 | nav[data-toggle='toc'] .nav .nav > .active:focus > a {
227 | padding-left: 15px;
228 | font-weight: 500;
229 | font-size: 1.35rem;
230 | }
231 |
232 | /* orcid ------------------------------------------------------------------- */
233 |
234 | .orcid {
235 | font-size: 16px;
236 | color: #A6CE39;
237 | /* margins are required by official ORCID trademark and display guidelines */
238 | margin-left:4px;
239 | margin-right:4px;
240 | vertical-align: middle;
241 | }
242 |
243 | /* Reference index & topics ----------------------------------------------- */
244 |
245 | .ref-index th {font-weight: normal;}
246 |
247 | .ref-index td {vertical-align: top; min-width: 100px}
248 | .ref-index .icon {width: 40px;}
249 | .ref-index .alias {width: 40%;}
250 | .ref-index-icons .alias {width: calc(40% - 40px);}
251 | .ref-index .title {width: 60%;}
252 |
253 | .ref-arguments th {text-align: right; padding-right: 10px;}
254 | .ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px}
255 | .ref-arguments .name {width: 20%;}
256 | .ref-arguments .desc {width: 80%;}
257 |
258 | /* Nice scrolling for wide elements --------------------------------------- */
259 |
260 | table {
261 | display: block;
262 | overflow: auto;
263 | }
264 |
265 | /* Syntax highlighting ---------------------------------------------------- */
266 |
267 | pre {
268 | word-wrap: normal;
269 | word-break: normal;
270 | border: 1px solid #eee;
271 | }
272 |
273 | pre, code {
274 | background-color: #f8f8f8;
275 | color: #333;
276 | }
277 |
278 | pre code {
279 | overflow: auto;
280 | word-wrap: normal;
281 | white-space: pre;
282 | }
283 |
284 | pre .img {
285 | margin: 5px 0;
286 | }
287 |
288 | pre .img img {
289 | background-color: #fff;
290 | display: block;
291 | height: auto;
292 | }
293 |
294 | code a, pre a {
295 | color: #375f84;
296 | }
297 |
298 | a.sourceLine:hover {
299 | text-decoration: none;
300 | }
301 |
302 | .fl {color: #1514b5;}
303 | .fu {color: #000000;} /* function */
304 | .ch,.st {color: #036a07;} /* string */
305 | .kw {color: #264D66;} /* keyword */
306 | .co {color: #888888;} /* comment */
307 |
308 | .message { color: black; font-weight: bolder;}
309 | .error { color: orange; font-weight: bolder;}
310 | .warning { color: #6A0366; font-weight: bolder;}
311 |
312 | /* Clipboard --------------------------*/
313 |
314 | .hasCopyButton {
315 | position: relative;
316 | }
317 |
318 | .btn-copy-ex {
319 | position: absolute;
320 | right: 0;
321 | top: 0;
322 | visibility: hidden;
323 | }
324 |
325 | .hasCopyButton:hover button.btn-copy-ex {
326 | visibility: visible;
327 | }
328 |
329 | /* headroom.js ------------------------ */
330 |
331 | .headroom {
332 | will-change: transform;
333 | transition: transform 200ms linear;
334 | }
335 | .headroom--pinned {
336 | transform: translateY(0%);
337 | }
338 | .headroom--unpinned {
339 | transform: translateY(-100%);
340 | }
341 |
342 | /* mark.js ----------------------------*/
343 |
344 | mark {
345 | background-color: rgba(255, 255, 51, 0.5);
346 | border-bottom: 2px solid rgba(255, 153, 51, 0.3);
347 | padding: 1px;
348 | }
349 |
350 | /* vertical spacing after htmlwidgets */
351 | .html-widget {
352 | margin-bottom: 10px;
353 | }
354 |
355 | /* fontawesome ------------------------ */
356 |
357 | .fab {
358 | font-family: "Font Awesome 5 Brands" !important;
359 | }
360 |
361 | /* don't display links in code chunks when printing */
362 | /* source: https://stackoverflow.com/a/10781533 */
363 | @media print {
364 | code a:link:after, code a:visited:after {
365 | content: "";
366 | }
367 | }
368 |
--------------------------------------------------------------------------------
/docs/docsearch.css:
--------------------------------------------------------------------------------
1 | /* Docsearch -------------------------------------------------------------- */
2 | /*
3 | Source: https://github.com/algolia/docsearch/
4 | License: MIT
5 | */
6 |
7 | .algolia-autocomplete {
8 | display: block;
9 | -webkit-box-flex: 1;
10 | -ms-flex: 1;
11 | flex: 1
12 | }
13 |
14 | .algolia-autocomplete .ds-dropdown-menu {
15 | width: 100%;
16 | min-width: none;
17 | max-width: none;
18 | padding: .75rem 0;
19 | background-color: #fff;
20 | background-clip: padding-box;
21 | border: 1px solid rgba(0, 0, 0, .1);
22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175);
23 | }
24 |
25 | @media (min-width:768px) {
26 | .algolia-autocomplete .ds-dropdown-menu {
27 | width: 175%
28 | }
29 | }
30 |
31 | .algolia-autocomplete .ds-dropdown-menu::before {
32 | display: none
33 | }
34 |
35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] {
36 | padding: 0;
37 | background-color: rgb(255,255,255);
38 | border: 0;
39 | max-height: 80vh;
40 | }
41 |
42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions {
43 | margin-top: 0
44 | }
45 |
46 | .algolia-autocomplete .algolia-docsearch-suggestion {
47 | padding: 0;
48 | overflow: visible
49 | }
50 |
51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header {
52 | padding: .125rem 1rem;
53 | margin-top: 0;
54 | font-size: 1.3em;
55 | font-weight: 500;
56 | color: #00008B;
57 | border-bottom: 0
58 | }
59 |
60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper {
61 | float: none;
62 | padding-top: 0
63 | }
64 |
65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column {
66 | float: none;
67 | width: auto;
68 | padding: 0;
69 | text-align: left
70 | }
71 |
72 | .algolia-autocomplete .algolia-docsearch-suggestion--content {
73 | float: none;
74 | width: auto;
75 | padding: 0
76 | }
77 |
78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before {
79 | display: none
80 | }
81 |
82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header {
83 | padding-top: .75rem;
84 | margin-top: .75rem;
85 | border-top: 1px solid rgba(0, 0, 0, .1)
86 | }
87 |
88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column {
89 | display: block;
90 | padding: .1rem 1rem;
91 | margin-bottom: 0.1;
92 | font-size: 1.0em;
93 | font-weight: 400
94 | /* display: none */
95 | }
96 |
97 | .algolia-autocomplete .algolia-docsearch-suggestion--title {
98 | display: block;
99 | padding: .25rem 1rem;
100 | margin-bottom: 0;
101 | font-size: 0.9em;
102 | font-weight: 400
103 | }
104 |
105 | .algolia-autocomplete .algolia-docsearch-suggestion--text {
106 | padding: 0 1rem .5rem;
107 | margin-top: -.25rem;
108 | font-size: 0.8em;
109 | font-weight: 400;
110 | line-height: 1.25
111 | }
112 |
113 | .algolia-autocomplete .algolia-docsearch-footer {
114 | width: 110px;
115 | height: 20px;
116 | z-index: 3;
117 | margin-top: 10.66667px;
118 | float: right;
119 | font-size: 0;
120 | line-height: 0;
121 | }
122 |
123 | .algolia-autocomplete .algolia-docsearch-footer--logo {
124 | background-image: url("data:image/svg+xml;utf8, ");
125 | background-repeat: no-repeat;
126 | background-position: 50%;
127 | background-size: 100%;
128 | overflow: hidden;
129 | text-indent: -9000px;
130 | width: 100%;
131 | height: 100%;
132 | display: block;
133 | transform: translate(-8px);
134 | }
135 |
136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight {
137 | color: #FF8C00;
138 | background: rgba(232, 189, 54, 0.1)
139 | }
140 |
141 |
142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight {
143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5)
144 | }
145 |
146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content {
147 | background-color: rgba(192, 192, 192, .15)
148 | }
149 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | A Simple, Opinionated Logging Utility • rlog
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
22 |
23 |
24 |
25 |
73 |
74 |
75 |
77 |
rlog is an opinionated, lightweight logging package for R.
78 |
It relies on long standing Unix traditions, to write simple log messages in a flexible way.
79 |
Log message output looks like this:
80 |
2021-02-21 17:19:06 [INFO] This is my log message
81 |
82 |
83 | Installation
84 |
Install rlog from GitHub with the following:
85 |
87 |
88 |
89 |
90 | Does R really need another logging package?
91 |
We think so, yes!
92 |
There are already loads of logging packages for R. Many are no longer maintained and of the remaining selection some are overly complex, making them less approachable for beginners.
93 |
Since logging should be an essential part of any production application or pipeline I think it’s important that as many people as possible are introduced to good logging practice.
94 |
If rlog doesn’t have enough features for you, I’d recommend the excellent “logger ” instead.
95 |
96 |
97 |
98 | rlog philosophy
99 |
The rlog philosophy is the Unix philosophy and as such, we expect applications using rlog to be able to integrate with other enterprise software quickly and efficiently.
100 |
rlog is simple by design and it relies on existing Unix/Linux norms to get the job done.
101 |
102 | Log message format is intentionally not configurable
103 | the log level can only be controlled by an environment variable
104 | log messages are written to standard output and standard error
105 |
106 |
107 |
108 |
109 | Usage
110 |
The best way to use rlag is to call the functions directly from within your applications.
111 |
There is one function per log message level:
112 |
119 |
If you run this code as-is without setting a custom LOG_LEVEL with the environment variable, you’ll get output like this:
120 |
2021-02-21 17:19:06 [FATAL] fatal
121 | 2021-02-21 17:19:06 [ERROR] error
122 | 2021-02-21 17:19:06 [WARN] warn
123 | 2021-02-21 17:19:06 [INFO] info
124 |
The “DEBUG” and “TRACE” message won’t be printed, since the default LOG_LEVEL is “INFO” and those message have lower priority.
125 |
Play around with setting the LOG_LEVEL directly in R and seeing what messages are emitted:
126 |
134 |
Gives us this output:
135 |
2021-02-21 17:19:06 [FATAL] fatal
136 | 2021-02-21 17:19:06 [ERROR] error
137 |
Remember though, the best way to set the environment variable is outside of the app. That way it’s easier to change at run-time.
138 |
So in your terminal you can do something like this before you run your script:
139 |
$ export LOG_LEVEL=TRACE
140 | $ ./my_script.R
141 |
Or you can even call your script with the appropriate value at run-time:
142 |
$ LOG_LEVEL=ERROR ./my_script.R
143 |
If you’re using RStudio Connect users can set an environment variable called LOG_LEVEL in the “Vars” tab of their apps control panel.
144 |
145 |
146 |
147 | Setting the log level
148 |
rlog relies on an environment variable called LOG_LEVEL to control which log messages are emitted.
149 |
If it’s not set, it will default to “INFO”.
150 |
The available levels – in decreasing order of severity – are as follows:
151 |
152 | fatal
153 | error
154 | warn
155 | info
156 | debug
157 | trace
158 |
159 |
When the LOG_LEVEL environment variable is set to “INFO”, only messages at that level and above will be emitted.
160 |
Another example:
161 |
162 | fatal
163 | error
164 | warn
165 | info
166 | debug <= If we set the log level here only messages of debug and above will be emitted.
167 | trace
168 |
169 |
This is a really powerful way of only including the messages you want to see in the log files at any given time. For example, you may choose to set the LOG_LEVEL to “TRACE” while developing your application or if it runs into a problem in production, but you might choose to run the application with a LOG_LEVEL of “ERROR” under normal circumstances.
170 |
171 |
172 |
173 | I want to write to a log file, not the console
174 |
rlog outputs it log messages into the console in the same way that most Unix/Linux tools do. Ordinary messages go to “standard output” (stdout ) and errors go to “standard error” (stderr ).
175 |
This means they can be captured in the standard Unix/Linux way:
176 |
./my_script.R > /path/to/file.log 2>&1
177 |
This command redirects stderr to stdout and drops it all into the /path/to/file.log file.
178 |
You can also keep the “normal” and error outputs separate:
179 |
./my_script.R > /path/to/file.log 2> /path/to/errors.log
180 |
Many enterprise software products, such as RStudio Connect will capture this output automatically and save it for you.
181 |
182 |
183 |
184 |
185 |
208 |
209 |
210 |
211 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------