log(3)

MODULE
log - Client API for the log functionality in the EVA application

DESCRIPTION

This module contains client functions to the generic Log Control services in the EVA application. There are two services available; log monitoring and log transfer. The logs are controlled by a log server, and each log may be transfered with FTP to a remote host.

The log server has a list of all active logs in the system. An application that wants to make a log controllable with this functionality, must register the log in the log server. Each log is implemented as a disk_log log. The application stores its log records using the ordinary functions in disk_log. The following picture illustrates the idea:
 +------+     tell     +-------+
 | Appl |   -------->  | log   |
 +------+              | server|
    |                _ +-------+
    |open,          /
    |log*,         /control
    |close        /
    |    +---------+
    +--->| disk_log|
         +---------+

First, the application opens the log. Thenit registers the log in the log server, which makes the log server control the log. The application can store log records in the log, until it eventually closes the log, and tells the log server about it.

Each log has an administrative and an operational status, that both can be either up or down. The administrative status is configurable, and reflects the desired operational status. Normally they are both the same. If the administrative status is set to up, the operational status will be up as well. However, if the log for some reason does not work, for example if the disk partition is full, the operational status will be down. When the operational status is down, no records are stored in the log.

Alarms

Two EVA alarms are defined in the log service, log_file_error and log_wrap_too_often.

    *   log_file_error. This alarm is generated if there is a file error when an item should be logged. Default severity is critical. The cause for this alarm can be any Reason as returned from file:write in case of error (it returns {error, Reason}). The alarm is cleared if the file system starts working again.

    *   log_wrap_too_often. This alarm is generated when the log wraps more often than the wrap time. Default severity is major. The cause for this alarm is undefined. The alarm is cleared if the log wraps within the wrap time, the next time it wraps.

EXPORTS

close(Name) -> ok

    Types
        Name = string()

    Use this function to remove a log from the log server.

get_logs() -> [Log]

    Types
        Log = #log

    Returns all logs known to log_server. The record #log is defined in the file log.hrl.

open(Name,Type,WrapTime)

    Types
        Name = string()
        Type = term()
        WrapTime = integer()

    Makes log_server aware of the log Name. The log must be an open disk_log log.

    The type argument is there for information to a manager.

    If the log is a wrap log, log_server generates the log_wrap_too_often alarm if the log wraps more often than WrapTime seconds. In this context, wraps means that disk_log switches to a previously used file, and some log items are lost.

set_admin_status(Name, AdminStatus) -> OperStatus | {error, Reason}

    Types
        Name = string()
        AdminStatus = OperStatus = up | down
        Reason = {error, {no_such_log, Name}}

    Sets the desired state of the log. Returns the new operational status of the log. If the administrative status is set to up, and the operational status is down, there is some error with the logging mechanism, for example if the disk partition is full.

    If the operational status of the log is down, no log records will be stored in the log. This function uses the functions disk_log:block/unblock to change the operational status.

transfer(Host,User,Passwd,DestFile,SearchFunc) -> ok | {error, Reason}

    Types
        Host = ip_address()
        User = string()
        Passwd = string()
        DestFile = string()
        SearchFunc = {M, F, A}
        Reason = ftp_bad_address | ftp_login_error | ftp_write_error | ftp_tranfer_error | {bad_search_result, term()}
        ip_address() = string() | {int(), int(), int(), int()}
        M = F = atom()
        A = list()
        M:F(Continuation | A) -> SearchResult
        SearchResult = eof | {NewContinuation, Bytes} | {error, R}
        Continuation = start | cont()
        NewContinuation = cont()
        Bytes = binary()
        R = term()

    This function is used to transfer a log with FTP to a remote host, for example a mangement station. It could be triggered from for example SNMP or from a web interface to the system. This log is received as one contiguous file, although it is stored as several files in the underlying disk_log log. It is possible to filter the log for certain log records, and to format the log records. Thus, log records can be efficiently stored by not formatting them when they are written, but later when the log is actually needed. Of course, to further improve performance, the log records can be transferred unformatted as well, and later formatted off-line at the management station.

    The Host argument is either a string or a four-tuple representing the IP address of the host. The string can be the name of the host, or the IP address in dotted decimal notation, for example "150.236.14.136".

    The SearchFunc argument specifies a function that will be called by the transfer session to get a chunk of log records to transfer. At the first call, the atom start is used as an initial continuation. Each time the function is called, it is supposed to return a new continuation and a binary that contains the bytes to be transferred (the formatted log records). When the end of the log is reached, eof is returned by the function. The return values of the SearchFunc is chosen to match those of disk_log:chunk/2. The extra arguments (A) to the functions can be used to pass filtering information to the search function. An example of a search function:
    -module(my_log).
    f(Cont, Time) ->
        case disk_log:chunk("my_log", Cont) of
            eof ->
                eof;
            {error, R} ->
                {error, R};
            {NCont, ListOfTerms} ->
                List = lists:map(fun(Term) ->
                                    format(Term, Time)
                                 end, ListOfTerms),
                Bin = list_to_binary(List),
                {NCont, Bin}
        end.
    %% Each log record is a tuple: {LogTime, LogData}
    format({LogTime, LogData}, Time) when LogTime > Time ->
        io_lib:format("time: ~p data: ~p~n", [LogTime, LogData]);
    format(_LogRecord, _Time) ->
        [].

    This function can be used as follows to transfer all log records stored after 1997-11-01:
    log:transfer("cave.ericsson.se", "mbj", "secret!", "my_log.txt",
                 {my_log, f, [{1997,11,01}]}

See Also

disk_log(3), eva(3), file(3)

AUTHOR
Martin Bjorklund - support@erlang.ericsson.se