All Projects → AvisoNovate → Logging

AvisoNovate / Logging

Licence: apache-2.0
Easy setup of clojure.tools.logging w/ SLF4j, plus request correlation

Programming Languages

clojure
4091 projects

Labels

Projects that are alternatives of or similar to Logging

Yii2 Slack Log
Pretty Slack log target for Yii 2
Stars: ✭ 24 (+14.29%)
Mutual labels:  logging
Pylogging
🏉 Python Logging Library
Stars: ✭ 9 (-57.14%)
Mutual labels:  logging
Gollum
An n:m message multiplexer written in Go
Stars: ✭ 883 (+4104.76%)
Mutual labels:  logging
Logger
HTTP middleware for Go that logs web requests to an io.Writer.
Stars: ✭ 24 (+14.29%)
Mutual labels:  logging
Command Bus
Java implementation of the Command-Bus pattern for Spring and CDI
Stars: ✭ 26 (+23.81%)
Mutual labels:  logging
Logger Telegram Backend
A logger backend for Telegram
Stars: ✭ 13 (-38.1%)
Mutual labels:  logging
Yii2 Telegram Log
Telegram log target for Yii 2
Stars: ✭ 24 (+14.29%)
Mutual labels:  logging
Cartus
A structured logging abstraction with multiple backends.
Stars: ✭ 21 (+0%)
Mutual labels:  logging
Wufei
Async Kuberenetes Namespace Log Recorder / Streamer
Stars: ✭ 27 (+28.57%)
Mutual labels:  logging
Loggingprint
Swift logging only when in Debug mode.
Stars: ✭ 14 (-33.33%)
Mutual labels:  logging
Phildb
Timeseries database
Stars: ✭ 25 (+19.05%)
Mutual labels:  logging
Discord Scripts
A collection of scripts to enhance your Discord experience.
Stars: ✭ 26 (+23.81%)
Mutual labels:  logging
Trail
Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platform the code is running.
Stars: ✭ 13 (-38.1%)
Mutual labels:  logging
Liblog
LibLog is a single file for you to either copy/paste or install via nuget, into your library/framework/application to provide a logging abstraction.
Stars: ✭ 925 (+4304.76%)
Mutual labels:  logging
Humblelogging
HumbleLogging is a lightweight C++ logging framework. It aims to be extendible, easy to understand and as fast as possible.
Stars: ✭ 15 (-28.57%)
Mutual labels:  logging
Znetcs.aspnetcore.logging.entityframeworkcore
This is Entity Framework Core logger and logger provider. A small package to allow store logs in any data store using Entity Framework Core.
Stars: ✭ 24 (+14.29%)
Mutual labels:  logging
Fluentd
Log shipping mechanism for Deis Workflow
Stars: ✭ 10 (-52.38%)
Mutual labels:  logging
Rsyslog
An R interface to syslog, the POSIX system logger API
Stars: ✭ 21 (+0%)
Mutual labels:  logging
Belogging
Easy and opinionated logging configuration for Python apps
Stars: ✭ 20 (-4.76%)
Mutual labels:  logging
Eliot
Eliot: the logging system that tells you *why* it happened
Stars: ✭ 874 (+4061.9%)
Mutual labels:  logging

Logging - Clojure logging with Logback and SLF4J plus request correlation across servers

image:https://img.shields.io/clojars/v/io.aviso/logging.svg[Clojars Project, link="http://clojars.org/io.aviso/logging"]

image:https://circleci.com/gh/AvisoNovate/logging/tree/master.svg?style=svg["CircleCI", link="https://circleci.com/gh/AvisoNovate/logging/tree/master"]

Logging is available under the terms of the Apache Software License 2.0.

link:http://avisonovate.github.io/docs/logging/[API Documentation]

Dependencies

Mostly, we set up the dependencies so that link:https://github.com/clojure/tools.logging[clojure.tools.logging], uses link:http://www.slf4j.org/[SLF4J] and link:http://logback.qos.ch/[Logback].

We also include the link:http://www.slf4j.org/legacy.html#jclOverSLF4J[shim library] that converts link:http://commons.apache.org/proper/commons-logging/[Apache Commons Logging] to use SLF4J as well.

Setup

The namespace io.aviso.logging.setup performs all the necessary setup; it installs link:https://github.com/AvisoNovate/pretty[pretty exception reporting] for console output and commons logging output, as well as a default uncaught exception handler (that logs the uncaught exception).

Simply have some part of your application require this namespace.

Request Correlation

Ever try to trace a request from a client through a cluster of services? Even if you can get all the logs in one place, how do you pick out the single thread of requests and responses from all the other requests and responses?

With request correlation, each request gets assigned a correlation id on entry to the system. When one server sends a request to another server, it includes the correlation id as a header on the request.

That, plus a little bit of logic in your Logback configuration, allows every request to be flagged.

Request Correlation Middleware

The function io.aviso.logging.correlation/wrap-with-request-correlation is a Ring middleware function; it is passed a Ring request handler and wraps it.

On each request, the request correlation id is extracted, or generated if not present. By default, the correlation id comes from the Correlation-Id header, and is generated as a random UUID if not present.

In addition, the io.aviso.logging.correlation/*correlation-id* Var is bound to the correlation id. This little bit of semi-global state can be used when making requests to other servers, to include the correlation id in the request.

Logging the Correlation Id

The final piece of the puzzle is to get the correlation id logged. this is accomplished by making the correlation id a link:http://logback.qos.ch/manual/mdc.html[mapped diagnostic context].

In your logback.xml (or logback-test.xml):

[source,xml]

<appender name="SETUP-CORR-ID" class="io.aviso.logging.CorrelationIdAppender"/>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%date{HH:mm:ss.SSS} %mdc{correlation-id} %-5level [%thread] %logger{} - %msg%n</pattern>
    </encoder>
</appender>

<root level="info">
    <appender-ref ref="SETUP-CORR-ID"/>
    <appender-ref ref="STDOUT"/>
</root>

The CorrelationIdAppender is used to set up the correlation id into the MDC (the mapped diagnostic context). After that, the %mdc{correlation-id} form can extract that value and include it in the logged output.

Extra MDC

Version 0.2.0 adds a generalization of request correlation; an arbitrary map of keys and values can be added to the MDC.

This takes the form of a new appender class, io.aviso.logging.ExtraMDCAppender:

[source,xml]

<appender name="SETUP-MDC" class="io.aviso.logging.ExtraMDCAppender"/>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%date{HH:mm:ss.SSS} %mdc{authenticated} %-5level [%thread] %logger{} - %msg%n</pattern>
    </encoder>
</appender>

<root level="info">
    <appender-ref ref="SETUP-MDC"/>
    <appender-ref ref="STDOUT"/>
</root>

In the above example, authenticated is presumably a value that may be bound into the *extra-mdc* var.

A macro, with-mdc, makes it easy to bind new keys and values into the extra MDC.

Logback's message diagnostic map is mutable and designed to be inherited by sub-threads in a way that overlaps with Clojure's inheriting of dynamic vars. Because of this, a value stored into the MDC is "sticky" and may leak into later logging on the thread, even after exiting the with-mdc block.

The best solution for this is to always set a default for any key that may be added inside a with-mdc block:

[source,clojure]

(require '[io.aviso.logging.mdc :refer [set-mdc-default with-mdc] '[clojure.tools.logging :as l])

(set-mdc-default {:authenticated "none"})

(with-mdc {:authenticated "http"} ... (l/info "Handling request") ... )

Although the "authenticated" key will have value "https" in the Logback MDC even after exiting from the with-mdc block, any subsequent logging will reset it back to the default, "none".

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].