Home

Awesome

Log4Vala 0.2

Log4Vala is a logging framework for Vala (or other GLib/GObject projects), heavily inspired by the syntax and architecture of Log4J and similar projects. The purpose is to provide a powerful and customizable logging API for your application or library.

Installation

To install the project from the Git repository, you will need Vala 0.26 or higher, and the Meson build system. Check out the repository, enter the repository directory, and enter the following:

meson --prefix=/usr builddir
cd builddir
ninja
sudo ninja install

Basic Usage

Using Log4Vala requires an initial initialization and configuration, then each module should obtain and use a 'Logger' to log messages. Advanced config is explained below, but we'll start with the defaults -- log to the screen, use a simple format.

In your main() function, or the entry point to your library:

Log4Vala.init();

Then, inside each class or module, obtain a logger. You may want to provide it as a private field, but there's no need to pass the logger around to each method. The get_logger() call will always return the same object for a given logger name.

public class TestClass : Object {
	private Log4Vala.Logger logger = Log4Vala.Logger.get_logger("TestClass");
}

With that logger, you can now log entries. There are six predefined log levels: FATAL, ERROR, WARN, INFO, DEBUG, and TRACE. Your configured logging level has to at least match the priority of the logging message. By default, the log level is TRACE, so all log entries will be shown. Setting the default log level to WARN would not show any messages in INFO, DEBUG, or TRACE.

To log, call the method matching the log level in your logger instance.

public void a_method() {
	logger.info("I am in a method!");

	// You may also call "log" with a log level.
	logger.log( Log4Vala.Level.INFO, "I am in a method!" );

	// You may also capture an error and log it.
	try {
		method_that_will_throw();
	} catch (Error e) {
		logger.error( "Error in throwable method!", e );
	}

	// Or, you can use the formatter method.
	logger.errorf("Oh no, an error! Error: %s", e.message);
}

You may also use async methods if you're in a run loop or event loop -- just append _async to the end of your logging call.

public void a_method() {
	logger.info_async.begin("I am in a method!");

	// You may also call "log" with a log level.
	logger.log_async.begin( Log4Vala.Level.INFO, "I am in a method!" );
}

The Log4Vala in front of each call can be skipped with a using Log4Vala; at the beginning of your vala file.

When you're ready to compile, add --pkg log4vala-0.2 to your valac compile command.

Appenders and Layouts

Log4Vala, much like other Log4* frameworks, utilizes a pipeline of logger to layout to appender. A Layout determines how the log message will be formatted, and an Appender will determine how the message will be stored. A few layouts and appenders are included with Log4Vala, and you can also create your own.

Appenders

Layouts

WARN - This is a message!
2018-01-01 15:31:48 WARN  example.class.foo This is a message!
CharDescription
%%A percent sign
%cThe category or logger name
%dThe date. The date format character may be followed by a date format specifier enclosed between braces. For example, %d{%H:%M:%S,%l}. If no date format specifier is given, then the following format is used: "2018-06-18T09:56:21Z". The date format specifier admits the same syntax as the ANSI C function strftime, with 1 addition. The addition is the specifier %l for milliseconds, padded with zeros to make 3 digits.
%mThe message
%nA line feed
%pThe priority or log level
%RSeconds since Jan 1, 1970 or epoch
%EThe error. The error format character may be followed by additional formatting in braces, where %Ec is the error code, %Ed is the domain, and %Em is the message. If no specifier is given, then the following format is used: "%Ec, %Ed, %Em".
%tThe thread ID, if in a threaded environment
%PThe process ID

A pattern similar to the SimpleLayout would look like:

%d{%Y-%m-%d %H:%M:%S} %5p %c %m %E{ | Error: Code %Ec, Domain %Ed, Message: %Em}

Configuration

By default, Log4Vala will write the log to STDOUT using ScreenAppender, via the SimpleLayout format. To change the defaults, or alter logging based on the logger name, some configuration should be changed.

Configuration File

The default way in most Log4* frameworks is the configuration file. Log4Vala uses a similar format to those other implementations. The configuration file can set a default logger and level, set up new appenders and configure them, and attach layouts to appenders. Individual loggers can also be configured.

To use a config file, provide Log4Vala with the path to the file within the init statement, like so:

Log4Vala.init("/tmp/log4vala.conf");

Log4Vala will ignore empty lines, or lines that start with #, as they denote a comment. Whitespace at the beginning or end of the line will be ignored.

A logger is configured with an optional log level, and one or more appenders. They are comma-separated, and the appender must be defined with an appender directive somewhere in the file. To define a default logger, configure 'log4vala.logger'. Otherwise, to define a configuration down the name chain, append it after logger. So, if you had a class called 'ExampleLib.Control', you could configure logging using 'log4vala.logger.ExampleLib.Control'.

The order of loggers and appenders does not matter, but a logger or appender must be named before they can be configured.

This example will set the default logger to a file at "/tmp/example.log", using a format similar to [2018-01-01 15:01:38] WARN test.class : A message, but only at ERROR or above.

log4vala.logger=ERROR, LOGFILE
    
log4vala.appender.LOGFILE=Log4Vala.Appender.FileAppender
log4vala.appender.LOGFILE.filename=/tmp/example.log
log4vala.appender.LOGFILE.mode=append
log4vala.appender.LOGFILE.layout=Log4Vala.Layout.PatternLayout
log4vala.appender.LOGFILE.layout.pattern=%d{%Y-%m-%d %H:%M:%S} %5p %c : %m

Programmatically

Log4Vala can also be configured without the configuration file. Using the Config singleton and creating objects, the same configuration can be duplicated.

var config = Log4Vala.Config.get_config();
config.root_level = Log4Vala.Level.ERROR;
config.root_appender = new Log4Vala.Appender.FileAppender();
config.root_appender.filename = "/tmp/example.log";
config.root_appender.mode = "append";
config.root_appender.layout = new Log4Vala.Layout.PatternLayout();
config.root_appender.layout.pattern = "%d{%Y-%m-%d %H:%M:%S} %5p %c : %m";