/alogger

Simply the best logging framework for Erlang

Primary LanguageErlang

The alog application

Overview

Authors: Alexander Dergachev (alexander.dergachev@gmail.com), Artem Golovinsky (artemgolovinsky@gmail.com), Igor Karymov (ingham.k@gmail.com), Dmitry Groshev (lambdadmitry@gmail.com). License

Copyright (c) 2011 Siberian Fast Food
Authors: Alexander Dergachev alexander.dergachev@gmail.com
         Artem Golovinsky    artemgolovinsky@gmail.com
         Igor Karymov        ingham.k@gmail.com
         Dmitry Groshev      lambdadmitry@gmail.com
The contents of this file are subject to the Erlang Public License,
Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.

Rationale

There is a lot of loggers in the wild. You can consider to use one of them in your new project. After a while a new cool logger appears, and you want it, so, you have to change lots of places in you code, and definitely you have to recompile the entire project. That sucks, doesn't it?

The Abstract Logger Interface (alogger) brings completely new opportunities of logging. Here you go:

  • the possibility to introduce any new logger to your project without a need to change the project code at all

  • the interface will provide some neat features which are not exist in most of the existent loggers, like these:

    • the possibility to change the logging priority "on the fly" without any significant overhead thanks to some parse_transform and hot code reloading magic

    • the possibility to change the logging priority by modules or by special tags

So, basically, with alogger you'll be able to add any new logger to you project, you even won't have to recompile your code. You'll be able to control all your log flows from the shell or through the config file.

We don't invent a wheel, there's nothing like this around!

Implemented logger interfaces

A the moment there're four logger interfaces out of the box:

  • alog_tty: a simple one, it prints logs by io:format

  • alog_syslog: an interface towards Syslog daemon

  • alog_scribe: an interface towards Scribe log daemon through thrift protocol

  • alog_disk_log: an interface towards disk_log logging facility

How to use alogger and feel some magic

You can use alogger in different ways.

Using macroses: you can use only .hrl file like this

-include_lib("alog.hrl")

and you will get standart ?DBG/?INFO/?ERROR/... (you can find out more information in alog module, which contains function that mimic macroses names and arguments). Or you can also engage our parse transformation:

-include_lib("alog_pt.hrl").

This way you can use tuple expression (like ?DBG({A, B})) which are translated to debug message with both names and values of A and B. Tuple expression can contain strings (like ?DBG({A, "string", B})); a log message will contain something like

alog_examples:42:debug [< 0.52.0 >]->[]: A: "foo" B: bar

Using runtime API: this API consists of pure function calls. Functions are defined in alog module.

Configuration

alogger can be configured to write different flows (or streams of log messages) to different loggers. It can be done in config (alog.config) or in runtime with alog_control module.

        [{alog, [
                  {enabled_loggers, Loggers},
                  {flows, [
                          {Filter,PriorityPattern, Loggers},
                  ]},
		  {LoggerName,ListOfSettings}
                ]}
         ].

enabled_loggers - list of loggers, enabled by default.

flows - every flow is represented as tuple of setting.

{Filter, PriorityPattern, Loggers}

Filter = {tag, TagList} | {mod, ModList}

  • TagList is list of tags, Every tag is atom. If you set tag as filter, printouts with pointed tags is sent to loggers. Name of modules are no matter in this case.

  • ModList is list of modules which should be logged to loggers. Tags are no matter. When ModList is set to ['_'] log message from any module will be printed. Also you can set exceptions using [{'_', not_for, ExModList}] where ExModList is list of modules which should not be logged.

PriorityPattern = [{Exp, PrioName}] | [PrioName] | {Exp, PrioName} | PrioName

  • Exp - arithmetic expression filter for priority. >=, =<, >, <, =:=, /= are possible.

  • PrioName - name of priority. Possible: emergency, critical, error, warning, notice, info, debug

Loggers = [Logger]

  • Logger is atom. Name of logger.
{LoggerName, ListOfSettings}

LoggerName - name of logger module.

ListOfSettings = [Setting]

  • Setting is for logger.

How to run examples

We prepared some simple logging examples, so you could check how it works. You can run it by the following command from the Erlang shell:

> alog_examples:run_examples().

NOTE: if you have enabled alog_scribe logger interface, you should have Scribe log daemon installed and configured (an configuration example you can find in the priv directory). For more information about Scribe installation procedure see Scribe documentation.

How to implement your own interface

To implement your own interface you should introduce a module which implements the gen_alogger behaviour. It's possible to configure your interface modules through priv/alog.config file. For each log interface module there's a configuration entry, for example:

{alog_syslog, [{ident, "alogger"},
               {logopt, [cons, perror, pid]},
               {facility, user}]}

Also, gen_logger behaviour provides two helper functions: get_opt/2 and get_opt/3, you can use it in your start/1 function to get neccessary configuration, for example:

start(Opts) ->
    Ident = gen_alogger:get_opt(ident, Opts, ?DEF_IDENT),
    Logopt = gen_alogger:get_opt(logopt, Opts, ?DEF_LOGOPT),
    Facility = gen_alogger:get_opt(facility, Opts, ?DEF_FACILITY),
...

Log levels

Log levels are arranged in the following order.

LevelDescription
0. emergencysystem is unusable
1. alertaction must be taken immediately
2. criticalcritical conditions
3. errorerror conditions
4. warningwarning conditions
5. noticenormal but significant condition
6. infoinformational
7. debugdebug-level messages

For example, emergency < error, and debug > warning.

Last updated

Aug 7 2011 23:56:44

Packages

scribe

Modules

alog
alog_common_formatter
alog_config
alog_control
alog_disk_log
alog_error_logger_handler
alog_examples
alog_if_default
alog_parse_trans
alog_pt
alog_scribe
alog_syslog
alog_tty
gen_alogger