Alchemy Logging (alog)

The alog framework provides tunable logging with easy-to-use defaults and power-user capabilities. The mantra of alog is "Log Early And Often". To accomplish this goal, alog makes it easy to enable verbose logging at develop/debug time and trim the verbosity at production run time, all while avoiding performance degredation by using lazily evaluated log messages which only render if enabled. The alog project maintains language-naitve implementations in many popular programming languages with the goal of giving a consistent application logging experience both when writing your code and when administering a cloud service written in multiple programming languages.

Channels and Levels

The primary components of the framework are channels and levels which allow for each log statement to be enabled or disabled when appropriate.

Levels: Each logging statement is made at a specific level. Levels provide sequential granularity, allowing detailed debugging statements to be placed in the code without clogging up the logs at runtime.   The sequence of levels and their general usage is as follows:

  1. off: Disable the given channel completely
  2. fatal: A fatal error has occurred. Any behavior after this statement should be regarded as undefined.
  3. error: An unrecoverable error has occurred. Any behavior after this statement should be regarded as undefined unless the error is explicitly handled.
  4. warning: A recoverable error condition has come up that the service maintainer should be aware of.
  5. info: High-level information that is valuable at runtime under moderate load.
  6. trace: Used to log begin/end of functions for debugging code paths.
  7. debug: High-level debugging statements such as function parameters.
  8. debug1: High-level debugging statements.
  9. debug2: Mid-level debugging statements such as computed values.
  10. debug3: Low-level debugging statements such as computed values inside loops.
  11. debug4: Ultra-low-level debugging statements such as data dumps and/or statements inside multiple nested loops.

Channels: Each logging statement is made to a specific channel. Channels are independent of one another and allow for logical grouping of log messages by functionality. A channel can be any string. A channel may have a specific level assigned to it, or it may use the configured default level if it is not given a specific level filter.

Using this combination of Channels and Levels, you can fine-tune what log statements are enabled when you run your application under different circumstances.

Standard Configuration

There are two primary pieces of configuration when setting up the alog environment:

default_level: This is the level that will be enabled for a given channel when a specific level has not been set in the filters.

filters: This is a mapping from channel name to level that allows levels to be set on a per-channel basis.


All alog implementations support two styles of formatting:

pretty: The pretty formatter is designed for development-time logging, making it easy to visually scan your log messages and follow the flow of execution

json: The json formatter is designed for production-runtime logging, making it easy to ingest structured representations of your runtime logs into a cloud log monitoring framework such as Sysdig

As a convenience, a converter is also provided from json -> pretty so that production logs can be read and visually parsed in a similar manner to development-time logs. The pretty -> json conversion is not provided since the header formatting for pretty logs can be lossy when channel names are truncated.


This section provides the high level details on installing and using each available implementation.


For full details see src/python


pip install alchemy-logging


import alog
alog.configure(default_level="info", filters="FOO:debug2,BAR:off")
channel = alog.use_channel("FOO")
channel.debug("Hello alog!")


For full details see src/ts


npm install alchemy-logging


import * as alog from 'alchemy-logging';
alog.configure('info', 'FOO:debug2,BAR:off');
alog.debug('FOO', 'Hello alog!');


For full details see src/go


go get


package main
import (
func main() {
	alog.Config(alog.INFO, alog.ChannelMap{
		"FOO": alog.DEBUG2,
		"BAR": alog.OFF,
	alog.Log("FOO", alog.DEBUG, "Hello alog!")


For full details see src/cpp


In your CMakeLists.txt using CPM:

set(ALOG_VERSION main CACHE STRING "The version (point in git history) of alog to use")
  NAME alog
  GITHUB_REPOSITORY IBM/alchemy-logging


#include <alog/logger.hpp>

int main()
    ALOG_SETUP("info", "FOO:debug2,BAR:off");
    ALOG(FOO, debug2, "Hello alog!");


GitHub - IBM/alchemy-logging: Application logging libraries with consistent semantics across c++, python, typescript, and go
Application logging libraries with consistent semantics across c++, python, typescript, and go - GitHub - IBM/alchemy-logging: Application logging libraries with consistent semantics across c++, py...