Skip to content
hyperthunk edited this page Jun 16, 2011 · 3 revisions

Fastlog has a rather simple API. The fastlog application should first be started. If you have appstart installed, you can start it by calling fastlog:start/0, otherwise you should call application:start(fastlog) instead.

Adding Loggers

Loggers are identified by an atom (or string) tag, which may include wildcards used to match on sub-categories at runtime. When a loggers tag contains a wildcard, and/or a logging function is called with a tag intended to match on a subset of an identity (e.g., calling foo.bar.* with foo.bar.baz), both the logger identify and the complete path being supplied to the logger are referred to as a category.

You can add a logger in this manner by calling fastlog:add_logger/1, which will give the logger a default configuration as follows:

  • Level: error
  • Handler: fastlog_logger (delegates to error_logger)
  • Pattern: "[%n] [%p] [%L] [%m] [%f] [line:%l] %s"

You may consult the Configuring Fastlog page for further details about configuration.

Loggers can also be configured when they are added, using the fastlog:add_logger/2 function. This version takes as its second argument, either the desired log level (as an atom) or a proplist of configuration values.

Removing Loggers

Loggers can be removed from the system at runtime, by calling fastlog:remove_logger/1 and passing the logger's identity (atom).

Checking Log Levels

There are three API calls for checking logging levels. The first, fastlog:get_level/0 returns the level of the default, top level logger. This logger is always active, and is invoked when you call a logging function without specifying a destination.

The function fastlog:get_level/1 takes a tag, and returns the level for the logger registered (i.e., added) against that exact tag, or the atom undefined if no such logger is active. If you wish to check the level for a category, rather than a specific logger, then you should call fastlog:check_level/1 instead, which has the desired result.

2> fastlog:add_logger('foo.bar.*', debug).
{ok,<0.50.0>} 
3> fastlog:get_level('foo.bar.*').        
debug
4> fastlog:get_level('foo.bar.baz').
undefined
5> fastlog:check_level('foo.bar.baz').
[{'foo.bar.*',debug}]

Changing Log Levels

Fastlog also supports changing log levels at runtime, making it easy to rpc on to a running node and provide additional logging data when necessary. The fastlog:set_level function comes in two versions, of arity 1 and 2 respectively. The arity-1 version takes a level and updates the top level logger (i.e., the logger with id = fastlog), and the other version takes the logger id as its first argument and the desired level as its second. This (latter) function will generate an exception if the logger id is not found.

Logging APIs

Fastlog supports two kinds of logging, and four logging levels. The two logging modes are synchronous and asynchronous, and these are determined by the client based on which function is called. The available logging levels are debug | info | warn | error, which are mutually exclusive. All of the logging functions require the desired logger (or category) to be specified, and this logger is always called (in the form of a gen_server call or cast message). The logger implementation will completely ignore the call, unless its active level is at least as high as that of the logging function called.

All the logging functions we're about to encounter come in three varieties, or arity one, two and three. Their meaning (and type signatures) are consistent throughout, and are organised thus:

-spec(<log-func>/1 :: (string() | #'fastlog.entry'{}) -> 'ok').

This logging function takes either a logging string (with no arguments) or a fastlog.entry record. In the former case, the string (which represents the log message) is passed to the top level logger verbatim; No additional formatting every takes place. When a record is passed however, this is passed to the logger specified in the dest field of the record.

-spec(<log-func>/2 :: (atom(), string() | #'fastlog.entry'{}) -> 'ok'; (string(), [term()]) -> 'ok').

As their type signature suggests, arity-2 logging functions will either pass Format-String + Args to the top level logger, or pass the supplied log record to a named logger (or category).

-spec(<log-func>/3 :: (atom(), string(), [term()]) -> 'ok').

The third variety of logging function is designed for calling a logger (or category) with a format string and list of arguments. These functions do not accept log records.

Logging at a specific level

Clients choose their log level by selecting a function in the fastlog module to call. The functions are named precisely for their level, so calls are made to fastlog:debug(...) and so on. There is no exported fastlog:log function, so the choice of level must be made at the call-site.

Synchronous Logging

As we have seen, each of the four supported logging levels is represented by three functions in the fastlog module, of arity one to three. For each of these, another function with the prefix sync_ is exported. The purpose of the sync_ variety of logging functions, is to call the logger synchronously and wait (i.e., block the calling process) until the logging request has been processed (or ignored, if the logger is inactive at the requested level). Blocking calls may offer performance benefits for some applications.

Logging Macros

Fastlog comes with some convenient macros, which will call each of the four arity-2 versions of the logging API functions. These macros are available once you import the fastlog header file. In order to control whether the macros call the synchronous or asynchronous versions, you may define a macro on a per-module basis.

-module(fastlog_example1).
-define(FASTLOG_SYNC, true).
-compile(export_all).

-include_lib("fastlog/include/fastlog.hrl").

demo() ->
    %% because FASTLOG_SYNC is defined, this will call fastlog:sync_debug/2
    ?DEBUG("Lagom är bäst ~s!~n", ["Henry"]). 

The available macros are capitalised versions of the four logging levels. In addition to these, the header defines LOG macro, which takes three arguments: destination, message (string) and args. This macro produces a 'fastlog.entry' record, which may be manipulated and passed to the various logging functions.