Skip to content

Clojure library with utilities and a DSL for logging on top of Timbre with support for Riemann.

License

Notifications You must be signed in to change notification settings

kitrerp/active-logger

 
 

Repository files navigation

active-logger

Utilities and DSL for logging on top of Timbre with support for Riemann, Logstash, and more.

https://img.shields.io/clojars/v/de.active-group/active-logger.svg

TL;DR

If you just want to get going, here is a minimal working example on how to start logging events.

  1. Add `active-logger` and `active-clojure` to your `deps.edn`:
    {:deps {de.active-group/active-clojure {:mvn/version "0.35.0"}
            de.active-group/active-logger  {:git/url "https://github.com/active-group/active-logger"
                                            :sha     "d53a0a55211ec6a8aed0e3315e5dc7679f0f3f3e"}}}
        
  2. Define the configuration to use and initialize the logging backend.
    (ns my.app
      (:require [active.clojure.config :as active-config]
                [active.clojure.logger.event :as event-logger]
                [active.clojure.logger.config.timbre :as timbre-config]))
    
    (def config-map
      {:timbre-config 
       {:level :debug  ;; Log everything that is at least a :debug message.
        :appenders
        {;; Print messages to stdout/stderr.
         :println '(println)
         ;; Write messages to a file.
         :spit '(spit "/tmp/my-app.log")
         ;; Submit messages to a logstash instance.
         :logstash '(logstash "localhost" 4660)}}})
    
    (def schema (active-config/schema "Configuration schema." timbre-config/timbre-config-section))
    (def config (active-config/make-configuration schema [] config-map))
    
    ;; Initialize the event-logger.
    (-> config
        (active-config/section-subconfig timbre-config/timbre-config-section)
        timbre-config/configure-events-logging
        event-logger/set-global-log-events-config!)
        
  3. Start logging some events:
    (ns my.app
      (:require ...
                [active.clojure.logger.event :as event-logger]))
    
    (event-logger/log-event! :info "We are live!")
        

Usage

active-logger is intended to be used alongside =active-clojure= and follows the same naming scheme (all active-logger namespaces can be found under active.clojure.logger).

There are two basic ways to do logging with active-logger: Effectful and monadic. In general, both of theses options are available for each logging function in active-logger.

Effectful

Effectful logging refers to logging functions that immediately execute. Usually they are signified by a bang (!) at the end of the var’s name (i. e. active.clojure.logger.event/log-event!). In any non-monadic execution context, use these functions for logging, metrics, etc.

Monadic

Monadic logging refers to logging functions that can be used to formulate the intent on logging at this location when executing a monadic program. The log function will only be executed when the monadic program is run.

Monadic in this context means programs defined using active.clojure.monad.

Example for effectful and monadic logging

(ns my.ns
  (:require [active.clojure.config :as active-config]
            [active.clojure.logger.config.timbre :as timbre-config]
            [active.clojure.logger.event :as event-logger]
            [active.clojure.monad :as monad :refer [monadic]]))

;; NOTE: Initialize as shown in TL;DR section.

;; Effectful logging 
(let [res (+ 2 2)]
  (event-logger/log-event! :trace (str "res =" res))
  res)     
;; 2020-07-11 15:19:02.659 host INFO [my.ns] TRACE - res = 4
;; => 4


;; Monadic logging
(def prog (monadic [res (monad/return 4)]
                   (event-logger/log-event :trace (str "res =" res))
                   (monad/return 4)))

(monad/run-free-reader-state-exception 
 event-logger/log-events-command-config
 prog)
;; 2020-07-11 15:19:02.659 host INFO [my.ns] TRACE - res = 4
;; => 4

Components

active-logger includes several different entities that can be logged.

Event

Events are reports of things that the system did that may be of interest for later perusal by system administrator in case of failures or by developers. Each event carries a namespace saying where the event came from, and a level that specifies how “important” the event is. Functions to log events can be found in active.clojure.logger.event.

Metrics

Metrics can be used to log metrics for specified parts of your system. Functions to log events can be found in active.clojure.logger.metric.

Timed Metrics

Timed metrics can be used to log timing characteristics specified parts of your system. Functions to log events can be found in active.clojure.logger.timed-metric.

State Change

State changes are for monitoring the live operation of a system. They announce for a certain system component its state, its service. Functions to log events can be found in active.clojure.logger.state-change.

Configuration

active-logger comes with two basic configuration sections: Timbre and Riemann. For more information on active.clojure.config, refer to =active-clojure=’s documentation on the topic.

In general, to provide a configuration means to supply a map that contains only keys and values according to some schema defined as a active.clojure.config/schema and consumed by active.clojure.config/make-configuration.

Timbre

There are lots of configuration options to define how the event logger should behave. For a full list of options, refer to the respective sources.

Here, we will cover the most important options:

:level

default: :debug

The minimum level a message must have to be printed. Possible values are #{:trace :debug :info :warn :error :fatal :report}.

:appenders

default: {:println (println)}

Defines how messages are printed (stdout, to a file, …). An appender spec is a list starting with one of {spit, rotor, logstash, println}, followed by keyword parameters corresponding to the respective appender.

Multiple appenders can be configured and active at the same time. A full example of an appender configuration might look like this:

{:appenders {:split   (spit {:fname "/tmp/app.log"})
             :riemann (riemann {:host "localhost"
                                :port 5555})
             :println (println)}}

Appender: spit

Specifies an appender that writes to a file, specified via the :fname setting. Example: {:spit (spit {:fname "my.log"})}

Appender: rotor

Specifies an appender that writes to a file and rotates the file when it reaches a given file size. It accepts the following settings:

optiondescriptiondefault
:pathPath to log file. file, historical versions are suffixed with a 3-digit index."./timbre-rotor.log"
:max-sizeMaximum size of a log file in bytes. Log files are rotated when they exceed this size.1.048.576 bytes (1~MB)
:backlogNumber of rotated logs to keep.5

Example:

{:rotor (rotor {:path "/tmp/project.log" 
                :max-size 1073741824
                :backlog 999})}

Appender: println

Specifies an appender that will print regular log entries to stdout, errors to stderr. Example: {:println (println)}

Appender: logstash

Specifies an appender that writes to a Logstash instance. It takes two arguments: the host name, and the port number of the Logstash instance. Example: {:logstash (logstash "localhost" 4660)}

Appender: riemann

Specifies an appender that writes to a Riemann instance. It accepts the following settings:

optiondescriptiondefault
:hostThe host Riemann is served on.“localhost”
:portThe host Riemann is listening on.5555

Example

{:riemann (riemann {:host "localhost" 
                    :port 5555})}

:ns-blacklist

It is possible to ignore specific namespaces in the log-output. ns-blacklist’s value it a sequence of glob-patterns. Matches will be ignored. Example: {:ns-blacklist ["my.project.internal.*"]}

:ns-whitelist

Converse of ns-blacklist: All specified patterns are included in the log output, everything else is ignored. Example: {:ns-whitelist ["nothing.else.matters"]}

:timestamp-opts

Section containing three settings related to how timestamps are formatted in logs:

optiondescription
:patternPattern for the timestamp (see SimpleDateFormat)
:localeThis is an IETF BCP 47 language tag string specifying the locale such as "de-DE" or "en-US" or :jvm-default.
:timezoneThis is an ID for the time zone relative to which log entry dates should formatted. This can be a full name such as "Germany/Berlin", or a custom ID such as "GMT-8:00". The value may also be :jvm-default for the default time zone, and :utc for UTC.

Riemann

Here are the configuration settings for Riemann. They happen in the :riemann section:

optiondescriptiondefault
:hostString specifying the host where Riemann runs."127.0.0.1
:portPort where Riemann runs.5555
:tls?Specifies whether the communication with Riemann should use TLS. It can be true or falsefalse
:keyIf :tls? is true, use the specified TLS key-file.-
:certIf :tls? is true, use the specified TSL cert-file.-
:ca-certIf :tls? is true, use the specified TSL CA cert-file.-

License

Copyright © 2020 Active Group GmbH

This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.

This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.

About

Clojure library with utilities and a DSL for logging on top of Timbre with support for Riemann.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Clojure 100.0%