最近更新: 2010-08-24

Vala - Time and Log

This article describes two things about Vala programming. First, how to get current time and output it as a formatted timesamp. Second, how to design custom log.

What Time Is It?

Vala provides two way to get time (it represents the number of seconds elapsed since 00:00:00 on January 1, 1970, UTC). They are TimeVal and time_t. time_t represents time by seconds. TimeVal represents more precise time, with seconds and microseconds.

time_t does not provide any methods to format as string. We should use Time to do this.

The following is an example to get current time and to output it as a formatted timestamp.

void main() {
    TimeVal nowv = TimeVal();
    nowv.get_current_time();
    stdout.printf("It is %s.\n", nowv.to_iso8601());

    // man ctime
    Time now1 = Time();
    now1 = Time.local( time_t() ); // get current time.
    stdout.printf("It is %s.\n", now1.to_string());

    // man strftime
    stdout.printf("It is %s.\n", now1.format("%F %H:%M:%S"));

    time_t t = nowv.tv_sec; // get time from TimeVal.
    now1 = Time.local( t );
    stdout.printf("It is %s.\n", now1.to_string());
}
rock@desktop:~$ valac what_time_is_it.vala
rock@desktop:~$ ./what_time_is_it
It is 2010-08-24T08:10:18.484744Z.
It is 2010-08-24 16:10:18.
It is 2010-08-24 16:10:18.
It is 2010-08-24 16:10:18.

Custom Your Log

When we design a background daemon, we usually need to log some informations to file. The simple way is just redirect stdout (or stderr) to our log file, then we could simply log our informations via printf or puts.

The following is a custom log example. It also adds a timestamp (see above) to log messages.

#if 0
namespace Log {
    void puts(string msg) {
        Time now = Time();
        now = Time.local(time_t()); 
        stderr.printf("[%s] %s\n", now.to_string(), msg);
        stderr.flush();
    }
}
#endif

public class Log {
    public static void puts(string msg) {
        Time now = Time();
        now = Time.local(time_t()); 
        stdout.printf("[%s] %s\n", now.to_string(), msg);
        stdout.flush();
    }
}

void main() {
    //redirect stdout to /tmp/test.log
    stdout = FileStream.open("/tmp/test.log", "ab");
    
    var s = "world";
    Log.puts(@"error message about $s.");
    
    var i = 10;
    var j = "jack";
    Log.puts(@"i is $i, j is $j.");
}
rock@rock-desktop:~$ ./time_log 
rock@rock-desktop:~$ cat /tmp/test.log 
[2010-08-24 16:26:01] error message about world.
[2010-08-24 16:26:01] i is 10, j is jack.

How about GLib.log

By default way, GLib.log(), GLib.message(), GLib.error(), GLib.warning(), and etc, will directly output message to /dev/stderr. We could not use FileStream to redirect those. You may invoke GLib.Log.set_default_handler() or GLib.Log.set_handler() to change handler.

void main() {
    var log_stream = FileStream.open("/tmp/test2.log", "ab");
    
    Log.set_default_handler(
        (domain, level, message) => {
            Time now = Time();
            now = Time.local(time_t()); 
            log_stream.printf("[%s] %s\n", now.to_string(), message);
        }
    );
    message("%s", "hello");
}

rock@rock-desktop:~$ ./time_log2 
rock@rock-desktop:~$ cat /tmp/test2.log 
[2010-08-24 16:48:27] time_log2.vala:11: hello

樂多舊網址: http://blog.roodo.com/rocksaying/archives/13543703.html