# log

### MODULE

log

### MODULE SUMMARY

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)

### AUTHORS

Martin Björklund - support@erlang.ericsson.se

eva 2.0.3
Copyright © 1991-2003 Ericsson Utvecklings AB