Skip to content

Commit

Permalink
[nop] Update README
Browse files Browse the repository at this point in the history
  • Loading branch information
ptaoussanis committed Oct 28, 2022
1 parent fbb3b74 commit 4b6e1c4
Showing 1 changed file with 92 additions and 87 deletions.
179 changes: 92 additions & 87 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,35 @@
<a href="https://www.taoensso.com" title="More stuff by @ptaoussanis at www.taoensso.com">
<img src="https://www.taoensso.com/taoensso-open-source.png" alt="Taoensso open-source" width="400"/></a>
<img src="https://www.taoensso.com/taoensso-open-source.png" alt="Taoensso open-source" width="350"/></a>

**[CHANGELOG]** | [API] | current [Break Version]:
**[CHANGELOG][]** | [API][] | current [Break Version][]:

```clojure
[com.taoensso/timbre "5.2.1"] ; See CHANGELOG for details
```

<!-- ![build status](https://github.com/ptaoussanis/timbre/workflows/build/badge.svg?branch=master) -->

> See [here](https://taoensso.com/clojure/backers) if you're interested in helping support my open-source work, thanks! - Peter Taoussanis
> See [here][backers] if to help support my open-source work, thanks! - [Peter Taoussanis][Taoensso.com]
# Timbre: a pure Clojure/Script logging library

Java logging can be a Kafkaesque mess of complexity that buys you little. Getting even the simplest logging working can be comically hard, and it often gets worse at scale as your needs become more sophisticated.
Getting even the simplest Java logging working can be maddeningly complex, and it often gets worse at scale as your needs become more sophisticated.

Timbre offers an **all Clojure/Script** alternative that's fast, deeply flexible, easy to configure with pure Clojure data, and that **just works out the box**. No XML.
Timbre offers an **all Clojure/Script** alternative that's fast, deeply flexible, easy to configure with pure Clojure data, and that **just works out the box**.

Supports optional interop with [tools.logging](https://github.com/ptaoussanis/timbre/blob/master/src/taoensso/timbre/tools/logging.clj) and [log4j/logback/slf4j](https://github.com/fzakaria/slf4j-timbre).

Happy hacking!

## Features
* Full **Clojure** + **ClojureScript** support (v4+).
* No XML or properties files. **A single, simple config map**, and you're set.
* Simple, flexible **fn appender model** with **middleware**.
* **Great performance** at any scale.
* Full **Clojure** & **ClojureScript** support, with built-in appenders for both.
* **A single, simple config map**, and you're set. No need for XML or properties files.
* Simple `(fn [data]) -> ?effects` appenders, and `(fn [data]) -> ?data` middleware.
* Easily save **raw logging arguments** to the DB of your choice.
* Easily filter logging calls by **any combination** of: level, namespace, appender.
* **Zero overhead** compile-time level/ns elision.
* Useful built-in appenders for **out-the-box** Clj+Cljs logging.
* Powerful, easy-to-configure **rate limits** and **async logging**.
* [Logs as Clojure values][] (v3+).
* Small, simple, cross-platform codebase.

## Community tools, appenders, etc.

Link | Description
------------------------ | -----------------------------------------------------
[@fzakaria/slf4j-timbre] | Route log4j/logback/sfl4j log output to Timbre
[@palletops/log-config] | Library to help manage Timbre logging config
Your link here? | **PR's welcome!**
* **Great performance** and flexibility at any scale.
* Small, simple, cross-platform pure-Clojure codebase.

## Getting started
## Quickstart

Add the necessary dependency to your project:

Expand All @@ -53,26 +41,20 @@ deps.edn: com.taoensso/timbre {:mvn/version "5.2.1"}
And setup your namespace imports:

```clojure
(ns my-clj-ns ; Clojure namespace
(ns my-ns
(:require
[taoensso.timbre :as timbre
;; Optional, just refer what you like:
:refer [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]))

(ns my-cljs-ns ; ; ClojureScript namespace
(:require
[taoensso.timbre :as timbre
:refer-macros [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]))
spy]]))
```

> You can also call `(timbre/refer-timbre)` to configure Clj ns referrals **automatically**.
> You can also call `(timbre/refer-timbre)` (Clj only) to refer everything above automatically.
### Logging
### Basic logging

By default, Timbre gives you basic `println` and `js/console` (v4+) output at a `:debug` log level:
By default, Timbre gives you basic `println` and `js/console` output for all logging calls of at least `:debug` log level:

```clojure
(info "This will print") => nil
Expand All @@ -88,53 +70,64 @@ By default, Timbre gives you basic `println` and `js/console` (v4+) output at a
(trace "This won't print due to insufficient log level") => nil
```

First-argument exceptions generate a nicely cleaned-up stack trace using [io.aviso.exception][] (Clj only):
First-argument exceptions will also generate a stack trace:

```clojure
(info (Exception. "Oh noes") "arg1" "arg2")
(info (Exception. "Oh no") "arg1" "arg2")
%> 15-Jun-13 19:22:55 localhost INFO [my-app.core] - arg1 arg2
java.lang.Exception: Oh noes
java.lang.Exception: Oh no
<Stacktrace>
```

Other utils include: `log-errors`, `log-and-rethrow-errors`, `logged-future`, and `handle-uncaught-jvm-exceptions!` (please see the [API] for details).
### Set the minimum logging level

A Timbre logging call will be disabled (noop) when the call's level (e.g. `(info ...)` is less than the active minimum level (e.g. `:warn`).

### Data flow
> Levels: `:trace` < `:debug` < `:info` < `:warn` < `:error` < `:fatal` < `:report`
Timbre's inherently a simple design, no magic. It's just Clojure data and functions:
- Call `(set-min-level! <min-level>)` to set the minimum level for **all** namespaces.
- Call `(set-ns-min-level! <min-level>)` to set the minimum level for the **current namespace** only.

1. Enabled logging calls generate a **data map**: `{:level _ :?ns-str _ ...}`
2. The resulting data map passes through any **middleware fns**, `(fn [data]) -> ?data`
3. The resulting data map is sent to all **appender fns**, `(fn [data]) -> ?effects`
> See the [config API][] for more.
### Configuration
## Architecture

This is the biggest win over Java logging IMO. Timbre's behaviour is entirelly controlled through a single Clojure map fully documented in about 100 lines of docstring:
Timbre's inherently a simple design, no magic. It's just **Clojure data and functions**.

- See Timbre's (v5) [config API][] for **full documentation**!
- See Timbre's (v5) [default config][].
Here's the flow for an `(info ...)` logging call:

Sophisticated behaviour is easily achieved through regular fn composition and the power of arbitrary Clojure fns: e.g. write to your database, send a message over the network, check some other state (e.g. environment config) before making a choice, etc.
1. Dynamic `*config*` is used as the current active [config][config API].
2. Is `:info` < the active minimum level? If so, end here and noop.
3. Is the current namespace filtered? If so, end here and noop.
4. Prepare a **log data map** of interesting [info][config API] incl. all logging arguments.
5. Pass the data map through any **middleware fns**: `(fn [data]) -> ?data`. These may transform the data. If returned data is nil, end here and noop.
6. Pass the data map to all **appender fns**: `(fn [data]) -> ?effects`. These may print output, save the data to a DB, trigger admin alerts, etc.

#### Log levels and ns filters: basics
## Configuration

Timbre logging calls will be disabled (noop) when:
Timbre's behaviour is controlled by the single dynamic `*config*` map, fully documented [here][config API].

- The call's logging level (e.g. `:info`) is < the active `:min-level` (e.g. `:warn`).
- The call is within a namespace not allowed by the current `:ns-filter` (e.g. `{:allow #{"*"} :deny #{"taoensso.*"}}`.
Its [default value][default config] can be easily overridden by:

#### Log levels and ns filters: advanced
- An [edn file][config API] on your resource path.
- A symbol defined by an [an environment variable][config API] or [JVM property][config API].
- A variety of [provided utils][config API].
- Standard Clojure utils (`binding`, `alter-var-root!`/`set!`).

- `:min-level` can also be a vector **mapping namespaces to minimum levels**, e.g.: `[[#{\"taoensso.*\"} :error] ... [#{\"*\"} :debug]]`.
- Appenders can optionally have their own `:min-level`.
Sophisticated behaviour is achieved through normal fn composition, and the power of arbitrary Clojure fns: e.g. write to your database, send a message over the network, check some other state (e.g. environment config) before making a choice, etc.

With all of the above, it's possible to easily enable/disable logging based on **any combination** of:
## Advanced minimum levels and namespace filtering

- Logging call level
- Namespace
- Appender
The `*config*` `:min-level` and `:ns-filter` values both support sophisticated pattern matching, e.g.:

#### Log levels and ns filters: compile-time elision
- `:min-level`: `[[#{\"taoensso.*\"} :error] ... [#{\"*\"} :debug]]`.
- `:ns-filter`: `{:allow #{"*"} :deny #{"taoensso.*"}}`.

As usual, the full functionality is described by the [config API][].

Note that both `:min-level` and `:ns-filter` may also be easily overridden on a **per-appender** basis.

### Compile-time elision

By setting the [relevant][config API] JVM properties or environment variables, Timbre can actually entirely exclude the code for disabled logging calls **at compile-time**, e.g.:

Expand All @@ -151,19 +144,22 @@ lein cljsbuild once # Compile js with appropriate logging calls excluded
lein uberjar # Compile jar ''
```

### Disabling stacktrace colors
## Disable stacktrace colors

ANSI colors are enabled by default for stacktraces. To turn these off (e.g. for log files or emails), you can add the following entry to your top-level config **or** individual appender map/s:
ANSI colors are enabled by default for Clojure stacktraces. To turn these off (e.g. for log files or emails), you can add the following entry to your top-level config or individual appender map/s:

```clojure
:output-fn (partial timbre/default-output-fn {:stacktrace-fonts {}})
:output-opts {:stacktrace-fonts {}}
```

And/or you can set the `TAOENSSO_TIMBRE_DEFAULT_STACKTRACE_FONTS_EDN` environment variable (supports edn).
And/or you can set the:

- `taoensso.timbre.default-stacktrace-fonts.edn` JVM property, or
- `TAOENSSO_TIMBRE_DEFAULT_STACKTRACE_FONTS_EDN` environment variable.

### Built-in appenders
## Included appenders

#### Basic file appender
### Basic file appender

```clojure
;; (:require [taoensso.timbre.appenders.core :as appenders]) ; Add to ns
Expand All @@ -175,7 +171,7 @@ And/or you can set the `TAOENSSO_TIMBRE_DEFAULT_STACKTRACE_FONTS_EDN` environmen
;; (timbre/merge-config! {:appenders {:spit nil}} ; To remove entirely
```

#### Redis ([Carmine]) appender (v3+)
### [Carmine][] (Redis) appender

```clojure
;; [com.taoensso/carmine <latest-version>] ; Add to project.clj deps
Expand All @@ -191,11 +187,11 @@ This gives us a high-performance Redis appender:
* Only the most recent instance of each **unique entry** is kept.
* Resulting **log is just a Clojure value**: a vector of log entries (maps).

Clojure has a rich selection of built-in and 3rd party tools for querying values like this.
Clojure has a rich selection of built-in and community tools for querying values like this.

See also `car-appender/query-entries`.

#### Email ([Postal]) appender
### [Postal][] (email) appender

```clojure
;; [com.draines/postal <latest-version>] ; Add to project.clj deps
Expand All @@ -209,35 +205,46 @@ See also `car-appender/query-entries`.
{:from "me@draines.com" :to "foo@example.com"})}})
```

#### Other included appenders
### Community appenders

A number of community appenders are included out-the-box [here](https://github.com/ptaoussanis/timbre/tree/master/community/src). These include appenders for Android, Logstash, Slack, Sentry, NodeJS, Syslog, PostgreSQL, etc.

Thanks goes to the respective authors!
**Please see the relevant namespace docstring for details**.

GitHub PRs for new appenders and for appender maintenance very welcome!

## More community tools, appenders, etc.

A number of community appenders are included out-the-box [here](https://github.com/ptaoussanis/timbre/tree/master/src/taoensso/timbre/appenders/community). **Please see the relevant docstring for details**. Thanks goes to the respective authors!
Some externally-hosted items are listed here:

Just give me a shout if you've got an appender you'd like to have added.
Link | Description
-------------------------- | -----------------------------------------------------
[@fzakaria/slf4j-timbre][] | Route log4j/logback/sfl4j log output to Timbre
[@palletops/log-config][] | Library to help manage Timbre logging config
Your link here? | **PR's welcome!**

## This project supports the ![ClojureWerkz-logo] goals
## This project supports the ![ClojureWerkz-logo][] goals

[ClojureWerkz] is a growing collection of open-source, **batteries-included Clojure libraries** that emphasise modern targets, great documentation, and thorough testing.
[ClojureWerkz][] is a growing collection of open-source, **batteries-included Clojure libraries** that emphasise modern targets, great documentation, and thorough testing.

## Contacting me / contributions

Please use the project's [GitHub issues page] for all questions, ideas, etc. **Pull requests welcome**. See the project's [GitHub contributors page] for a list of contributors.
Please use the project's [GitHub issues page][] for all questions, ideas, etc. **Pull requests welcome**. See the project's [GitHub contributors page][] for a list of contributors.

Otherwise, you can reach me at [Taoensso.com]. Happy hacking!
Otherwise, you can reach me at [Taoensso.com][]. Happy hacking!

\- [Peter Taoussanis]
\- [Peter Taoussanis][Taoensso.com]

## License

Distributed under the [EPL v1.0] \(same as Clojure).
Copyright &copy; 2015-2022 [Peter Taoussanis].
Distributed under the [EPL v1.0][] \(same as Clojure).
Copyright &copy; 2015-2022 [Peter Taoussanis][Taoensso.com].

<!--- Standard links -->
[Taoensso.com]: https://www.taoensso.com
[Peter Taoussanis]: https://www.taoensso.com
[@ptaoussanis]: https://www.taoensso.com
[More by @ptaoussanis]: https://www.taoensso.com
[Break Version]: https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md
[backers]: https://taoensso.com/clojure/backers

<!--- Standard links (repo specific) -->
[CHANGELOG]: https://github.com/ptaoussanis/timbre/releases
Expand All @@ -249,14 +256,12 @@ Copyright &copy; 2015-2022 [Peter Taoussanis].

<!--- Unique links -->
[logging profiler]: #profiling
[Logs as Clojure values]: #redis-carmine-appender-v3
[@palletops/log-config]: https://github.com/palletops/log-config
[@fzakaria/slf4j-timbre]: https://github.com/fzakaria/slf4j-timbre
[io.aviso.exception]: https://github.com/AvisoNovate/pretty
[Carmine]: https://github.com/ptaoussanis/carmine
[Tufte]: https://github.com/ptaoussanis/tufte
[Postal]: https://github.com/drewr/postal
[ClojureWerkz-logo]: https://raw.github.com/clojurewerkz/clojurewerkz.org/master/assets/images/logos/clojurewerkz_long_h_50.png
[ClojureWerkz]: http://clojurewerkz.org/
[config API]: http://ptaoussanis.github.io/timbre/taoensso.timbre.html#var-*config*
[default config]: http://ptaoussanis.github.io/timbre/taoensso.timbre.html#var-default-config
[default config]: http://ptaoussanis.github.io/timbre/taoensso.timbre.html#var-default-config

0 comments on commit 4b6e1c4

Please sign in to comment.