Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add leveled logging #16

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## v0.1.9 - (unreleased)
- Added flag to support ElasticSearch v6.x correctly
- Added built-in leveled logging
- Deprecated `:transform` in favor of transducers via `:transduce`


## v0.1.8 - (2020-03-09)
Expand Down
108 changes: 104 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Here some features and key design decisions that make ***μ/log*** special:
* Adding publishers won't affect logging performances
* Extremely easy to create *stateful* publishers for new systems
* Wide range of publishers available
* Built-in and customizable leveled logging
* *Event logs are useful, but not as important as process flow
(therefore preferable to drop events rather than crashing the
process)*
Expand All @@ -49,7 +50,7 @@ Available publishers:
Existing logging libraries are based on a design from the 80s and
early 90s. Most of the systems at the time where developed in
standalone servers where logging messages to console or file was the
predominant thing to do. Logging was mostly providing debbugging
predominant thing to do. Logging was mostly providing debugging
information and system behavioural introspection.

Most of modern systems are distributed in virtualized machines that
Expand All @@ -72,7 +73,7 @@ decades.
I believe we need the break free of these anachronistic design and use
event loggers, *not message loggers*, which are designed for dynamic
distributed systems living in cloud and using centralized log
aggregators. *So here is **μ/log** designed for this very purpose.*
aggregators. *So here is ***μ/log*** designed for this very purpose.*


## Usage
Expand Down Expand Up @@ -153,7 +154,7 @@ aggregate on it in a specialized timeseries database.
Adding events which are rich in attributes and dimensions is extremely
useful, however it is not easy to have all the attributes and
dimensions at your disposal everywhere in the code. To get around
this problem **μ/log** supports the use of context.
this problem ***μ/log*** supports the use of context.

There are two levels of context, a global level and a local one.

Expand Down Expand Up @@ -256,14 +257,69 @@ Local context works across function boundaries:

```

## Leveled logging

Like many logging libraries, ***μ/log*** provides a default
hierarchy of log levels:

* `verbose`
* `debug`
* `info`
* `warning`
* `error`
* `fatal`

The built-in publishers support a log level configuration
to filter out events with an inferior level. Once a publisher is
configured with a log level, the `μ/log` macro will still produce
log events, but the publisher will filter them out, unless the
`:mulog/level` key is provided with a level *greater than or equal*
to the one specified in the publisher's configuration.

The `μ/verbose`, `μ/debug`, `μ/info`, `μ/warning`, `μ/error` and
`μ/fatal` macros leverage the use of local contexts to provide
a friendlier API.

For example:

``` clojure
(ns your-ns
(:require [com.brunobonacci.mulog :as μ]
[com.brunobonacci.mulog.levels :as lvl]))

(μ/start-publisher! {:type :console
:level ::lvl/info})

(μ/log ::system-started :init-time 32)
;; nothing...

;; set global context
(μ/set-global-context! {:mulog/level ::lvl/info})

(μ/log ::system-started :init-time 32)
;; {:mulog/level :com.brunobonacci.mulog.levels/info, :mulog/timestamp 1572709206048, :mulog/event-name :your-ns/system-started, :mulog/namespace "your-ns", :init-time 32}

(μ/info ::system-started :init-time 32)
;; same as above

(μ/log ::system-started :mulog/level ::lvl/warning :init-time 32)
;; {:mulog/level :com.brunobonacci.mulog.levels/warning, :mulog/timestamp 1572709332340, :mulog/event-name :your-ns/system-started, :mulog/namespace "your-ns", :init-time 32}

(μ/warning ::system-started :init-time 32)
;; same as above

(μ/debug ::system-started :init-time 32)
;; nothing...
```

## Best practices

Here some best practices to follow while logging events:

* Use namespaced keywords or qualified strings for the `event-name`
* Log values not opaque objects, objects will be turned into strings
which diminishes their value
* Do now log mutable values, since rendering is done asynchronously
* Do not log mutable values, since rendering is done asynchronously
you could be logging a different state. If values are mutable
capture the current state (deref) and log it.
* Avoid logging deeply nested maps, they are hard to query.
Expand All @@ -283,11 +339,22 @@ The available configuration options:
``` clojure
{:type :console

;; a log level from the `levels/default-levels` hierarchy.
;; This configuration will make the publisher filter out any
;; log event without `:mulog/event` key or with a value which
;; is not a descendant of this level. (since v0.1.9)
;; Will be composed with the transformation described below.
:level nil

;; DEPRECATED since 0.1.9
;; a function to apply to the sequence of events before publishing.
;; This transformation function can be used to filter, tranform,
;; anonymise events before they are published to a external system.
;; by defatult there is no transformation. (since v0.1.8)
:transform identity

;; like `:transform`, but is a transducer. (since v0.1.9)
:transduce (map identity)
}

```
Expand All @@ -312,11 +379,22 @@ The available configuration options:
;; If the file already exists, it will append the new events.
:filename "/tmp/mulog/events.log"

;; a log level from the `levels/default-levels` hierarchy.
;; This configuration will make the publisher filter out any
;; log event without `:mulog/event` key or with a value which
;; is not a descendant of this level. (since v0.1.9)
;; Will be composed with the transformation described below.
:level nil

;; DEPRECATED since 0.1.9
;; a function to apply to the sequence of events before publishing.
;; This transformation function can be used to filter, tranform,
;; anonymise events before they are published to a external system.
;; by defatult there is no transformation. (since v0.1.8)
:transform identity

;; like `:transform`, but is a transducer. (since v0.1.9)
:transduce (map identity)
}

```
Expand Down Expand Up @@ -384,11 +462,22 @@ The available configuration options:
;; See more on that in the link below.
:name-mangling true

;; a log level from the `levels/default-levels` hierarchy.
;; This configuration will make the publisher filter out any
;; log event without `:mulog/event` key or with a value which
;; is not a descendant of this level. (since v0.1.9)
;; Will be composed with the transformation described below.
:level nil

;; DEPRECATED since 0.1.9
;; a function to apply to the sequence of events before publishing.
;; This transformation function can be used to filter, tranform,
;; anonymise events before they are published to a external system.
;; by defatult there is no transformation. (since v0.1.8)
:transform identity

;; like `:transform`, but is a transducer. (since v0.1.9)
:transduce (map identity)
}

```
Expand Down Expand Up @@ -438,11 +527,22 @@ The available configuration options:
;; as global context
;; :key-field :puid

;; a log level from the `levels/default-levels` hierarchy.
;; This configuration will make the publisher filter out any
;; log event without `:mulog/event` key or with a value which
;; is not a descendant of this level. (since v0.1.9)
;; Will be composed with the transformation described below.
:level nil

;; DEPRECATED since 0.1.9
;; a function to apply to the sequence of events before publishing.
;; This transformation function can be used to filter, tranform,
;; anonymise events before they are published to a external system.
;; by defatult there is no transformation. (since v0.1.8)
:transform identity

;; like `:transform`, but is a transducer. (since v0.1.9)
:transduce (map identity)
}
```

Expand Down
Loading