Linux Event Logging For Enterprise-Class Systems

Version 1.41  (not yet fully updated for evlog-1.5.0 release)

 December 6, 2002

 

NOTE:  For a listing of features that are not yet available, along with a list of planned enhancements to existing features, click here.

 

Team Members:

Larry Kessler  (lkessler@users.sourceforge.net)

James Keniston  (kenistoj@users.sourceforge.net)

Hien Nguyen (nguyhien@users.sourceforge.net)

   

1     Abstract. 3

2         Introduction.. 3

3         Goals.. 4

4         Compliance with proposed POSIX Standard 1003.25.. 5

5         Linux Event Logging Overview... 6

6         Linux Event Logging Detailed Description.. 7

6.1        Event Record Contents. 7

6.1.1        Fixed portion of Event Record. 7

6.1.2        Variable-length portion of Event Record. 8

6.1.2.1       POSIX_LOG_STRING.. 8

6.1.2.2       POSIX_LOG_BINARY. 8

6.1.2.2.1        Formatting Templates. 8

6.1.2.2.1.1        General Format of a Template. 8

6.1.2.2.1.1.1    Cpp Directives. 9

6.1.2.2.1.2        Imports and Typedefs. 9

6.1.2.2.1.2.1    Typedef Statements. 9

6.1.2.2.1.2.2     Import Statements. 9

6.1.2.2.1.3        Header Section. 10

6.1.2.2.1.3.1           Header of Record Template. 10

6.1.2.2.1.3.2           Header of Struct Template. 10

6.1.2.2.1.4        Attribute Sections. 10

6.1.2.2.1.4.1           Attribute Name. 11

6.1.2.2.1.4.2           Attribute Type. 11

6.1.2.2.1.4.3           Attribute Dimension or Bit-Field Width. 11

6.1.2.2.1.4.4           Const Attribute’s Value. 12

6.1.2.2.1.4.5           Attribute Format 12

6.1.2.2.1.4.6     More about Typedefs. 15

6.1.2.2.1.4.7    Alignment of Attributes in a Record or Struct 15

6.1.2.2.1.5        Template Formatting Specification. 16

6.1.2.2.1.5.1    Free Form.. 16

6.1.2.2.1.5.2    format string. 16

6.1.2.2.1.5.3    format wstring. 16

6.1.2.2.1.6        Sample Templates. 16

6.1.2.2.1.7        More on Importing Templates. 18

6.1.2.2.2         Using formatting templates with POSIX_LOG_STRING and POSIX_LOG_NODATA   18

6.1.2.2.3        Advantages and Disadvantages. 19

6.2      Event Logging and Retrieval 19

6.2.1        Facility Registry. 19

6.2.1.1       Restricted Logging. 21

6.2.2        evlogd Daemon  and Event Buffering. 21

6.2.2.1       Screening of Events. 22

6.2.2.2       Discarding duplicate events. 23

6.2.3        API Functions. 24

6.2.3.1       Writing Event Records. 24

6.2.3.1.1        Writing Events from User Space. 24

6.2.3.1.2        Writing Events from Kernel Space. 26

6.2.3.2       Formatting Event Records. 29

6.2.3.3       Formatting Templates. 32

6.2.3.3.1        The Template Repository. 32

6.2.3.3.2   Notes on template Use in Multithreaded Applications. 33

6.2.3.3.3        Compiling Templates. 33

6.2.3.3.4        Template Application. 34

6.2.3.4         Registering Facilities. 41

6.2.3.4.1        Registering Facilities from User space. 41

6.2.3.4.2        Registering Facilities from Kernel space. 42

6.2.4        User Commands. 43

6.2.4.1        evlconfig - Configure logging daemon. 43

6.2.4.2       evlfacility - Manage Facility Registry. 45

6.2.4.3        evlsend -  Event generation command. 48

6.2.4.4         evlview - View log events. 49

6.2.4.5       evltc - Compile formatting templates. 54

6.3        Filtering of Event Records. 57

6.4          Event Notification. 58

6.4.1        Overview.. 58

6.4.2        Detailed Design. 59

6.4.2.1       evlnotifyd  Server Design. 59

6.4.2.1.1        Processing a New Notification Request 60

6.4.2.2        Client Design. 61

6.4.2.2.1        posix_log_notify_add() 61

6.4.2.3       Client-Server Conversations. 61

6.4.2.3.1        Types of Messages. 61

6.4.2.3.2        Creating a Notification Request 61

6.4.2.3.3        Getting the Status of a Notification Request 61

6.4.2.3.4        Removing a Notification Request 62

6.4.2.4       evlactiond Client 62

6.4.2.4.1        Registering for event notification. 62

6.4.2.4.2        Processing an event notification. 62

6.4.2.5       Threads-Based Notification. 63

6.4.3        API Functions. 63

6.4.4        User Commands. 63

6.4.4.1       evlnotify - Event Notification. 63

6.5      Log Management 66

6.5.1      User Commands. 68

6.5.1.1       evlogmgr - Event Log Manager. 68

6.6      Query and Filter Expression Syntax Rules. 71

6.6.1 Extensions to the POSIX Standard. 74

6.7      Modifications to the Linux Kernel 74

6.7.1      Enhanced printk. 74

6.8      Modifications to syslog. 75

7         Appendices.. 76

7.1      Appendix A  POSIX 1003.25 **DRAFT**. 76

7.2      Appendix B Overview of Syslog 1.3 (for Linux) 76

Syslogd Options. 76

Remote Logging of syslog messages. 76

syslog.conf 77

severity codes. 77

Additional syslog options. 78

klogd. 78

logger command. 79

Log File Management / logrotate command. 79

Associated Files. 80

7.3      Appendix C Issues and New Requirements. 81

7.4      Appendix D siginfo.h header file. 81

7.5      Appendix E   Date and Time Formats. 84

7.6      Appendix F   Facility Names and Facility Code creation. 85

8         Revision History.. 86

 

 

 

 

1     Abstract

This document describes an Enterprise-class Event Logging facility for Linux.   Refer to Appendix C Issues and New Requirements for items that are not currently addressed in the body of this document.

2         Introduction

For the purpose of problem tracking and problem determination, events and informational messages from kernel subsystems and system applications are logged for later analysis.

In Linux, the most commonly used logging facilities are printk/klog (for logging kernel events) and syslog (for logging non-kernel events), which is referred to collectively as sysklogd.   See Appendix B Overview of Syslog 1.3 (for Linux).  Although quite suitable for single-processor desktop or small server applications, for multi-processor medium-to-large servers, commonly found in medium-to-large enterprises, sysklog has several shortcomings, which include:

              Events are recorded as text only, and some pertinent information (for example, facility and severity) is not recorded.  Also, events can be recorded in multiple destinations, which makes effective post-processing of messages/events difficult.

              Limited user interface is available to extract, filter, and view only events of interest. 

              A limited set of event providers (facilities) are supported, with only 8 available for the implementation to define (LOCAL0-7).

              Limited Event "notification" capabilities.

              Limited ability to manage and limit syslog generated log file sizes and the age of the events (logrotate, a separate RPM, does provide archiving capability based on age or size of the entire log file, but it does not allow selective removal of events from the log files based on user or application specified criteria). 

 

 

3         Goals

Given sysklogd's limitations, and the need to provide additional capabilities for large, multi-processor, Enterprise-class systems, the goals are:

 

 


4         Compliance with proposed POSIX Standard 1003.25

 

Linux Event Logging conforms to proposed POSIX Standard 1003.25, System API - Services for Reliable, Available, and Serviceable Systems (SRASS).  As of March 2002, this standard has not been adopted, and the descriptions provided within are subject to change, accordingly. 

Appendix A  POSIX 1003.25 **DRAFT** contains a link to the most recent draft of this standard.   The information in Appendix A will not be repeated in the body of this document, except when additional explanation is needed.  It is recommended that you read and become familiar with the draft POSIX standard before reading the remainder of this document.  Through active participation in the IEEE Working Group, the authors of this document will keep this document consistent with latest draft of the POSIX Standard.

In summary, the requirements and functionality specified in the latest draft of the standard:

1.        A single system-wide log that is always available to accept event records.

2.        All event records consist of a fixed structure representing attributes of the event record and a variable-length data buffer containing the event data (text or binary).

3.        API functions exist for applications to:

·         write to the log

·         open the log (required for reading, but not required for writing to the log)

·         seek to record(s) that match the selection criteria. 

·         Register for event notification, where a real-time signal is generated and a sigval object is passed, when an event record is written to the log which contains values that match the specified selection criteria. 

 

It should be noted that there is a deviation from the "single system-wide log" requirement specified by the POSIX standard, which is provided in order to more closely match the current behavior of sysklogd with respect to logging AUTHPRIV messages into a separate "private" log file with restricted read access.  See Facility Registry for a detailed explanation.

5         Linux Event Logging Overview

 

There are two primary interfaces to Event Logging as defined by the direction of information flow. They are the Provider Interface and the Consumer Interface.   A secondary interface is provided for Log Management.

The following diagram illustrates the flow of information.


http://evlog.sourceforge.net/evl1.gif

 

The Provider Interface is used by software to report events.  Providers may include commands executed from the command line or shell script.  With every event, a base set of information must be provided to make the event data useful for analysis and acceptable for logging.

The Event Logging system collects additional information, such as time of the event, combines it with the provider-supplied data, and creates an event log entry.  The Event Logging System also:

·         Optionally takes printk() and syslog()/vsyslog() messages, and logs them as POSIX-compliant event records.

·         Optionally, and based upon specified thresholds, suppresses logging of duplicate events being logged in rapid succession, to minimize system performance degradation.

·         Optionally, and based upon specified criteria, screens events that are written to the log.  For example, messages for debugging purposes may not be of interest to a System Administrator. 

·         Filters events that are read from the log, based on specified criteria.

·         Notifies registered Consumers, when events match Consumer-specified criteria.

·         Provides a method for configuring the event buffer size

 

The Consumer Interface:

 

·         Retrieves selected event data (based on Consumer specified selection criteria) from the log.

 

 

·         Registers for notification (based on Consumer specified criteria) when events matching the criteria are written to the log.  

 

The Consumer-interface users typically include system end users (mostly system administrators and operators) and service/support groups.

 

Log Management:

·         Provides methods for:

o        Managing the size of the event log.

o        Specifying criteria for automatically removing events from the log that are no longer of interest, truncating the log, and reclaiming the space.

 


6         Linux Event Logging Detailed Description

6.1        Event Record Contents

An Event Record consists of a fixed-length, predefined structure, and a variable-length portion, up to POSIX_LOG_ENTRY_MAXLEN long, which contains event data attributes that are passed by the provider of the event record. 

6.1.1        Fixed portion of Event Record

See Appendix A for contents of the fixed-portion of the event record.   Additional content has been defined as follows:

·         The following log_event_types  are reserved:

EVL_PRINTK_MESSAGE  (0x2) - indicates that event was originally written with the printk() function.  All messages written with printk() will have this event type unless the event logging feature that includes caller location information (source file, function, line number)  is enabled, in which case the event type will be a checksum derived from source file name, function name, and printk format string.  The log_facility will always be LOG_KERN for this event type.

EVL_SYSLOG_MESSAGE  (0x1) - indicates that event was originally written with the syslog() or vsyslog() function.    The log_facility will be passed by the caller of syslog().

EVL_BUFFER_OVERRUN (0x6) - indicates that one or more event records have been discarded due to an overrun of the kernel event buffer, or temporary event buffer allocated by the evlogd daemon.  The log_facility will always be LOG_LOGMGMT for this event type.  See Event Buffer and evlogd Daemon for more information.

EVL_DUPS_DISCARDED (0x7) - indicates that one or more duplicate event records have been discarded.  The log_facility will always be LOG_LOGMGMT for this event type.  See Discarding duplicate events for more information.

EVLOG_REGISTER_FAC (40) - indicates that the event is a special event generated when evl_register_facility() is called in the kernel.  See Registering Facilities from Kernel space for details.

·         The following log_flags bits have been reserved for use by event logging:

                POSIX_LOG_TRUNCATE (0x1) - Defined in the POSIX standard.

EVL_KERNEL_EVENT (0x2) - Indicates that event was logged from within the kernel.   If caller of log write functions in user-space (evl_log_write, posix_log_write, etc.) sets this flag to 1, ECANCELED is returned and the event is not logged.  This is intended to prevent an application or user from erroneously indicating that the event was logged in the kernel, when in fact it was logged in user-space.

EVL_INITIAL_BOOT_EVENT (0x4) - This bit indicates that the event was logged before a valid  time value was available in the kernel.  When this bit is set the evlogd daemon will overwrite the log_time field in the event record with the system startup time (determined by subtracting uptime from current time), and thus provides a reasonable approximation for log_time.

EVL_KERNTIME_LOCAL (0x8) - This bit indicates that the log_time value in the event record (created in the kernel) is set to local time, and needs to be adjusted to GMT by the evlogd daemon.  evlogd will reset this bit after the time is adjusted.

EVL_INTERRUPT (0x10) - This bit indicates that the event was logged from interrupt context. 

EVL_PRINTK_MESSAGE  (0x20) - indicates that event was originally written with the printk() function.  

Reserved for future event logging use:  0x40, 0x80.

 

6.1.2        Variable-length portion of Event Record

The 2  variable-length data formats defined in the POSIX standard are supported, as indicated by the log_format value:

·         POSIX_LOG_STRING - A NULL-terminated string.

·         POSIX_LOG_BINARY - Binary data, requiring additional information to interpret and format.

POSIX_LOG_NODATA is also a valid log_format, and indicates that there is no variable-length data associated with the event.  

 

6.1.2.1       POSIX_LOG_STRING

The POSIX standard requires that compliant implementations support variable-length event data consisting of a NULL-terminated character string.

 

6.1.2.2       POSIX_LOG_BINARY

Binary data can be described as a contiguous string of bytes representing one or more attributes in the optional portion of an event record.  The information needed for parsing and formatting the optional attributes contained within this binary data is provided by formatting templates.

 

6.1.2.2.1        Formatting Templates

NOTE:  Although formatting templates are primarily intended for use with log_format of POSIX_LOG_BINARY, they can also be used with other log_formats.  See 6.1.2.2.2         Using formatting templates with POSIX_LOG_STRING and POSIX_LOG_NODATA for details.

There are 5 sections in a template:

 

  1. Imports and Typedefs
  2. Header
  3. Const attributes (optional)
  4. Record attributes
  5. Template formatting specification

 

These sections are described in detail below.

6.1.2.2.1.1        General Format of a Template

The imports/typedefs, header, and attribute sections of a template are made up of statements.  In general, statement syntax follows the conventions of the C language.  In particular, the following language elements follow C syntax:

·         comments

·         identifiers

·         string and wide-string literals, including automatic concatenation of adjacent string literals or adjacent wide-string literals

·         integer, char, wide-char, and floating-point constants

·         white space

In the header and attribute sections, statements are terminated with semicolons (;).  A single line can contain multiple statements, and a single statement can span multiple lines.

The final section of the template, the template formatting specification, may be in the form of a statement, or it may be free-form text.  Its format is defined later in this discussion.

The special statement END (upper case, no semicolon, no white space, no comments, on a line by itself) is used to separate multiple templates in the same source file.  The final template in a file need not contain an END statement.

6.1.2.2.1.1.1    Cpp Directives

The evltc template compiler has the option of passing your template source code through the C preprocessor, cpp, before compiling it.  Therefore, your template source code can include C-preprocessor directives such as #include, #define, and #ifdef, with appropriate results.

6.1.2.2.1.2        Imports and Typedefs

The imports/typedefs section contains zero or more import statements and zero or more typedef statements.  Within this section, import and typedef statements can appear intermixed in any order.  The imports and typedefs remain in effect through the end of the template source file.

6.1.2.2.1.2.1    Typedef Statements

A typedef statement in a template is analogous to a typedef statement in the C language.  Each typedef statement has the form

        typedef type_spec  name  dimension_spec  format_spec ;

where type_spec, name, dimension_spec, and format_spec are defined as for attribute statements.  (See “Attribute Sections” later in this discussion.)  The specified name can be used as a type_spec in subsequent attribute statements.  Each such attribute assumes the typedef’s type, its dimension (if any), and possibly its format (if any).  For a further explanation of typedefs, see the “More on Typedefs” section under “Attribute Sections.”

6.1.2.2.1.2.2     Import Statements

Each import statement has the form

      import struct_path ;

 

A struct_path is a sequence of one or more identifiers delimited by periods.  This sequence identifies a struct template (see next section) that is referenced later in this template file.  For example, the statement

      import gui.graphics.point;

would typically import the struct template from the file /var/evlog/templates/gui/graphics/point.to.  The importing template can then declare attributes of type “struct point” or “struct gui.graphics.point”.

 

The final component of a struct_path can be an asterisk (*), specifying that all struct templates from the indicated directory should be imported.  For example, the statement

      import gui.graphics.*;

would typically import the templates from all the .to files in the /var/evlog/templates/gui/graphics directory.

 

Importing a struct template brings a binary representation of that template into memory, much as if that template had been previously defined in the current template source file.  Importing of templates is further discussed in the section “More on Importing Templates,” later in this discussion of formatting templates.

6.1.2.2.1.3        Header Section

There are two types of templates that are used to describe event records:

 

Record and struct templates differ primarily in the content of their header sections.

 

6.1.2.2.1.3.1           Header of Record Template

The header of a record template contains 3 statements that must be specified in the following order.  (The description statement is optional.)

facility facility_id ;

event_type event_id ;

description description ;

 

 

The facility_id identifies the facility to which this template applies; it corresponds to the log_facility member in the fixed portion of an event record.  The facility_id is either an integer constant or a string literal from the facility registry (see Facility Registry) -- e.g.,

 

facility 128;

facility "MAIL";

facility "Bob’s Volume Manager";

 

The event_id is an integer constant that corresponds to an event record's log_event_type member.  Together, the facility and event-type match the template to a particular type of event record.

 

An event_type statement may also be of the form

      event_type default;

This indicates that this template will be used by default for any event type, in the indicated facility, that does not have its own template.

 

The description is a string literal that contains a human-readable title for the template. 

6.1.2.2.1.3.2           Header of Struct Template

The header of a struct template contains a struct statement and an optional description statement, in that order.  The description statement is as described above.  The format of a struct statement is

[const] struct struct_name ;

where struct_name is an identifier that uniquely identifies this struct.

 

A struct template that is declared const must have a const-attributes section and no record-attributes section.  Such a template is used solely to define const values that may be referenced in other templates.  A non-const struct template must have at least a record-attributes section.

6.1.2.2.1.4        Attribute Sections

A template may have a record-attributes section and/or a const-attributes section.  The const-attributes section defines attributes with fixed values that are provided by the template, and are not included in the event record.  The record-attributes section defines attributes in the order that they appear in the optional part of the event record.

Each section consists of three parts:

1.        the start-attributes clause.  For the const-attributes section, this is “const {“.  For the record-attributes section, this is “[aligned] attributes {“.  The optional “aligned” keyword specifies that the attributes are aligned as if they were members of a C struct (and therefore may contain padding after some values).  The “aligned” option is discussed further under “Alignment of Attributes in a Record or Struct.”

2.        one or more attribute statements, each of which resembles a C-language data declaration

3.        the end-attributes clause: “}

In the record-attributes section, an attribute statement specifies the name, type, and formatting specification of an attribute, and (if it is an array or bit-field) its dimension.  The format of the statement is

 type_spec  name  dimension_spec  format_spec ;

 

In the const-attributes section, each attribute statement also specifies a value for the attribute (unless the attribute is a const struct, which carries its own predefined values):

 type_spec  name dimension_spec = value_spec  format_spec ;

 

The record-attributes section cannot include attributes that are const structs.

6.1.2.2.1.4.1           Attribute Name

The attribute’s name is a valid C-language identifier that distinguishes this attribute from other attributes defined in this template. (However, this name may be the same as the name of one or more attributes defined in struct templates referenced by this template.)  The following attribute names are reserved, as explained in POSIX 1003.25: recid, size, format, event_type, facility, severity, uid, gid, pid, pgrp, time, flags, thread, processor, data.  The following words are also reserved: aligned, attributes, const, default, description, import, signed, struct, typedef, unsigned, and all the type names listed in the “Table of Optional Attribute Data Types and Format Specifiers” later in this section.

 

6.1.2.2.1.4.2           Attribute Type

The attribute’s type_spec can take one of the following forms:

·         one of the type names listed in the table later in this section (e.g., “ushort”, “ldouble”);

·         the C-language equivalent of one of those type names (e.g., “unsigned short”, “long double”);

·         the name of a previously defined typedef (see “More about Typedefs” later in this section); or

·         the construct “struct struct_name” where struct_name is the name of a struct template that was previously defined or imported in the current template source file.  If the specified struct template was not previously defined or imported in the current file, but a file named struct_name.to exists in the same directory as the current file, that struct template will be imported automatically.

6.1.2.2.1.4.3           Attribute Dimension or Bit-Field Width

The attribute’s dimension_spec is omitted if the attribute is not an array or bit-field.  If the attribute is an array, the dimension_spec is one of the following constructs, enclosed in square brackets [ ]:

 

A const attribute cannot have a dimension of [_R_] or [*].

Multi-dimensional attributes per se are not supported.  However, you could obtain the effect of a two-dimensional array as follows: A struct may contain an array as its only attribute, and another template may declare an array of such structs.

Bit-Fields.  If the attribute is a bit-field, the dimension_spec has the format

: width

where width is the attribute’s size in bits, an integer constant.  Bit-field attributes have the same semantics as C-language bit-fields, with the following exception:

·         The width must be a decimal, hexadecimal, or octal integer constant.

Bit-field storage and alignment conventions match those of gcc on the system that wrote the event log.  The size of a bit-field cannot exceed the size of a long long.  Unnamed bit-fields are permitted.  In particular, the “int :0” construct (which in C means, “skip to the beginning of the next storage unit”) is supported.

A const attribute cannot be a bit-field.

6.1.2.2.1.4.4           Const Attribute’s Value

A const attribute’s value_spec is a constant (string literal, or integer, floating-point, or character constant) that specifies the attribute’s value.  For aggregate attributes (records and arrays), C-style aggregate initializers are used – for example:

const {

      struct point origin = {0,0};

      int daysPerMonth[12] = {31, 28, 31, 30, 31, 30,

31, 31, 30, 31, 30, 31} “(%d )”;

      struct xpg4Msg probableCauses[] = {

            {2, 1, “Operator fell asleep”},

            {2, 2, “Backhoe”}

      } “(Probable cause[%I] = %Z\n)”;

}

 

Formatting of arrays and structs is discussed in the next subsection.

Due to automatic concatenation of string literals, the following attribute statement, though legal, will probably not produce the intended effect:

string helpMsg = “Help!” “%-20s”;

 

To resolve this problem, even a scalar attribute’s value_spec can be enclosed in curly braces – e.g.,

string helpMsg = { “Help!” } “%-20s”;

6.1.2.2.1.4.5           Attribute Format

The attribute’s format_spec is a string literal that specifies how the attribute is to be formatted.

 

If the attribute is a scalar (simple) attribute – not an array or struct – the format_spec must be a valid printf format specification for a single value of that type, beginning with a “%” and ending with one of the format specifiers from the table below.  The standard printf flags (‘-‘, ‘+’, space, ‘#’, and ‘0’) and field-width and precision specifiers are also permitted.

 

If the format_spec is omitted, the format specifier defaults to the one shown for that data type in the table.  For example, the default format_spec for ints, shorts, and chars is “%d”.

 

The special format specifiers %t, %b, and %v are also supported, as described later in this section.

Table of Optional Attribute Data Types and Format Specifiers used with formatting templates.

Type Names

Applicable printf Format Specifiers

Default Specifier

short

d, i, o, x, X, u without flag h or l

d

ushort

d , i, o, x, X, u without flag h or l

u

int

d , i, o, x, X, u without flag h or l

d

uint

d , i, o, x, X, u without flag h or l

u

long

d , i, o, x, X, u with flag l

ld

ulong

d , i, o, x, X, u with flag l

lu

longlong

d , i, o, x, X, u with flag L

lld

ulonglong

d , i, o, x, X, u with flag L

llu

address

d, i, o, x, X, u with flag l, p

p

float

f, e, E, g, G

f

double

f, e, E, g, G

f

ldouble

flag L with f, e, E, g, G

Lf

schar

c, C, d , i, o, x, X, u without flag h or l

d

uchar

c, C, u , i, o, x, X, u without flag h or l

u

char

Same as either schar (signed char) or uchar,

depending on whether char is signed or unsigned

on the system where evltc was built.

d or u

string

s

s

wchar

C, flag l with c

lc

wstring

S, flag l with s

ls

 

Dump Format.  The format_spec can be %t for any attribute.  %t indicates that the data should be displayed in dump format: hexadecimal, with the ASCII equivalent also displayed.  For example, given an attribute definition of “uchar x[32]”, a formatting specifier of %t might produce the following:

 

00000000 61 62 63 64 65 66 67 68  61 62 63 64 65 66 67 68 | abcdefgh abcdefgh

00000010 3F 3F 3F 3F 4A 3F 3F 3F  3F 3F 3F 3F 4A 3F 3F 3F | ????J??? ????J???

 

Bitmaps.  For integer types, the %b format specifier can be used.  %b specifies that the attribute should be formatted as a bitmap.  A %b specifier has the following format:

 

"%b/bit_pattern1/string1/bit_pattern2/string2/.../bit_patternN/stringN/"

 

Each bit pattern is either a hexadecimal number beginning with 0x or 0X or x or X, or a binary pattern beginning with 0b or 0B or b or B.  For every bit pattern that matches the attribute’s value, the corresponding string is included in the formatted representation of the value.

 

In the examples shown in this section, the strings and bit patterns are delimited by slashes (/), but any punctuation character may be used as a delimiter.  In a %b or %v format specifier, the delimiter is the character immediately following the %b or %v.   The delimiter character cannot appear in any of the strings.

 

A hexadecimal bit pattern matches the attribute’s value if all the 1s in the hex value are also 1s in the attribute’s value – i.e., (attribute_value & hex_pattern) == hex_pattern.  For example, when the format specifier

"%b/0x1/HUMAN/0x2/ADULT/0x4/FEMALE/"

is applied to the value 5, the result is

0x5(HUMAN|FEMALE)

If it is applied to the value 8, the result is

0x8

 

A binary pattern is a sequence of 0s, 1s, and Xs (upper or lower case), each representing a bit.  All X bits, and all bits not explicitly specified, are treated as don’t-care bits.  0 and 1 bits must match the attribute’s value.  For example, the previous sample specification could be expressed as

"%b/0b1/HUMAN/0b1x/ADULT/0b1xx/FEMALE/"

To give non-humans, juveniles, and males (the “zero” bits) explicit recognition, we could expand the specification to

"%b/0b1/HUMAN/0b1x/ADULT/0b1xx/FEMALE/"

"0b0/INHUMAN/0b0x/JUVENILE/0b0xx/MALE/"

(Note that the two adjacent strings are automatically concatenated.)  Applied to the value 5, this specifier would produce

0x5(HUMAN|FEMALE|JUVENILE)

 

Once a pattern is matched, any subsequent patterns associated with those bits are ignored.  For example, If the specification

"%b/0x7/WOMAN/0x1/HUMAN/0x2/ADULT/0x4/FEMALE/"

is applied to the value 7, the result is

0x7(WOMAN)

not

0x7(WOMAN|HUMAN|ADULT|FEMALE)

 

Named Values.  Like %b, the %v format specifier is restricted to integer types, and specifies a set of value/string pairs.  When a value in the %v list exactly matches the attribute’s value, the corresponding string is substituted.  If there is no match, the attribute’s value in decimal is substituted.  For example, when the format specifier

"%v/1/Sun/2/Mon/3/Tue/4/Wed/5/Thu/6/Fri/7/Sat/"

is applied to the value 6, the result is “Fri”.  When it is applied to the value 8, the result is “8”.

 

Struct Attributes.  If the attribute is a struct, the format_spec must be omitted, since the format is specified in the struct’s template.  The special %Z specifier is used when formatting arrays of structs, as described under “Array Attributes.”

 

Array Attributes.  If the attribute is an array, the format_spec (if any) may be followed by the construct

      delimiter=string

where string is a string literal.  This delimiter string is inserted between the elements of the formatted array.  The default delimiter is a single space.

 

If the format_spec is omitted, the array's elements will be formatted using the default format for that type (or %Z, for an array of structs).

 

If specified, the format_spec must be one of the following constructs:

int   widgets[5] "%#x";

might yield the following formatted output:

0x5 0xa 0xc 0x43 0x3

 

Within the format_spec, %I and %Z have special interpretations.  %I is replaced by the index (in decimal) of the current array element.  For example, the attribute statement

int   widgets[5] "w[%I]=%2d" delimiter="\n";

might yield the following formatted output:

w[0]= 5

w[1]=10

w[2]=12

w[3]=67

w[4]= 3

 

%Z is used with arrays of structs, and stands for a single element of the array, formatted according to the struct’s template.  For example, the attribute statement

struct point endPoints[2] "endPoint[%I] = %Z" delimiter="\n";

                might yield the following output:

endPoint[0] = (10,15)

endPoint[1] = (-25,15)

 

int   widgets[5] "(%d, )";

might yield the following formatted output:

5, 10, 12, 67, 3,

 

6.1.2.2.1.4.6     More about Typedefs

The semantics of the components of a typedef statement are largely the same as those of an attribute statement.  A typespec defines a type, and may also define a dimension and/or format.  When a typedef’s name is given as an attribute’s type_spec, the attribute is defined as follows:

·         The typedef’s type is assigned to the attribute.

·         If the typedef defines a dimension, that will be assigned to the attribute; otherwise, the attribute’s dimension (if specified) will be used.  It is illegal for both the typedef and the attribute to explicitly specify dimensions.

·         If the attribute statement does not explicitly specify a format, the typedef’s format (if any) will be assigned to the attribute.

A typedef is not associated with any particular template.  Therefore, its dimension cannot be an attribute name.  However, it can be [_R_].

A typedef with a dimension of [ ] -- for example,

      typedef int int_array_t[] “(%d )”;

-- is legal.  However, only const attributes can be of this type (since the size of the array is determined from the initializer list).

A typedef cannot define a bit-field.  A typedef cannot be initialized with a value.

A typedef name cannot be a reserved word.  However, the same (legal) name can be used independently for a typedef, struct, and/or attribute.

The form

      typedef struct s { ... } s_t;

is allowed in C but not in a template.  The equivalent code for a template is:

      struct s; [aligned] attributes { ... } format string “...”

      END

      typedef struct s s_t;

6.1.2.2.1.4.7    Alignment of Attributes in a Record or Struct

The “aligned” keyword in a record-attributes clause specifies that, in the event record, the attributes’ values will be aligned as if they were members of a C struct.  As a result, the record is expected to contain padding between values (and possibly after the last value) to achieve alignment.

 

For example, a struct defined as follows --

                attributes { char c; int i; }

-- is expected to occupy 5 bytes on a 32-bit system: 1 for c and 4 for i.  The record might be written as follows:

      evl_log_write(facility, event_type, severity, flags,

            "char", c, "int", i);

 

By contrast, a struct defined as follows --

                aligned attributes { char c; int i; }

-- is expected to occupy 8 bytes on a 32-bit system: 1 for c, 3 for alignment, and 4 for i.  The record might be written as follows:

                struct s { char c; int i; } svar;

...

posix_log_write(facility, event_type, severity, &svar,

sizeof(svar), POSIX_LOG_BINARY, flags);

 

In a record or struct with aligned attributes, no attribute can have a size that is unknown at compile time.  Such attributes include strings, wstrings, variable-dimension arrays, and unaligned structs.

6.1.2.2.1.5        Template Formatting Specification

 

The last section of the template defines how the record’s formatted attributes are to be presented.  This section must appear immediately after the final attribute section.  This section can take three forms:

·         free form

·         format string string_literal

·         format wstring wide_string_literal

6.1.2.2.1.5.1    Free Form

A free-form formatting specification begins with the keyword “format” on a line by itself.    Everything that follows the format statement, until the end of the template, is interpreted as the format string.

The formatted representation of a template is a copy of this format string, with the appropriate formatted attribute value substituted wherever an %attribute_name% construct appears.   attribute_name can be a simple name (e.g., “employee”) or a reference to a struct member (e.g., “employee.addr.city”).

 

The %attribute_name% construct may include an embedded formatting specification -- e.g. "%lun:x% -- that overrides the format that would otherwise be used.  Any newline (line break) in the format string also appears in the formatted output, unless it is immediately preceded by a \.  Newlines, tabs, and other special characters can also be encoded using standard C escapes (\n, \t, etc.).

 

For an event-record template, a newline is automatically appended to the formatted representation, so that the formatted output of an event-record template always takes up at least one complete line.  For a struct template, any terminating newline must be explicitly specified – as a trailing blank line, as a \n escape, or as the last character of a formatted array attribute.

The C preprocessor does not always preserve white space intact.  So if you are going to run your template source file through the C preprocessor, you may want to use the “format string” or “format wstring” form instead.

6.1.2.2.1.5.2    format string

This form consists of the words “format string”, followed by one or more string literals, which are automatically concatenated into the format string.  The words “format” and “string” must be separated by at least one white-space character (but no newlines).

6.1.2.2.1.5.3    format wstring

This form consists of the words “format wstring”, followed by one or more wide-string literals, which are automatically concatenated.

6.1.2.2.1.6        Sample Templates

Here is a simple struct template:

struct point;

attributes {

      int   x;    /* Format defaults to %d */

      int   y;

}

format string "(%x%,%y%)"

 

Here is a simple template that uses the “point” struct template:

facility "Jan's Graphics Editor";

event_type 456;

description "Circle has wrong color";

attributes {

      int               color       "%#6x";

      struct point      center;

      int               radius;

}

format

Circle with center %center% and radius %radius% has wrong color.

Color (RGB) = %color%.

 

This template might yield the following output:

Circle with center (40,55) and radius 20 has wrong color.

Color (RGB) = 0x00ff7f.

 

Here's a more complicated example:

/*****************************************************************/

/* HEADER SECTION */

facility "LOCAL1";

event_type 0x3115;

 

/* CONST-ATTRIBUTES SECTION */

const {

      string      repair_action = "Replace SCSI adapter";

}

 

/* RECORD-ATTRIBUTES SECTION */

attributes {

      char        unit_ser_no[8]    "(%c)";

      ushort      lun               "%u";

      char        sense_bytes[12]   "%t";

/* For the next attribute, the various sections of the format_spec are

 * automatically concatenated into a single string.

 */

      uchar       recovery_stat     "%b/0x40/INTERFACE_WAS_RESET/"

                                    "0x20/RECOVERY_ACTION_STARTED/"

                                    "0x10/RECOVERY_ACTION_FAILED/";

/* The final attribute specification says to display the rest of the

 * bytes in dump format.

 */

      char        extra_data[_R_]   "%t";

}

 

/* FORMATTING SECTION */

format

SCSI interface error: Adapter Serial Number/LUN = %unit_ser_no%/\

%lun%

 

\tRecovery Status: %recovery_stat%

\tSense Bytes:

%sense_bytes%

        

\tRecommended repair action:

\t\t%repair_action%\n\n

 

%extra_data%

/*****************************************************************/

 

This template might yield the following output:

SCSI interface error: Adapter Serial Number/LUN = XSCSI178/3

 

Recovery Status: 0x50(INTERFACE_WAS_RESET|RECOVERY_ACTION_FAILED)

Sense Bytes:

00000000 61 62 63 64 65 66 67 68  61 62 63 64              | abcdefgh abcd

        

Recommended repair action:

Replace SCSI adapter

 

 

00000000 26 B3 B3 25 AB BC CD                              | &..%...

 

6.1.2.2.1.7        More on Importing Templates

The algorithm for finding the template specified in an import statement is as follows:

  1. The struct_path from the import statement is converted into a relative pathname by replacing all periods with slashes and appending “.to”.  For example, “gui.graphics.point” becomes “gui/graphics/point.to”.
  2. This relative pathname is applied to each of the following directories in turn until a file is found:
    1. the directory in which the current template source file resides
    2. the directories specified in the EVLTMPLPATH environment variable (a colon-delimited list of directories).  If the EVLTMPLPATH environment variable is not defined, the directories /var/evlog/templates/$LANG and /var/evlog/templates are searched, in that order.
  3. The selected template file is read into memory if it is not already there.

 

It is neither necessary nor permitted to import a template with the same name as one previously defined in the current template source file, unless the imported template is from a different directory.  For example, the following sequence of statements is illegal

      struct statusRegister;

      [definition of struct statusRegister’s attributes and format]

      END

      import statusRegister;  /* ILLEGAL */

 

However, the following sequence of statements is legal:

      struct statusRegister;

      [definition of struct statusRegister’s attributes and format]

      END

      import chipSet.fpu.statusRegister;  /* LEGAL [unless chipSet/fpu specifies the current directory] */

      import chipSet.fpu.dataRegisters;

      ...

      attributes {

            struct statusRegister cpuStatus;    /* refers to struct defined in this file */

            struct chipSet.fpu.statusRegister fpuStatus;

            struct dataRegisters dataRegs;

      }

      ...

 

6.1.2.2.2         Using formatting templates with POSIX_LOG_STRING and POSIX_LOG_NODATA

 

When using formatting templates with log_format of POSIX_LOG_NODATA, the "record attributes" section will be omitted, but the other 4 sections (imports/typedefs, header, const attributes, and template formatting specification) can still be used, and can reference attributes in the fixed portion of the event record.

 

When using formatting templates with log_format of POSIX_LOG_STRING, the "record attributes" section should specify a single attribute of type string -- for example:

 

     string      event_string;

 

"event_string" can then be referenced in the template formatting specification.

 

 

6.1.2.2.3        Advantages and Disadvantages

One advantage of the POSIX_LOG_BINARY data format is that only binary data values are stored in the event record, not formatting information, thus producing smaller event records.  Another advantage is that additional explanatory or suggested-action information can be included in the formatting templates, without increasing the size of the event records, or changing the software that logs the events.  The primary disadvantage is that formatting templates are stored separately from the code that logs the event, so there is a chance that the code and the template will get out of sync.

        

The creation, updating, and management of the formatting templates are described under FormattingTemplates and Formatting templates - Add/delete templates

 

6.2      Event Logging and Retrieval

6.2.1        Facility Registry

When events are written to the event log, one of the arguments that gets passed is facility.  The facility argument can be obtained by calling posix_log_strtofac() which converts a character string representation of facility into an integer representation, which is what actually gets stored into the event log.  posix_log_strtofac(), and posix_log_factostr() which converts integer to character string, both read from the file /var/evlog/facility_registry which has the following minimum entries, to support the minimum set of facilities specified by the POSIX standard (plus CRON and AUTHPRIV defined for syslog):

0      KERN 

8      USER

16    MAIL

24    DAEMON

32    AUTH

40    SYSLOG

48    LPR

56    NEWS

64    UUCP

72    CRON

80      AUTHPRIV     private     

88      FTP

96    LOGMGMT

128  LOCAL0

136  LOCAL1

144  LOCAL2

152  LOCAL3

160  LOCAL4

168  LOCAL5

176  LOCAL6

184     LOCAL7

Note that there is an additional parameter specified for "80  AUTHPRIV".  The parameter  "private" indicates that events logged with log_facility=AUTHPRIV will be written to a "private" log file,  /var/evlog/privatelog file.   If  this parameter is not set then events are logged to the standard active log file,  /var/evlog/eventlog.  Events cannot be logged to more than one log file.  "private" can be specified for multiple facilities.

The ability to write events to a private log instead of the standard log is modeled after the handling of syslog messages with facility of AUTHPRIV.   syslog.conf is frequently set up to write AUTHPRIV messages to /var/log/secure, while other messages are written to /var/log/messages (or destinations specified in /etc/syslog.conf).  This provides the ability to allow general read access for most messages but more restrictive read access for AUTHPRIV messages, as determined by the file permissions for the 2 (or more) message files.

Similar to the "private" parameter, another optional parameter, "kernel" may also be indicated.  For example:

0      KERN   kernel

The "kernel" parameter indicates that events logged by this facility will be logged from the kernel, as opposed to user-space.   If "kernel" is specified, and the associated event did not originate in the kernel, then the event will not be logged.   

 The facility codes match the corresponding definitions in sys/syslog.h, with the exception of LOGMGMT, which is not defined in syslog.h:

/* facility codes */

#define     LOG_KERN    (0<<3)      /* kernel messages */

#define     LOG_USER    (1<<3)      /* random user-level messages */

#define     LOG_MAIL    (2<<3)      /* mail system */

#define     LOG_DAEMON  (3<<3)      /* system daemons */

#define     LOG_AUTH    (4<<3)      /* security/authorization messages*/

#define     LOG_SYSLOG  (5<<3)      /* messages generated by syslogd */

#define     LOG_LPR     (6<<3)      /* line printer subsystem */

#define     LOG_NEWS    (7<<3)      /* network news subsystem */

#define     LOG_UUCP    (8<<3)      /* UUCP subsystem */

#define     LOG_CRON    (9<<3)      /* clock daemon */

#define     LOG_AUTHPRIV(10<<3)     /* security/authorization messages (private) */

#define     LOG_FTP     (11<<3)     /* ftp daemon */

 

      /* other codes through 15 reserved for system use */

#define     LOG_LOCAL0  (16<<3)     /* reserved for local use */

#define     LOG_LOCAL1  (17<<3)     /* reserved for local use */

#define     LOG_LOCAL2  (18<<3)     /* reserved for local use */

#define     LOG_LOCAL3  (19<<3)     /* reserved for local use */

#define     LOG_LOCAL4  (20<<3)     /* reserved for local use */

#define     LOG_LOCAL5  (21<<3)     /* reserved for local use */

#define     LOG_LOCAL6  (22<<3)     /* reserved for local use */

#define     LOG_LOCAL7  (23<<3)     /* reserved for local use */

 

A system that uses this event logging will probably add many more additional facilities to this registry to represent the entities in the system that will be logging events.  The evlfacility - Manage Facility Registry command is provided for Systems Administrators.  Additionally, functions are available in both kernel and user space for registering new facilities and obtaining facility integer values based on facility name.   See Registering Facilities and  7.5      Appendix F   Facility Names and Facility Code creation for more details.

 

6.2.1.1       Restricted Logging

 

In addition to the optional "private" and "kernel" parameters, an optional "restricted logging" filter can also be specified for any facility in the facility registry.   If a restricted logging filter is not specified for a facility, then all event records from that facility will be logged (unless discarded by another mechanism - see Screening of Events and Discarding duplicate events).  However, if a restricted logging filter is specified, then only event records with attribute values matching the filter will be logged.  To illustrate, see the following examples:

This entry in the facility registry…

136  LOCAL1   private    ' uid = "bsmith" && severity=INFO '

specifies that events from facilty LOCAL1 will only be logged if user id is "bsmith" and severity is INFO, and they will be written to the "private" log. 

In this example:

0xf39e1b2a   "My Facility"    ' log_format != BINARY '

specifies that events from facility "My Facility" will only be logged to the standard event log if variable-length data is NODATA or STRING.

The restricted logging filter is applied by the evlogd daemon (see Event Buffer and evlogd Daemon) before the event record is written to the log file.  Only attribute members from the fixed portion of the event record may be referenced in the filter.

 

6.2.2        evlogd Daemon  and Event Buffering

 

For events logged in user space the evlogd daemon (/usr/bin/evlogd) reads the events via socket from posix_log_write() and other user-space logging functions and writes the events into the standard event log (/var/evlog/eventlog), or alternately into the private event log (/var/evlog/privatelog) for facilities identified with the "private" option in the facility registry.  Events that are discarded either by the screening process (see Screening of Events), or by the discarding of duplicate events (see Discarding duplicate events), are not written to either log.

 

For events logged in the kernel the evlogd daemon forks a child process that reads events from the kernel event buffer via the ksyslog() system call and passes them to evlogd (via socket).  The child process will adjust the log_time value in the event record header if the EVL_INITIAL_BOOT_EVENT or EVL_KERNTIME_LOCAL bits are set in log_flags.  See 6.1.1        Fixed portion of Event Record for details.  evlogd also provides special handling of events associated with facility registration, as described under Registering Facilities from Kernel space.  evlogd writes events read from the kernel to one of the two log files (except for ones it discards) as described above.

 

The kernel event buffer is a static buffer with a default size of 128 Kbytes.  If required, the event buffer size can be changed during kernel configuration.  When the volume of incoming messages from posix_log_write() and other kernel logging functions completely fills the buffer faster than they can be read by evlogd, the most recently written events are discarded.  Once the overrun condition has been resolved, an event is logged indicating the total number of events that were dropped.

 

For example, assume that a flood of events results in 162 events being dropped, then viewing the event log with a filter of

facility == LOGMGMT  &&  event_type == EVL_BUFFER_OVERRUN

and displaying in compact mode, might show the following:

 

1453,43,POSIX_LOG_STRING,6,LOGMGMT,INFO,0,0,753,16,Sat Sep 15 11:32:31 2001,0,2,1,Discarded 162 events due to buffer overrun

 

During periods when the evlogd daemon is unable to gain exclusive access to /var/evlog/eventlog or /var/evlog/privatelog for writing event records, for example when the files are locked for log management, it allocates a temporary buffer to hold events (both kernel and user events).  When the locked file can be opened again by evlogd, the events are read from the buffer, written to the appropriate log file, and the buffer is freed. If the allocated buffer overflows before the events can be written to the log file(s) then the number of discarded events is counted and an event identical to the one described in the previous paragraph is logged.   

 

 

6.2.2.1       Screening of Events

 

The default behavior of the various write functions is as follows:

1.        All events written from the Kernel using the functions defined under Writing Events from Kernel Space, and events passed to printk(), are logged. 

2.        All events written by root (log_uid="root") are logged. 

3.        Events with log_facility of LOG_KERN will be logged if, and only if, they are written by the kernel or log_uid ="root".  This behavior cannot be modified.  If an illegal write of an event using LOG_KERN is attempted, the event will not be written to the kernel buffer, and whichever write function was called will return EPERM. 

4.        All events not covered by the preceding items, are logged. 

With the exception of item 3 above, the default behavior can be modified through use of the evlconfig command using the -screen option, which allows specifying which events logged from the kernel, by root, and from applications will be discarded.  To illustrate, defining the following screen:

evlconfig  -screen   uid = 0  &&  (facility = LPR  ||  severity = DEBUG)

specifies that events logged by root with facility of LPR, or with severity of DEBUG, will be discarded.

Note that all members of posix_log_entry (the fixed-portion of the event record) are valid for the -screen option.  See evlconfig - Configure logging daemon for more details.

An additional mechanism for discarding events is described under Discarding Duplicate Events.

 

6.2.2.2       Discarding duplicate events

 

An event is considered a duplicate if it is identical to the previous event, meaning that both the fixed portion, with the exception of log_time and log_recid, and the variable-length portion are the same.

   

When an event is to be logged, it is checked to determine if it is a duplicate of the previously logged event, based on the above definition.  If it is a duplicate, a duplicate-event counter will be incremented by 1, and the event will be discarded (purged from the event buffer and not written to the event log).  Also, if this is the first in this batch of discarded duplicates, a timer will be started (see item 3 below).

 

The discarding of duplicates continues until one of the following occurs:

 

  1. A different (not a duplicate) event is logged.
  2. The number of duplicate events matches the count specified with the evlconfig -dup_count command, or the default count.
  3. The time interval specified with the evlconfig -dup_time_int command, or the default time interval, has passed.

 

Note that if dup_time_int is set to 0, then step 3. does not apply.  Conversely, if dup_count is set to 0, then step 2. does not apply.  If both are 0, no duplicates are discarded, meaning all events are logged.

 

For all three cases, an event is logged that indicates the total number of duplicate events that were discarded, along with the event_type and facility.  Additionally, checking for duplicates is restarted (duplicate counter is reset to 0 and timer is cleared).[2]  

 

Discarding of duplicates can be switched on and off with the evlconfig -discard dups on | off command.

 

To illustrate, assume a duplicate-event count of 25, a time interval of 1 second, the logging of the same duplicate event at a rate of 30 events per second, and discarding of duplicates is enabled.  If all occurrences of the event in the log are displayed, by using a filter of

(facility == LOCAL1 || facility == LOGMGMT) &&

(event_type == 37 || event_type == EVL_DUPS_DISCARDED)

and displayed in compact mode, then the output might appear as follows:

 

1452,32,POSIX_LOG_STRING,37,LOCAL1,ERR,21924,3,753,16,

Thu Mar 15 19:32:31 2001,0,2,1

SCSI device 13 interface reset

 

1453,66,POSIX_LOG_STRING,7,LOGMGMT,INFO,0,0,753,16,

Thu Mar 15 19:32:31 2001,0,2,1

Discarded 25 duplicate events, event_type = 37, facility = LOCAL1

 

1454,32,POSIX_LOG_STRING,37,LOCAL1,ERR,21924,3,753,16,

Thu Mar 15 19:32:32 2001,0,2,1

SCSI device 13 interface reset

 

1453,66,POSIX_LOG_STRING,7,LOGMGMT,INFO,0,0,753,16,

Thu Mar 15 19:32:32 2001,0,2,1

Discarded 17 duplicate events, event_type = 37, facility = LOCAL1

 

1456,32,45,POSIX_LOG_STRING,37,LOCAL1,ERR,2324,6,2753,44,

Thu Mar 15 19:32:35 2001,0,1,1

Eth/0 interface reset by user

 

Note that the last event shown differs from the 44 events that preceded it, which were all duplicates.

 

It should also be noted that events which are written to the private log file, /var/evlog/privatelog, are also discarded by this mechanism.  See Facility Registry for more information on the private log file.

 

For more mores details on displaying events, see the evlview command.                                 

                                            

6.2.3        API Functions

6.2.3.1       Writing Event Records

Functions are provided for writing events to the event log from both user-space and from kernel-space. 

6.2.3.1.1        Writing Events from User Space

The POSIX standard provides posix_log_printf() for writing event records with log_format of POSIX_LOG_STRING from user-space.   It also provides posix_log_write(), where the log_format is specified, for logging from user-space.  An additional function is provided for writing event records with log_format of POSIX_LOG_BINARY, which is described below.

#include <posix_evlog.h>

#include <evlog.h>

int evl_log_write(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags, ...);

 

Used for writing event records with log_format of POSIX_LOG_BINARY, an alternative to posix_log_write() is provided where a variable-length argument list is passed instead of the address and length of a provider-allocated buffer.  Using this function, instead of posix_log_write(), removes the burden from the provider of allocating and subsequently freeing a buffer containing the variable-length data.

The evl_log_write() function determines from the variable argument list the size of the buffer to allocate, allocates and fills the buffer with the variable-length argument list, calls posix_log_write(), frees the buffer, and returns.

In order for evl_log_write() to allocate the correct buffer size, the optional attribute data type must be specified along with the optional attribute value, or values.   Valid data types are shown in the Table of Optional Attribute Data Types and Format Specifiers used with formatting templates, under Attribute Format.  Both single elements and arrays of elements may be specified.  The string "endofdata" must be used to indicate the end of the variable-length list.

 

If the variable-length data length exceeds LOG_ENTRY_MAXLEN, then the POSIX_LOG_TRUNCATE flag is set in log_flags and the data is truncated.

 

An example illustrates the required syntax, and ordering:

rc =  evl_log_write( facility, event_type, severity,

  "ushort", 0x1111,    /* type = unsigned short, value = 0x1111 */    

  "4*uchar", 5, 10, 15, 20,     /* 4 consecutive unsigned chars */

  "int[]", 10, int_array,       /* array of 10 ints */

  "string", "This is an example",

  "endofdata");

 

Values are packed into the buffer, with no pad bytes added for alignment.  Given the above example, on a 32-bit machine, the resulting buffer will be 65 bytes long: 2 for the ushort, 4 for the uchars, 40 for the int array, and 19 for the (null-terminated) string.

The flags argument contains application-defined flags.  The event record's log_flags member shall be set to the value of the flags argument.   evl_log_write() may also set the {POSIX_LOG_TRUNCATE} flag in the event record's log_flags member, as appropriate.  If the {POSIX_LOG_TRUNCATE} flag is set in the flags argument, it will also be set in the event record's log_flags member, even if evl_log_write() does not truncate the record.

 

 

Errors returned:

 

[EINVAL]              The facility argument is not a valid log facility.

 

[EINVAL]              The severity argument is invalid.

 

[EINVAL]              Arguments in the variable-length argument list are either invalid or not in the expected order, or an invalid number of arguments were passed.

 

[ENOSPC]              The event buffer has run out of space.

 

[EPERM]                The caller does not have the appropriate privilege for writing with the given facility.  Specifically, an application whose effective user ID is not root has attempted to log an event with a facility of LOG_KERN.

 

[EIO]                       An I/O error occurred.  This includes the event logging system not being configured.

 

 

 

#include <posix_evlog.h>

#include <evlog.h>

int evl_log_vwrite(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags, va_list args);

 

Identical to evl_log_write() with the exception that args is passed instead of a variable-length argument list. 

 

 

#include <posix_evlog.h>

int posix_log_vprintf(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags,

        const char *format, va_list args);

 

Identical to posix_log_printf(), described in the POSIX Spec., with the exception that args is passed instead of a variable-length argument list. 

 

 

 

6.2.3.1.2        Writing Events from Kernel Space

 

API functions that are analogous to posix_log_printf(), evl_log_write(), and posix_log_write()  are provided for writing events to the event log in kernel-space. 

 

#include <evl_log.h>

int posix_log_write(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, const void *buf, size_t len,

        int format, unsigned int flags);

 

This function has the same arguments, behavior, and returns (other than noted below) as posix_log_write() in user-space, which is defined in the draft POSIX standard.  Please refer to the POSIX event-logging specification referenced in Appendix A  POSIX 1003.25 **DRAFT** for a complete description of this function.

 

The following returns are not applicable to posix_log_write() in the kernel:

 

[EINVAL]              The facility argument is not a valid log facility.  

 

Any facility value is accepted; however, to avoid duplicate facility names between the kernel and user-space, facilities used in the kernel should be registered in the facility registry.  See Facility Registry for details.

 

[EMSGSIZE]         The len argument exceeds {POSIX_LOG_ENTRY_MAXLEN} length, and {POSIX_LOG_TRUNCATE} is not defined by the implementation.

 

POSIX_LOG_TRUNCATE is defined for this implementation.

 

              [EPERM]  The caller does not have the appropriate implementation-defined privilege for writing with the given facility.  For example, an application whose effective user ID is not root has attempted to log an event with a reserved facility code.

 

Any facility value is accepted .

 

              [ECANCELED]       The event-logging system has declined to log this event, for some implementation-defined reason.  For example, this event is a duplicate of another recently logged event, or the event-logging system has been configured to screen out events such as this one.

 

                                There are no implementation-defined reasons in this implementation.  Discarding of duplicates, for example, is performed by the evlogd logging daemon, not this function.

                               

              [EIO]     An I/O error occurred in writing to the system log. 

 

                                Not a valid return inside the kernel since event is only written to a buffer (unless it is full, then ENOSPC is returned).

 

     The following return exists only for posix_log_write() in the kernel, not in user-space.

 

              [ENOSYS]       Event logging is not configured in the kernel.

                               

 

 

#include <evl_log.h>

int posix_log_printf(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags, const char *format, ...);

 

This function has the same arguments, behavior, and returns (other than noted below) as posix_log_printf() in user-space, which is defined in the draft POSIX standard.  Please refer to the POSIX event-logging specification referenced in Appendix A  POSIX 1003.25 **DRAFT** for a complete description of this function.

 

The following returns are not applicable to posix_log_printf() in the kernel:

 

[EINVAL]              The facility argument is not a valid log facility.  

 

Any facility value is accepted; however, to avoid duplicate facility names between the kernel and user-space, facilities used in the kernel should be registered in the facility registry.  See Facility Registry for details.

 

               [EPERM]  The caller does not have the appropriate implementation-defined privilege for writing with the given facility.  For example, an application whose effective user ID is not root has attempted to log an event with a reserved facility code.

 

Any facility value is accepted .

 

              [ECANCELED]       The event-logging system has declined to log this event, for some implementation-defined reason.  For example, this event is a duplicate of another recently logged event, or the event-logging system has been configured to screen out events such as this one.

 

                                There are no implementation-defined reasons in this implementation.  Discarding of duplicates, for example, is performed by the evlogd logging daemon, not this function.

 

 

[EIO]     An I/O error occurred in writing to the system log. 

 

                                Not a valid return inside the kernel since event is only written to a buffer (unless it is full, then ENOSPC is returned).

 

     The following return exists only for posix_log_write() in the kernel, not in user-space.

 

              [ENOSYS]       Event logging is not configured in the kernel.

 

 

#include <evl_log.h>

int posix_log_vprintf(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags,

        const char *format, va_list args);

 

Identical to posix_log_printf(), with the exception that args is passed instead of a variable-length argument list. 

 

 

 

#include <evl_log.h>

evl_writek(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags, ...);

 

Used for writing event records with log_format of POSIX_LOG_BINARY,  the evl_writek() function determines from the variable argument list the size of the buffer to allocate, allocates and fills the buffer with the variable-length argument list, writes to the event buffer, and returns.

In order for evl_writek() to allocate the correct buffer size, the optional attribute data type must be specified along with the optional attribute value, or values.   Valid data types are shown in the Table of Optional Attribute Data Types and Format Specifiers used with formatting templates, under Attribute Format with the exception of float, double, ldouble, wchar and wstring, which are not supported.  Both single elements or arrays of elements may be specified.  The string "endofdata" must be used to indicate the end of the variable-length list.

 

If the variable-length data length exceeds LOG_ENTRY_MAXLEN then the POSIX_LOG_TRUNCATE flag is set in log_flags and the data is truncated.

 

All facility codes and event types will be accepted.   However, to avoid duplicate facility names between the kernel and user-space, facilities used in the kernel should be registered in the facility registry.  See Facility Registry for details.

 

Here is a sample call to evl_writek().  See the corresponding example in the description of the evl_log_write() function for an explanation of the argument list.

rc = evl_writek( facility, event_type, severity,

  "ushort", 0x1111,

  "4*uchar", 5, 10, 15, 20,

  "int[]", 10, int_array,

  "string", "This is an example",

  "endofdata");

The flags argument contains caller-defined flags.  The event record's log_flags member shall be set to the value of the flags argument.   evl_writek() may also set the {POSIX_LOG_TRUNCATE} flag in the event record's log_flags member, as appropriate.  If the {POSIX_LOG_TRUNCATE} flag is set in the flags argument, it will also be set in the event record's log_flags member, even if evl_writek() does not truncate the record.

 

 

 

Errors returned:

 

[EINVAL]              The severity argument is invalid.

 

[EINVAL]              Arguments in the variable-length argument list are either invalid or not in the expected order, or an invalid number of arguments were passed.

 

[ENOSPC]              The event buffer has run out of space.

 

[ENOSYS]              The event logging system is not configured.

 

 

#include <evl_log.h>

evl_vwritek(posix_log_facility_t facility, int event_type,

        posix_log_severity_t severity, unsigned int flags, va_list args);

 

Identical to evl_writek(), with the exception that args is passed instead of a variable-length argument list.

 

 

6.2.3.2       Formatting Event Records

 

#include <posix_evlog.h>

#include <evlog.h>

int evl_format_evrec_fixed(const  struct  posix_log_entry  *entry,  char *buf, size_t buflen,

        size_t *reqlen, const char *separator, size_t linelen,  int fmt_flags);

 

This function stores a character string describing the data contained in the fixed portion of the event record pointed to by entry into the buffer pointed to by the buf argument.

 

The buffer pointed to by buf is assumed to be at least buflen bytes long.  If buf is equal to NULL, or the buffer is too small to hold the returned character string, the function will fail.  In any case, if the reqlen argument is not NULL, the length in bytes required for the full character string will be stored in the location pointed to by reqlen.

 

The character string passed in the separator argument is used to delimit attributes that are written into buf.   If separator is NULL, no delimiter string is inserted between attributes.      

 

This function inserts newlines (\n) as necessary into the buf buffer to limit the maximum line length to linelen characters.  A linelen value of 0 indicates that there is no limit on the line length.  (If an attribute's value exceeds linelen characters, it will have a line to itself.)

 

The following  fmt_flags modify the character string written to the buffer:

 

EVL_COMPACT

 

Specifies that contents of the event record are written in a compact form.  This means that the attribute names for attributes in the fixed portion of the event record are not written, only the values.

 

                An example with a separator of ", " and linelen of 67:

 

recid=7214, size=31, format=POSIX_LOG_STRING, event_type=3, facility=LOCAL1, severity=ERR, uid=2324, gid=6, pid=2753, pgrp=44, time=Tue Jun 19 19:32:31 2001, flags=0, thread=-1, processor=1

     

An example of the COMPACT formatting, with a separator of "!" and a linelen of 0:

 

7214!31!POSIX_LOG_STRING!3!LOCAL1!ERR!2324!6!2753!44!Tue Jun 19 19:32:31 2001!0!-1!1    

 

Errors returned:

[EINVAL]     entry or buf are NULL

[EINVAL]     fmt_flags not equal to EVL_COMPACT, and not equal to 0.

[EINVAL}    separator is > 20 characters.

[EMSGSIZE] buf is too small to hold the string.

       

#include <posix_evlog.h>

#include <evlog.h>

int evl_format_evrec_variable(const struct posix_log_entry  *entry,  const void *var_buf, char *buf,      size_t buflen, size *reqlen);

This function stores a character string describing the data contained in the variable-length portion of the event record pointed to by var_buf into the buffer pointed to by the buf argument.

 

The buffer pointed to by buf is assumed to be at least buflen bytes long.  If  buf is equal to NULL, or the buffer is too small to hold the returned character string, the function will fail.  In any case, if the reqlen argument is not NULL, the length in bytes required for the full character string will be stored in the location pointed to by reqlen.

 

The actions performed are based on the log_format value:

·       POSIX_LOG_NODATA - If a formatting template exists, then applicable information read from the appropriate formatting template is copied into the buf buffer; otherwise, a null string is copied into buf.  

·         POSIX_LOG_STRING - If a formatting template exists, then applicable information read from the appropriate formatting template, in combination with the null-terminated string read from var_buf,, is copied into buf  (assuming that the string is referenced in the record attributes section of the template) ; otherwise, just the null-terminated string is copied into buf. 

·         POSIX_LOG_BINARY - If a formatting template exists, then variable-length data from var_buf is formatted based upon information read from the appropriate formatting template and copied into buf; otherwise, the variable-length data is formatted in dump format (displayed in HEX, with ASCII equivalent), for example:

 

00000000 61 62 63 64 65 66 67 68  61 62 63 64 65 66 67 68 | abcdefgh abcdefgh

00000010 3F 3F 3F 3F 4A 3F 3F 3F  3F 3F 3F 3F 4A 3F 3F 3F | ????J??? ????J???

 

 

Errors returned:

[EINVAL]        buf,  entry or var_buf are NULL.

[EMSGSIZE]    buf is too small to hold string.

 

#include <posix_evlog.h>

#include <evlog.h>

int evl_format_evrec_sprintf(const struct posix_log_entry *entry,  const void *var_buf, const char *format, char *buf, size_t buflen, size *reqlen);

This function stores a character string describing the data contained in the event record pointed to by entry (the fixed portion) and var_buf  (the variable-length portion) into the buffer pointed to by the buf argument.  

 

The desired formatting is specified in the format argument.

 

Standard attributes are referenced using the attribute names defined in the POSIX standard:

recid, size, format, event_type, facility, severity, uid, gid, pid, pgrp, time, flags, thread, processor

For example, %recid% is replaced by the event record’s decimal record ID.

 

The pseudo-attribute “data” stands for entire variable-length portion of the event record.  The construct %data% is replaced by the string obtained by formatting this record using evl_format_evrec_variable() (see above).

 

The construct %attribute_name%, where attribute_name is the name of a non-standard attribute defined in this event record’s formatting template, is replaced by the formatted value of that variable.  attribute_name can be a simple name (e.g. “employee”) or a reference to a struct member (e.g. "employee.addr.city").

 

An attribute’s format can be overridden by appending a valid format specifier to the attribute name, separated by a ':' -- for example, %event_type:x%.

 

The buffer pointed to by buf is assumed to be at least buflen bytes long.  If  buf is equal to NULL, or the buffer is too small to hold the returned character string, the function will fail.  In any case, if the reqlen argument is not NULL, the length in bytes required for the full character string will be stored in the location pointed to by reqlen.

 

As an example, assume a formatting template like the one shown for event type 0x3115 under Formatting Template Example.  Given a format string defined as follows:

 

"Logical unit number is 0x%lun:x%\nfor facility %facility% and event type of  %event_type% decimal, 0x%event_type:x% hex\n"

 

The result stored in buf is:

 

Logical unit number is 0x3

for facility LOCAL1 and event type of 12565 decimal, 0x3115 hex

 

 

Errors returned:

[EINVAL]         entry, var_buf or buf are NULL

[EINVAL]         format is equal to NULL.

[EMSGSIZE]    buf is too small to hold the string.

[EBADMSG]    format references an attribute which does not exist.

 

#include <posix_evlog.h>

#include <evlog.h>

int evl_atttostr(const char *attribute, const struct posix_log_entry *entry, const void *var_buf, char *buf, size_t buflen, size_t *reqlen);

 This function stores a null-terminated character-string representation of an attribute value into the buffer pointed to by buf.  The value is taken from the event record whose fixed and variable parts are pointed to by entry and  var_buf, respectively.  The attribute's name is attribute.

The attribute is formatted according to the rules specified for evl_format_evrec_sprintf().

The buffer pointed to by buf is assumed to be at least buflen bytes long.  If  buf is equal to NULL, or the buffer is too small to hold the returned character string, the function will fail.  In any case, if the reqlen argument is not NULL, the length in bytes required for the full character string will be stored in the location pointed to by reqlen.

 

 

Errors returned:

[EINVAL]         buf or entry is NULL.

[EINVAL]         var_buf is NULL, and log_format is not POSIX_LOG_NODATA.

[EINVAL]         attribute is invalid, or does not exist in this event record.

[EMSGSIZE]    buf is too small to hold the string.

 

6.2.3.3       Formatting Templates

 

The formatting template example describes the information that is contained in a particular template.

Like C modules, formatting templates exist in two forms: source and binary.  A template source file that contains n template specifications will yield n binary template files when it is compiled using the evltc command.  Compilation of a template source file occurs in two steps:

1.        Parsing the template specification(s), as with the evl_parsetemplates() function

2.        Creating the binary file for each template, as with the evl_writetemplates() function

This is essentially what the evltc template compiler does.  These two functions are described in the “Template Management” section that follows.

API functions for template application are provided to:

·         Read the template's binary information, and return a pointer to a master evltemplate_t object.

·         Make one or more clones of a master evltemplate_t object.

·         Populate an evltemplate_t clone object with an event record's optional attributes (either initially, or to update the previous optional attributes with the most recent ones).

·         Use the evltemplate_t object to examine an event record's attributes.

 

6.2.3.3.1        The Template Repository

By default, the template repository is the directory /var/evlog/templates.  The evl_readtemplate() function, which loads an event-record template into memory, looks for that template in the binary file “/var/evlog/templates/facility/eventtype.to” where facility is the canonical facility name (see 7.5      Appendix F   Facility Names and Facility Code creation), and eventtype is the hexadecimal event type.  For the default template for facility facility, the binary template file is named default.to.  If the EVLTMPLPATH environment variable is set (and contains a colon-delimited set of directory paths), evl_readtemplate() will search those directories instead of  /var/evlog/templates.  If EVLTMPLPATH is not set, but the LANG environment variable is set, templates will be sought in /var/evlog/templates/$LANG first, then /var/evlog/templates.

The algorithm for finding a struct template that is referenced by another template is described under “More on Importing Templates” in the description of a template source file.  This algorithm is also affected by the EVLTMPLPATH environment variable.

When a template source file is compiled, the resulting binary files are created in the same directory as the source file.  Within a binary file, all struct references are relative, not absolute.  Therefore, it is possible to build a set of template binary files in one location (specified by the EVLTMPLPATH variable), and then move them (with or without the source files) to /var/evlog/templates.

 

6.2.3.3.2   Notes on template Use in Multithreaded Applications     

The functions in the “Compiling Templates” section are not intended to be thread-safe.  Using these functions in one thread, while another thread uses these same functions and/or the functions in the “Template Application” section, will produce undefined results.

 

The functions in the “Template Application” section are intended to be thread-safe in an application that uses POSIX threads.  Keep in mind, however, that if you pass the TMPL_REUSE1CLONE flag to evltemplate_initmgr(), all subsequent calls to evl_readtemplate() that request a clone of a particular template will return pointers to the same clone.  Therefore, take care when using the TMPL_REUSE1CLONE option in multithreaded applications.

 

Also keep in mind that functions such as the following may call functions in the “Template Application” section in order to obtain information about non-standard attributes in a record: posix_log_seek(), posix_log_query_match(), evl_format_evrec_variable(), evl_format_evrec_sprintf(), evl_atttostr().

 

6.2.3.3.3        Compiling Templates

 

#include <posix_evlog.h>

#include <evl_template.h>

int evl_parsetemplates(const char *source_filename, evltemplate_t *template_list[ ], size_t listsize,

size_t *ntemplates, FILE *errorfile, const char *prog_name);

 

This function reads the template specification(s) contained in the file whose pathname is source_filename.  Each template specification is checked for errors.  If errorfile is not NULL, error messages (if any) are written to errorfile.  Certain types of error messages are prefixed with the specified program name, prog_name -- e.g., “evltc”.

For each template specification that is successfully parsed, a pointer to the corresponding template object is stored in the template_list array.  listsize specifies the capacity of the array (i.e., the number of elements).  Upon return, *ntemplates is set to the number of successfully parsed templates.

The following types of errors are detected:

o        Syntax error

o        Facility, event_type, or struct name missing or invalid

o        A struct without attributes

o        Problems with an attribute’s name, type, dimension, or format

o        Const attribute value missing or incompatible with type

o        Invalid attribute reference in format section

o        Reference to a nonexistent struct template

o        Multiple instances of the same template (e.g., the source file contains multiple templates for struct x)

If there is at least one valid template specification, and no errors are detected, evl_parsetemplate() returns 0; otherwise it returns one of the following error codes:

[EINVAL]              The source_filename argument does not specify a readable file.

 

[EINVAL]              template_list is NULL, or ntemplates is NULL, or prog_name is NULL.

 

[EBADMSG]         Syntax error in template information; error messages are written to errorfile.

 

[EMSGSIZE]         template_list is not big enough to hold pointers to all the templates in the source file; that is, ntemplates exceeds listsize.

 

 

#include <posix_evlog.h>

#include <evl_template.h>

int evl_writetemplates(const char *directory, const evltemplate_t *template_list[ ], size_t listsize);

 

templatelist is an array of pointers to unpopulated templates, as returned by evl_parsetemplates().  listsize is the number of templates in the array.  This function writes each template to a binary template file in the directory whose pathname is directory.  Any existing file by that name is overwritten.

The name of a struct-template file is structname.to, where structname is the name of the struct.  The name of an event-record template is eventtype.to, where eventtype is the decimal event type.  If eventtype  is negative, the minus sign (-) is converted to an equals sign (=).

evl_writetemplates() returns 0 on success, or the indicated error code if one of the following errors is detected.  evl_writetemplates() stops writing files when it detects an error, but does not attempt to restore or remove files written before the error was detected.

 

[EINVAL]              template_list is NULL, or listsize is zero.

 

[ENOTDIR]           directory does not specify an existing directory.

 

[EPERM]                The caller does not have the appropriate privilege to write the desired template file(s).

 

[EIO]                       Some other error occurred while trying to write a template file.

 

6.2.3.3.4        Template Application

 

#include <posix_evlog.h>

#include <evl_template.h>

int evl_readtemplate(posix_log_facility_t facility, int event_type, evltemplate_t **template, int clone);

This function loads into memory a copy of the template for the specified facility and event type, and stores a pointer to that template at the location pointed to by template.  If this template references one or more struct templates (i.e., because this template has attributes of type struct), those templates will also be loaded into memory if they are not already present.

 

If the value of clone is zero, the resulting template will be the master template for this facility and event type.  If the master template for this facility and event type already exists in memory, evl_readtemplate() will return a pointer to that template.  The master template cannot be populated; it must first be cloned (using evl_clonetemplate()), and the resulting clone can be populated.

 

If the value of clone is non-zero, the resulting template will be a clone, as created by evl_clonetemplate(), and template->tm_master will point to the master template.  If the TMPL_REUSE1CLONE flag was passed to the template manager via evltemplate_initmgr(), and a clone of this template already exists in memory, evl_readtemplate() will return a pointer to that clone; otherwise a new clone will be created.

 

If there is no template specifically designated for the indicated facility and event type, but there is a default template for that facility, that default template will be provided.  As with other templates, only one master copy of a facility’s default template will be created, even if it is accessed via multiple evl_readtemplate() calls with different event types.  Similarly, if the TMPL_REUSE1CLONE flag is set in the template manager, there will be only one clone of the default template (unless you create others explicitly using evl_clonetemplate()).

 

evl_readtemplate() returns 0 on success, or the indicated error code if one of the following errors is detected.

 

[ENOENT]             There is no binary template file for the specified facility and event type, and there is no default template for that facility.

 

[EIO]                       The binary template file exists but cannot be successfully loaded.

 

[EINVAL]              template is NULL.

 

#include <posix_evlog.h>

#include <evl_template.h>

int evl_clonetemplate(evltemplate_t *master, evltemplate_t **clone);

This function creates a clone of the specified master template, and stores a pointer to the clone at the location pointed to by clone.  Any number of clones may be created from the same master template in this way.  Master templates are created using evl_readtemplate().

evl_clonetemplate() returns 0 on success, or the indicated error code if one of the following errors is detected.

 

[EINVAL]              master is NULL or clone is NULL .

 

[EINVAL}              master points to a clone template rather than a master.

 

#include <posix_evlog.h>

#include <evl_template.h>

int evl_populatetemplate(evltemplate_t *template, const posix_log_entry *entry, const void *buf);

This function populates the template object pointed to by template with values from the event record pointed to by entry (the fixed portion of the record) and buf (the optional portion).  The length, in bytes, of the buffer pointed to by buf is assumed to be entry->log_size.

 

template should have been previously created via evl_clonetemplate(), or via evl_readtemplate() with clone != 0 .  If it is currently populated, it will be depopulated before being repopulated with the new values.

 

It is not considered an error if the template implies that buf should contain more or less than entry->log_size bytes of data.  If buf contains more data than is implied by the template, the extraneous data will be stored in an attribute of type char[_R_] with the name _EXTRA_DATA_.  If buf contains insufficient data, the latter attributes in the template will be marked as empty.  If a scalar attribute is only partially filled when the end of buf is reached, that attribute will be marked as empty, and the leftover bytes will be stored in the _EXTRA_DATA _ attribute.  A partially filled struct or array will contain some populated elements and some empty ones.

 

If the data in buf implies that an array attribute has a negative size, the array will be treated as if it has a size of zero.

 

The populated template object contains references to the memory areas pointed to by entry and/or buf.  Therefore, if the contents of these areas are changed after the call to evl_populatetemplate(), subsequent references to the populated template (other than to depopulate or destroy the template) will produce undefined behavior.

 

Errors returned:

[EINVAL]              template or entry is NULL

[EINVAL]              template points to a master template rather than a clone.

 

#include <posix_evlog.h>

#include <evl_template.h>

int evl_depopulatetemplate(evltemplate_t *template);

The evl_depopulatetemplate() function disconnects the template object pointed to by template from its associated event record, reversing the effect of the previous evl_populatetemplate() operation on that template object.

 

Calling evl_depopulatetemplate() with a depopulated template object has no effect.

 

Errors returned:

 [EINVAL]             template is NULL, or appears to point to an invalid template object.

#include <posix_evlog.h>

#include <evl_template.h>

int evl_freetemplate(evltemplate_t *template);

The evl_freetemplate() function deallocates the template object pointed to by the template argument.  If the template object is populated (i.e., via evl_populatetemplate()), it will be depopulated before it is deallocated.

 

Since a master template shares a portion of its data structure with all its clones, it is illegal to deallocate a master template before deallocating all its clones.

 

Errors returned:

 [EINVAL]             template is NULL, or points to a master template with one or more existing clones.

#include <posix_evlog.h>

#include <evl_template.h>

int evl_releasetemplate(evltemplate_t *template);

 The evl_releasetemplate() function specifies that the indicated template can be released for reuse.  If the template is populated, it will be depopulated, unless the TMPL_LAZYDEPOP flag was passed to the template manager via evltemplate_initmgr().  If the template is a clone, and the TMPL_REUSE1CLONE flag was passed to the template manager, the template will be retained in memory; otherwise evl_releasetemplate() will attempt to free it by calling evl_freetemplate().

 

Errors returned:

 [EINVAL]     template is NULL, or points to a master template with one or more existing clones.

#include <posix_evlog.h>

#include <evl_template.h>

int evltemplate_initmgr(int flags);

The evltemplate_initmgr() function initializes this process’s template manager and specifies management options. The flags argument is the bitwise OR of zero or more of the following flags:

·         TMPL_REUSE1CLONE -- specifies that for a particular facility and event type, the same clone will be used all the time; each call to evl_readtemplate() with clone != 0 will return a pointer to this clone.  If this flag is not set, evl_releasetemplate() will free the specified clone, and evl_readtemplate() will create a new clone.

·         TMPL_LAZYDEPOP -- specifies that evl_releasetemplate() will not depopulate the specified clone.  This can be useful if the clone might be reused in its populated state.

For example, posix_log_query_match() may cause a clone template to be populated with a particular event record.  Before returning, posix_log_query_match() calls evl_releasetemplate().  If the TMPL_REUSE1CLONE and TMPL_LAZYDEPOP flags are set, the template will stay in memory and remain populated.  Subsequent code might then use the clone without repopulating it.

 

NOTE: To verify that a clone is populated with the correct event record, verify the following:

·         The clone’s tm_recid field matches the record ID of the desired record.

·         The clone’s tm_entry field is equal to the address of the record’s posix_log_entry struct.

·         The clone’s tm_data field is equal to the address of the record’s variable data.

 

By default (i.e, before evltemplate_initmgr() is first called), the TMPL_REUSE1CLONE and TMPL_LAZYDEPOP flags are cleared in the template manager.   A process must not call evltemplate_initmgr() more than once.

 

Errors returned:

 [EINVAL]     flags contains an illegal value.

 [EINVAL]    This function has been called previously.

 

#include <posix_evlog.h>

#include <evl_template.h>

int evltemplate_getatt(const evltemplate_t *template, const char *attribute_name, evlattribute_t **attribute);

attribute_name is the name of an attribute in the template object pointed to by template.  attribute_name can be a simple name (e.g., “employee”) or a reference to a struct member (e.g., “employee.addr.city”).  However, it cannot reference an array element (e.g., “widgets[2]” or “endPoints[1].y”).

The evltemplate_getatt() function stores a pointer to this attribute in the location pointed to by attribute.  The template may be master or clone, and may be populated or unpopulated.

Errors returned:

[EINVAL]              template does not point to a valid template.

[EINVAL]              attribute_name is NULL, or attribute is NULL.

 [ENOENT]            The template contains no attribute whose name is attribute_name.  The value of attribute is unchanged.

 

#include <posix_evlog.h>

#include <evl_template.h>

int evlatt_getstring(const evlattribute_t *attribute, char *buf, size_t buflen)

attribute is a pointer to an attribute in a template, as returned by evltemplate_getatt()or evltemplate_getatts(). The evlatt_getstring() function stores the string representation of that attribute’s value in the buffer pointed to by buf.  The buffer’s size in bytes is assumed to be buflen.  If the attribute's string representation would exceed buflen bytes, the copy is truncated to buflen bytes (including the terminating null character), and EMSGSIZE is returned.

If the specified attribute is empty (i.e., lacking a value in the associated event record), buf[0] is set to the null character to indicate a zero-length string.  This will always be the case for a non-const attribute in an unpopulated template.

Errors returned:

[EINVAL]              template does not point to a valid template.

[EINVAL]              attribute is NULL, or buf is NULL.

[EMSGSIZE]         The buffer length (as specified by buflen) is insufficient to hold the returned character string.

#include <posix_evlog.h>

#include <evl_template.h>

int evlatt_getinfo(const evlattribute_t *attribute, evlatt_info_t *info)

attribute is a pointer to an attribute in a template, as returned by evltemplate_getatt() or evltemplate_getatts(). The evlatt_getinfo() function stores the information about this attribute in the structure pointed to by info.  This structure has the following members:

typedef struct evlatt_info {

      unsigned int      att_flags;        /* flags defined below */

const char        *att_name;

int               att_type;         /* e.g., TY_INT, TY_STRING */

int               att_isarray;      /* 1 = array */

int               att_dimfixed;     /* # elements in fixed-size array */

int               att_dimpop;       /* # elements in populated array */

} evlatt_info_t;

 

The att_flags member may include the following flags:

·         EVL_ATTR_CONST – The attribute is a const attribute.

·         EVL_ATTR_BITFIELD – The attribute is a bit-field.

·         EVL_ATTR_EXISTS – The attribute has a value.  EVL_ATTR_CONST implies EVL_ATTR_EXISTS.  For a non-const attribute, EVL_ATTR_EXISTS will not be set if the template is not populated or the attribute lacks a value in the associated event record.

The att_name member points to the attribute’s name in the template object itself, and so should not be freed or otherwise modified by the caller.

If the attribute is not an array, the att_isarray, att_dimfixed, and att_dimpop members are all set to zero.  Otherwise, att_isarray is set to 1, and  att_dimfixed and att_dimpop have the following values:

·         If the template specifies that the array has a fixed number of elements, att_dimfixed contains that number, whether or not the template is populated, and whether or not the record (if any) actually contains the entire array.  Otherwise, att_dimfixed is -1.

·         If the EVL_ATTR_EXISTS flag is set for this attribute, att_dimpop contains the number of elements in the populated array.  Otherwise, att_dimpop is -1.

The att_type member specifies the base type of the attribute: one of the type codes listed in the following table.  To obtain the value of the attribute, use the function indicated in the table, passing the address of the evlattribute_t object.  Note that these functions cannot be used to extract values from arrays.

Type Code

Type

Function to Obtain Value

TY_CHAR, TY_SHORT, TY_INT, TY_LONG

char, short, int, long

long evl_getLongAttVal(att)

TY_UCHAR, TY_USHORT, TY_UINT, TY_ULONG

unsigned char, unsigned short, unsigned int, unsigned long

unsigned long evl_getUlongAttVal(att)

TY_LONGLONG

long long

long long evl_getLonglongAttVal(att)

TY_ULONGLONG

unsigned long long

unsigned long long evl_getUlonglongAttVal(att)

TY_ADDRESS

void *

void *evl_getAddressAttVal(att)

TY_FLOAT, TY_DOUBLE

float, double

double evl_getDoubleAttVal(att)

TY_LONGDOUBLE

long double

long double evl_getLongdoubleAttVal(att)

TY_STRING

char *

char *evl_getStringAttVal(att)

TY_STRUCT

struct

none

 

For an attribute of type struct, a pointer to the attribute’s struct template can be obtained using the evlatt_getstructtmpls() function, which see.

For an attribute that is an array of structs, the function evlatt_getstructfromarray() (which see) can be used to obtain a pointer to a populated struct template that represents a selected element of that array.

For other array attributes, the function evl_getArrayAttVal(att) returns a pointer to the first byte of that array in the event record.

Errors returned:

 [EINVAL]             attribute is NULL or info is NULL.

#include <posix_evlog.h>

#include <evl_template.h>

int evltemplate_getatts(const evltemplate_t *template, evlattribute_t *buf[ ], unsigned int bufatts, unsigned int *natts);

This function is like evltemplate_getatt(), except that it returns pointers to evlattribute_t objects for all attributes in the indicated template (which may be master or clone, populated or unpopulated).  buf points to an array into which evltemplate_getatts() will store the evlattribute_t pointers, and bufatts is the number of such pointers that the buffer can hold.

If buf is NULL or the number of attributes in the template exceeds bufatts, evltemplate_getatts() will fail.  In any case, if natts is not NULL, *natts will be set to the total number of attributes in the template.

For attributes of type struct, evltemplate_getatts() returns an evlattribute_t pointer for the struct itself (e.g. “startPoint”), but not for its component attributes (e.g., “startPoint.x”, “startPoint.y”).  The evlatt_getstructtmpls() function can be used to examine the template(s) corresponding to that attribute.

For an array attribute (including an array of structs), only one evlattribute_t object is returned; it describes the array itself.

Errors returned:

[EINVAL]              template does not point to a valid template.

[EINVAL]              buf is NULL, or bufatts is zero.

[EMSGSIZE]         The template contains more than bufatts attributes.

#include <posix_evlog.h>

#include <evl_template.h>

int evlatt_getstructtmpls(const evlattribute_t *attribute, const evltemplate_t **master, const evltemplate_t **clone);

attribute is a pointer to an attribute in a template, as returned by evltemplate_getatt() or evltemplate_getatts().  The base type of the attribute must be TY_STRUCT, and the attribute must not be an array.

If master is not NULL, a pointer to the master template for that struct is stored to the location pointed to by master.

If clone is not NULL, then a pointer to the populated clone template containing the component values for attribute is stored to the location pointed to by clone.  If attribute has no value (e.g., because it is part of a master template, or because it is an unpopulated attribute in a clone), NULL will be stored to the location pointed to by clone.

Errors returned:

[EINVAL]              attribute does not point to a non-array attribute whose base type is TY_STRUCT.

[EINVAL]              Both master and clone are NULL.

#include <posix_evlog.h>

#include <evl_template.h>

int evlatt_getstructfromarray(const evlattribute_t *att, int index, const evltemplate_t **tmpl);

att is a pointer to an attribute in a populated template, as returned by evltemplate_getatt() or evltemplate_getatts().  The attribute must be an array of structs.  index selects an element in this array.  *tmpl is set to point to the populated template that represents that particular element.

Errors returned:

[EINVAL]              att does not point to an attribute that is an array of structs.

[EINVAL]              att points to an unpopulated (or otherwise empty) array.

[EINVAL]              tmpl is NULL.

[EINVAL]              index is less than zero.

[ENOENT]             There is no element in the array with index = index.

 

6.2.3.4   Registering Facilities

 

6.2.3.4.1    Registering Facilities from User space

 

#include <evl_log.h>

int evl_register_facility( const char *fname, posix_log_facility_t  *fcode )

If the facility registry already contains a facility whose name is fname, set fcode to the corresponding code. 

If the facility registry does not contain a facility whose name is fname, compute the facility code as the 32-bit CRC of the canonical equivalent of fname, and set fcode to the computed value.  Add fname and fcode to the facility registry, unless there is already a facility in the registry with the same code as fcode, in which case return EEXIST. 

See 7.5      Appendix F   Facility Names and Facility Code creation for more details on facility code generation from canonical name.

   Errors returned:

[EINVAL]   fname or fcode are NULL

[EINVAL]   fname length is zero, or greater than POSIX_LOG_MEMSTR_MAXLEN

[EEXIST]   fcode generated from fname already exists in the facility registry.

[EPERM]    The caller does not have the appropriate privilege to register a facility.

[EAGAIN]   Insufficient system resources are available.  Try again.

 

#include <evl_log.h>

int evl_gen_facility_code( const char *fname, posix_log_facility_t  *fcode )

If fname is the upper or lower case name of a standard Linux facility, fcode is set to the corresponding facility code.  The standard facility names and facility codes are listed under 6.2.1        Facility Registry.

If fname is not a standard Linux facility, compute the facility code as the 32-bit CRC of the canonical equivalent of fname.  If the resulting code is the same as one of the standard facilities, return EEXIST; otherwise, set fcode to the computed value.

See 7.5      Appendix F   Facility Names and Facility Code creation for more details on facility code generation from canonical name.

Errors returned:

[EINVAL]   fname or fcode are NULL

[EINVAL]   fname length is zero, or greater than POSIX_LOG_MEMSTR_MAXLEN

[EEXIST]   fcode generated from fname conflicts with a standard facility code.

 

6.2.3.4.2     Registering Facilities from Kernel space  

 

#include <evl_log.h>

int evl_register_facility( const char *fname, posix_log_facility_t  *fcode )

Computes the facility code as the 32-bit CRC of the canonical equivalent of fname.  If the computed value collides with a standard facility code, and fname is not the corresponding standard name (see 6.2.1        Facility Registry for standard names and codes), return EEXIST; otherwise, set fcode to the computed value.

To ensure that the facility is registered in the facility registry, a special event is logged with facility=LOG_LOGMGMT and event_type=EVLOG_REGISTER_FAC.  evlogd intercepts the event record, and if the facility is not already registered, registers it with the "kernel" parameter set, to prevent logging with this facility from user-space. 

An event record is also generated if the computed value collides with a standard facility code, as described above.  evlogd simply logs the event without taking any other actions. 

See 7.5      Appendix F   Facility Names and Facility Code creation for more details on facility code generation from canonical name.

   Errors returned:

[EINVAL]   fname or fcode are NULL

[EINVAL]   fname length is zero, or greater than POSIX_LOG_MEMSTR_MAXLEN

[EEXIST]   fcode generated from fname already exists in the facility registry.

[ENOSYS]   Event Logging is not configured in the kernel.

[ENOSPC]   The event buffer has run out of space, and the EVLOG_REGISTER_FAC event cannot be logged.

 

#include <evl_log.h>

int evl_gen_facility_code( const char *fname, posix_log_facility_t  *fcode )

If fname is the upper or lower case name of a standard Linux facility, fcode is set to the corresponding facility code.  The standard facility names and facility codes are listed under 6.2.1        Facility Registry.

If fname is not a standard Linux facility, compute the facility code as the 32-bit CRC of the canonical equivalent of fname.  If the resulting code is the same as one of the standard facilities, return EEXIST; otherwise, set fcode to the computed value.

See 7.5      Appendix F   Facility Names and Facility Code creation for more details on facility code generation from canonical name.

Errors returned:

[EINVAL]   fname or fcode are NULL

[EINVAL]   fname length is zero, or greater than POSIX_LOG_MEMSTR_MAXLEN

[EEXIST]   fcode generated from fname conflicts with a standard facility code.

[ENOSYS]   Event Logging is not configured in the kernel.

 

6.2.4        User Commands

 

6.2.4.1        evlconfig - Configure logging daemon

                                                                      

  

SYNOPSIS                                                            

         evlconfig -l|--list                 

         evlconfig -s|--screen filter | nofilter

                        evlconfig –i|--interval seconds

   evlconfig –c|--count events                        

         evlconfig -d|--discarddups on | off

         evlconfig -o|--output severity-level | off

               

                                                                         

DESCRIPTION                                                         

The evlconfig command lets you change the default settings for event logging.   

                                                                         

evlconfig accepts the following options (unless otherwise noted, root permission is required to use these options):

                

 

  -l, --list                                                  

            List current settings for the following:         

               Discarding of duplicate events, enabled or disabled.

               Discarding duplicates time interval and count     

               Event screening

               Console display level

                       

            This option is available to all users.         

 

       

  -s, --screen filter | nofilter                                                 

Specifies a filter name or filter expression for screening-out events.  See Query and Filter Expression Syntax Rules for details.  All events that match the filter are discarded.  All event record attributes from the fixed portion of the event record can be specified.  The default logging behavior is that events logged from the kernel (log_facility==KERN) or logged by root (effective user ID of 'root') are not screened-out and discarded. Also, by default events logged by applications are not screened-out and discarded (unless attempting to log with log_facility==KERN).  Issuing this command replaces the existing screen, if any, and a filter specification of 'nofilter' removes the screen.  Refer to Screening of Events for more information.

 

                                             

        -i, --interval seconds

Sets the time interval for discarding of duplicate events.  The default interval is 3 seconds.  The allowable range is from 1 to 3600 (1 hour).  If this parameter is non-0, but count is set to zero, then discarding of duplicates will be based strictly on time interval, and event count will be ignored.  If interval and count are both equal to 0, then no duplicates will be discarded (all events will be logged).  Refer to Discarding duplicate events for more information.      

 

  -c, --count events

Sets the event count for discarding of duplicate events.  The default count is 100 events. The allowable range is from 1 to 10000.  If this parameter is non-0, but interval is set to zero, then discarding of duplicates will be based strictly on event count, and time interval will be ignored.  If interval and count are both equal to 0, then no duplicates will be discarded (all events will be logged).  Refer to Discarding duplicate events for more information.

 

  -d, --discarddups on | off                                                 

Enables or disables the discarding of events that are being logged in rapid succession.  Default setting is 'on'.  This parameter is stored in  /var/evlog/evlog.conf.  Refer to Discarding duplicate events for more information.

 

  -o, --output severity-level | off

Controls displaying of kernel events on the system console.  Either specifies the severity-level(s) of events to be displayed on the console, or turns displaying completely off.  The default setting is "off".  Valid severity-levels are EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO, DEBUG.  Specifying a severity-level of CRIT, for example, will cause events with severity-level of CRIT and higher (ALERT and EMERG) to be displayed on the system console.

 

This option utilizes the same system call as the klogd command with the -c option.

Events forwarded from printk will not be displayed, since they would be duplicates of messages already displayed from printk.

 

For all displayed events, the facility, event type, and format (STRING, BINARY or NODATA) will be displayed.  For events with log_format of POSIX_LOG_STRING the formatted string will also be displayed.  For events with log_format of POSIX_LOG_BINARY up to the first 16 bytes of variable data will be displayed in hex. 

 

Examples:

 

F00001000:T3C9D9A1B:S:This is an example of an event with log_format of STRING.

FFFEA2000:T00000015:B:<11223344 AABBCCDD 55667788 99AABBCC ...> 231 more bytes

F20002000:TACDBE016:B:<3243632C DAB>

F00000300:TAAB7E165:N:<No data> 

 

F indicates Facility (hex), T indicates Event type (hex), S indicates STRING, B indicates BINARY, N indicates No Data.

 

           

   EXAMPLES

 

      evlconfig --list

 

            displays the following:

                 

                  Discard_dups = on

                  Discard interval = 3 seconds

                  Discard count = 10 identical events

                  Event Screen: 

                    uid!="root" && severity=DEBUG

                  Console display level = CRIT

                   

The event screen in this example indicates to log DEBUG events only from root.  All other DEBUG events are discarded.

 

 

         FILES

                                                               

        /var/evlog/evlog.conf         evlogd Configuration file

        /var/evlog/eventlog           Standard Event Log

        /var/evlog/privatelog         Private Log

  /var/run/evlogd.pid           evlogd Process ID   

                                                          

                                             

 

6.2.4.2       evlfacility - Manage Facility Registry

 

SYNOPSIS                                                            

        

         evlfacility -l|--list

         evlfacility -v|--verify [file]  

         evlfacility -r|--replace file

         evlfacility -a|--add facility-name [-k|--kernel]

            [-p|--private] [-f|--filter filter]

         evlfacility -d|--delete facility-name

         evlfacility -c|--change facility-name [-k|--kernel] | [-u|--user] |

      [-p|--private] | [-n|--noprivate] |

            [-f|--filter filter | nofilter ]

        

 

                                                                        

DESCRIPTION                                                         

The evlfacility command lets you list contents of the event logging facility registry, replace the entire facility registry, add facility (with options) to the facility registry, delete facilities, or modify an existing facility.  See Facility Registry for more details.

 

For evlfacility options that modify the facility registry, event logging applications already in progress will start using the modified registry within 5 seconds.  The following options are accepted (unless otherwise noted, root permission is required to use these options):

              

 

        -l, --list

Displays the facility names and associated integer values contained in the facility registry, /var/evlog/facility_registry.  Also displays whether or not the facility logs events from the kernel, which events, if any, are written to the /var/evlog/privatelog file, and which events have restricted logging.  See Restricted Logging for details.

 

This option is available to all users.

 

  -v, --verify [file]

Checks the validity of the indicated file and reports any errors found to stderr.  If no file is specified, then the contents of the facility registry file, /var/evlog/facility_registry, are checked for validity.

             

  -r, --replace file

Checks the validity of the indicated file and reports any errors found to stderr.  If no errors are found, then the contents of the facility registry file, /var/evlog/facility_registry, are replaced by those of the indicated file. 

 

  -a, --add facility-name  [-k|--kernel]

[-p, --private][-f, --filter filter]

Adds an entry to the facility registry for the indicated facility-name.  A facility-value is automatically assigned. 

 

If --kernel is specified, it indicates that this facility will log events from the kernel.  Otherwise, events will be logged from user-space.

 

If --private is specified, then events logged with the specified facility will be logged to the private log file, /var/evlog/privatelog, instead of the standard log file, /var/evlog/eventlog.

 

If a filter is specified, it indicates that for this facility, only records that match the indicated filter will be logged.  Only attributes in the fixed-portion of the event record may be used in the filter expression. See Query and Filter Expression Syntax Rules and Restricted Logging for more information.

 

  -d, --delete facility-name

Deletes an entry from the facility registry for the specified facility-name. 

 

        -c, --change facility-name [-k|--kernel] | [-u|--user] |

           [-p|--private] | [-n|--noprivate] |

           [-f|--filter filter | nofilter ]

Modifies one or more of the optional parameters associated with facility-name in the facility registry.

     

  -k, --kernel

Adds the "kernel" parameter for the specified facility-name in the facility registry.

      This option is not valid with --user.

 

  -u, --user

Removes the "kernel" parameter for the specified facility-name in the facility registry.

This option is not valid with --kernel.

 

  -p, --private

Adds the "private" parameter for the specified facility-name in the facility registry.  

This option is not valid with --noprivate.

 

  -n, --noprivate  

Deletes the "private" parameter for the specified facility-name in the facility registry.

This option is not valid with --private.   

 

  -f, --filter filter | nofilter

Adds the specified restricted logging filter for the specified facility-name in the facility registry.  If "nofilter" is specified, then any existing filter is removed.  See Query and Filter Expression Syntax Rules and Restricted Logging for more information.

 

 

   EXAMPLE

 

evlfacility --add "Mr Admin" --private --filter 'log_format!=BINARY && gid="admins"'

 

Adds facility "Mr Admin" to the facility registry.  Events from this facility will be logged to the private log.  BINARY events will not be logged (only variable-length data formats of NODATA or STRING), and events will be logged only if group id is "admins".           

 

         FILES

                                                              

        /var/evlog/facility_registry  Facility registry         

 

 

                      

6.2.4.3        evlsend -  Event generation command                            

                                                                        

SYNOPSIS

                                                         

     evlsend     -f|--facility facility –t|--type event-type

[-s|--severity severity]            

[-m|--message message-string]

[-b|--binary attr-type attr-value ...]                    

                                                                

                                  

                                                                        

DESCRIPTION                                                             

     The evlsend command lets you send an event message to the system.                                                             

                                                                        

evlsend accepts the following options (available to all users):               

                                                                     

        

-f, --facility facility

Facility to record in the event record.  This option must be specified, and the facility must be defined in the Facility Registry.

 

-t, --type event-type

Specify the event type to record in the event record.   This option must be specified.

                                                

-s, --severity severity

Severity to record in the event record.  If this option is not specified, then the default severity is INFO. Valid severity values are those defined in the POSIX standard.   

      

      -m, --message message-string

Specifies that the variable data format is POSIX_LOG_STRING and logs the message.  Not valid with the --binary option.    

 

-b, --binary attr-type, attr-value [, . . .]

Specifies that the variable data format is POSIX_LOG_BINARY.  Not valid with the --message option.  attr-type and attr-value must both be specified, and multiple pairs of these 2 parameters can be specified.  This command uses values from the Table of Variable Data Types and Format Specifiers used with formatting templates under  Attribute Format  for valid attr-types.   

 

                                                                      

  EXAMPLES                           

 

      Logging a string:

                               

evlsend -f LOCAL3 -s INFO -t 61 -m "Log this string"      

 

Logging binary data:

 

evlsend --facility LOCAL5 --type 65 --binary uchar 0x22 string "Log this string too, but use default severity."                                 

                                         

                                                               

  FILES                                                               

            /var/evlog/eventlog           Standard Event log        

            /var/evlog/privatelog         Private Event log 

                                              

                                                                             

                                                                          

6.2.4.4    evlview - View log events

 

SYNOPSIS

       evlview --help

 

        OR

 

       evlview [ input] [ output ] [ -f | --filter filter ]

        [ -b |  --templates ] [ -B | --notemplates ]

 

       input    (defaults    to    /var/evlog/eventlog,   or   to

       /var/evlog/privatelog with -p | --private):

        [ -n | --new ][ -T | --timeout nsec ][ -R | --recid rid ]

         OR

        [ -l | --log srclogfile] [ -t | --tail nrec ]

        [ -r | --reverse ]

 

       output (defaults to stdout):

        [ -o | --out destlogfile ]

         OR

        [ -S | --formatstr format-string ] [ format_opts ]

         OR

        [ -F | --formatfile format-file ] [ format_opts ]

         OR

        [ -c | --compact ] [ -s | --separator sep ] [format_opts]

         OR

        [ -m | --syslog ]

 

       format_opts:

        [ -N | --newlines n ] [ -d | --datefmt date-format ]

 

DESCRIPTION

       The evlview utility lets you view events from an event

       log,  view  events  in  real time, or read records from an

       event log and write the records to another file.

 

OPTIONS

       -n, --new

              Display only new events  as  they  are  logged.  By

              default,  events are read from the entire event log

              until the end of the log is reached. This option is

              not  valid  when  --log  specifies  an inactive log

              file.

 

       -T, --timeout nsec

              Specifies the interval in seconds that  the  viewer

              should  wait for the next event to be generated. If

              this interval passes with no new events, the viewer

              terminates.  The  interval  restarts  with each new

              event. By  default,  with  the  --new  option,  the

              viewer  runs  until  it  is  killed. This option is

              valid only when the --new option is used.

 

       -R, --recid rid

              Valid  only  with  --new.   Before  displaying  new

              records,  display  the  end  of  the  existing log,

              starting with the first record whose ID is  greater

              than or equal to rid.

 

       -l, --log srclogfile

              Specifies  the name of an alternate log file as the

              source of events -- for example,  the  private  log

              /var/evlog/privatelog. Events read from the private

              log file can be read only by users with the  appro­priate

  read  permission.   If  this  option is not

              specified, events are read from the  active  system

              log, /var/evlog/eventlog.

 

       -p, --private

              Equivalent to --log /var/evlog/privatelog.

 

       -t, --tail nrec

              Specifies  that  evlview  should read the last nrec

              records in the event log file. If a filter is spec­ified,

              then  the  last  nrec records are read that

              match the filter.

 

       -r, --reverse

              Read events in reverse  order,  starting  with  the

              most  recently  written  event.  Default is to read

              starting with the oldest event in the event log.

 

       -o, --out destlogfile

              Specifies that event records should be appended  to

              the  specified  destlogfile  instead  of being displayed

  to stdout. This option is not valid with the

              --formatstr,  --formatfile, --compact, --separator,

              --datefmt, --newlines, or --syslog options.

 

       -S, --formatstr format-string

              Specifies an alternative format for events that are

              displayed (see Example 3).

 

              For  the fixed portion of the event record, members

              are referenced by the attribute  names  defined  in

              the    POSIX   standard:   recid,   size,   format,

              event_type, facility,  severity,  uid,  gid,  pgrp,

              time, flags, thread, and processor.

 

              An  additional  attribute is available, host, which

              displays the local hostname.

 

              For log_format of STRING, %data% displays the

  variable-length data as the data string.

 

              For  log_format  of  NODATA, %data% displays a NULL

              string.

 

              For log_format of BINARY, %data% displays the vari­able 

  length  data according to the associated for­

              matting template, if any, or  in  hex  dump  format

              otherwise.

 

              If  log_format  is BINARY and a formatting template

              exists for the event record, optional attributes in

              the  variable-length  portion  can be referenced by

              attribute name as defined in  the  formatting  tem­plate.

  However,  the  formatting  string  (if any)

              specified in format-string is used instead  of  the

              formatting specification from the template.

 

              If  this option is not specified, then default formatting

  is used.  This option is not valid if specified  along

  with  --out, --formatfile, --compact, --separator, or --syslog.

 

       -F, --formatfile format-file

              Performs the same actions as --formatstr,  but  the

              alternative  format  is read from format-file. This

              option is not valid if specified along with  --out,

              --formatstr, --compact, --separator, or --syslog.

 

       -c, --compact

              Specifies  that  contents  of  the event record are

              displayed in a compact form. In compact  form,  the

              attribute names for attributes in the fixed portion

              of the event record are  not  displayed,  only  the

              values.   This option cannot be used with --format­

              str, --formatfile, --syslog, or --out.

 

       -s, --separator sep

              Specifies that the character string sep be used  as

              the  separator  between attributes displayed by the

              viewer. The default separator is ",".  The  separator

  string  cannot  exceed  20  characters.   This

              option is not valid with --formatstr, --formatfile,

              --syslog, or --out.

 

       -N, --newlines n

              When  displaying  records,  ensures  that there are

              exactly n newlines between records.   For  example,

              -N 2 gets you exactly 1 blank line between records.

              n must be greater than zero.  If a record  ends  in

              more than n newlines, then an appropriate number of

              those newlines will be omitted  from  the  display.

              If  this  option  is  omitted, evlview ensures that

              there is at  least  one  newline  between  records.

              This option is not valid with --out or --syslog.

 

       -d, --datefmt dateformat

              Format  the  log_time  attribute  according  to the

              dateformat string, which is  passed  to  the  strf­time(3)

  function.   The  default  format  is "%c".

              This option is not valid with --out or --syslog.

 

       -m, --syslog

              Approximate the output  format  of  the  syslogd(8)

              daemon: for each record displayed, print the times­

              tamp, host name, and message.  For multi-line  messages,

  BINARY-format  events, and events formatted

              by formatting templates, the output  may  not  look

              much like syslogd output.  This option is not valid

              with the --out, --formatstr,  --formatfile,  --compact,

              --separator,   --datefmt,   or   --newlines options.

 

       -f, --filter filter

              Specifies a filter (query) expression. Only  events

              matching  the  filter  are displayed.  See

              6.6      Query and Filter Expression Syntax Rules

  for more information.

 

       -b, --templates

              Forces non-standard attribute names to be  accepted

              in the filter expression supplied with the --filter

              option, as well as the format  specified  with  the

              --formatstr  or  --formatfile option.  A "non-stan­dard"

  attribute is one  defined  via  a  formatting

              template  rather  than  in the fixed portion of the

              event record.  An additional non-standard attribute

              is  available, host, which displays local hostname.

              For a particular event, if the named attribute does

              not  exist,  it  will  format as a null string, and

              references to it  in  the  filter  expression  will

              evaluate to false.

 

       -B, --notemplates

              Specifies  that  the  evlview  command  should  not

              attempt  to  locate   formatting   templates.    By

              default,  evlview  will  attempt  to use formatting

              templates when displaying records.

 

       -h, --help

              Displays the usage statement.

 

EXAMPLES

       Example 1.

              evlview --filter 'facility==USER && data contains

                 "interface reset"'

 

              might produce the following output (if there are  2

              matching events in the log):

 

              recid=7214, size=31, format=STRING, event_type=0x3, facility=USER,

              severity=ERR, uid=bill, gid=appdev, pid=2753, pgrp=44,

              time=Mon Jun 18 19:32:31 2001, flags=0x0, thread=0x0, processor=1

              Eth/0 interface reset by user

 

              recid=8612, size=31, format=STRING, event_type=0x3, facility=USER, 

              severity=ERR, uid=bill, gid=appdev, pid=2753, pgrp=44,

              time=Wed Jun 20 14:32:31 2001, flags=0x0, thread=0x0, processor=1

              Eth/1 interface reset by user

 

              Note  that  the  date  and time format shown in the

              examples is based on the LANG environment  variable

              not  being  set  (or  being set to "C").  For other

              settings, the format will differ.  For example:

 

                   $export LANG=es_MX    (Spanish, Mexico)

 

              might result in a display of:

 

                   lun 04 feb 2002 11:52:18 PST

 

              Also, see Example 6 for additional date formatting options.

 

       Example 2.

              evlview -f 'facility==LOCAL1 && data contains

              "Eth/0 interface"' --compact -s !

 

              might produce the following:

 

              7214!31!STRING!0x3!LOCAL1!ERR!bill!appdev!2753!44!

              Tue Jun 19 19:32:31 2001!0x0!0x0!1

              Eth/0 interface reset by user

 

       Example 3.

              evlview -b -f 'facility==LOCAL1 && event_type==0x3115 && lun=0x3'

              -S "Logical unit number is 0x%lun:x%\nfor facility %facility%

              and event type of %event_type:d% decimal, %event_type% hex\n"

 

              might produce the following:

 

              Logical unit number is 0x3

              for facility LOCAL1 and event type of 12565 decimal, 0x3115 hex

 

              Note that the -b  option  allows  the  non-standard

              attribute  "lun" to be included with the -f (--fil­

              ter) option.

 

              Also, note that due to the length of the formatting

              string,  use  of  the  --formatfile option would be

              preferable in practice instead of the -S or format­

              str option.

 

       Example 4.

              evlview -f 'age < "2h"'

 

              would  display  all events logged during the past 2

              hours.

 

       Example 5.

              lastrid=`cat /var/evlog/bootrecid`

              nextrid=`expr $lastrid + 1`

              evlview -n -R $nextrid -f 'flags & printk'

                 --syslog >> /var/log/printks

 

              would    run     continuously,     appending     to

              /var/log/printks  all  messages  logged by the kernel's

  printk() function, starting  with  the  first

              message after the current boot.  The message format

              is that of the syslogd daemon.

 

       Example 6.

              evlview -b -S "%time% %host% %facility% %severity%

                 %event_type%"  --datefmt "%A %B %d %l:%M:%S %p"

 

              might display the following:

 

                 Tuesday June 4  1:29:26 PM elm3b99 KERN NOTICE 0x2ffe11ac

                 Tuesday June 4  1:29:26 PM elm3b99 KERN ALERT 0x5818f89e

                 Tuesday June 4  1:29:26 PM elm3b99 LOGMGMT INFO 0x28

 

              and demonstrates the use of  the  --datefmt  option

              and %host%.

 

FILES

       /var/evlog/eventlog              Standard Event log

       /var/evlog/privatelog            Private log

 

NOTES

       When evlview is interrupted by a log-maintenance operation

       (e.g., when evlogmgr runs), evlview waits until the operation

       completes  and  then picks up where it had left off.

       This is intended to work even if the portion of  the  file

       where  evlview  was  reading is deleted during log maintenance. 

       If a timeout interval is specified with --timeout,

       and  the timeout expires while evlview is waiting for completion

       of the log-maintenance operation,  evlview  terminates with an

       error message.

 

 

           

 

 

6.2.4.5       evltc - Compile formatting templates

 

SYNOPSIS                                                                 

                       

      evltc sourcefile [-f|--func] [-n|--noto] [-c|--cpp] [cpp_options]

      or

      evltc binfile.to                                                 

                                                                         

DESCRIPTION                                                             

The evltc command reads the formatting template specification(s) in sourcefile and creates a binary template file for each specification.  sourcefile may not define two templates with the same event_type, even if for different facilities.  Binary files are created in the directory where sourcefile resides.

 

If the name of the specified file ends in ".to", it is assumed to be a binary template file.  It is read, and if it contains an event-record template, the corresponding sample call to the evl_log_write() function is printed, as with -f.  In this case, the -f and -n options (if specified) are ignored, and any cpp-related options are flagged as errors.

 

The binary file for an event-record template is named “eventtype.to”, where eventtype is the decimal event type.  If eventtype is negative, the minus sign (-) is converted to an equals sign (=).

 

The binary file for a struct template is named “structname.to”.

 

If the source file contains any errors, no binary files are produced, and error messages are written to stderr.

 

The algorithm for finding a struct template that is referenced by another template is described under More on Importing Templates in the description of a template source file.

 

evltc accepts the following options (available to all users):

                                                                           

        -f, --func

When this option is specified, a sample call to the evl_log_write() function is printed for each event-record template in the specified file.  Such a call could be used to log an event record whose format matches the template. 

                                                                            

        -n, --noto

Compile the template source and report errors as appropriate, but do not write out the binary template file(s).

                                                                                            

        -c, --cpp

Run sourcefile through the C preprocessor, /usr/bin/cpp, and compile the result.  The contents of sourcefile are unchanged.

 

        -D macro[=defn]

Passed to the C preprocessor.  Implies -c.

 

        -U macro

Passed to the C preprocessor.  Implies -c.

 

        -I dir

Passed to the C preprocessor.  Implies -c.

                                

EXAMPLES                

 

Example 1. 

                                            

Suppose the file VolMgr.t contains the following text.

/* Start of first template */

struct sourceInfo;

attributes {

      string sourceFile;  int lineNumber;

}

format

%sourceFile%: %lineNumber%:

END

/* Start of second template */

facility "VolMgr"; event_type 456;

attributes {

      struct sourceInfo srcInfo;

      string volumeName;  ulong vsize;

}

format

%srcInfo%

Created volume %volumeName% with size %vsize%.

END

/* Start of third template */

facility "VolMgr"; event_type 789;

attributes {

      struct sourceInfo srcInfo;

      string diskName;  string diskGroup;

}

format

%srcInfo%

Added disk %diskName% to disk group %diskGroup%.

 

The command

       evltc VolMgr.t

will create three files, sourceInfo.to, 456.to, and 789.to in the same directory as VolMgr.t 

 

 

Example 2.

 

      Given the following formatting template, stored in the file SCSIadap.t:

 

      /* HEADER SECTION */

facility "LOCAL1";

event_type 0x3115;

/* CONST-ATTRIBUTES SECTION */

const {

      string      repair_action = "Replace SCSI adapter";

}

/* RECORD-ATTRIBUTES SECTION */

attributes {

      char        unit_ser_no[8]          "(%c)";

      ushort      lun                     "%u";

      char        sense_bytes[12]         "%t";

/* For the next attribute, the various segments of the format string are

 * automatically concatenated into a single string.

 */

      uchar       recovery_stat     "%b/0x40/INTERFACE_WAS_RESET/"

                                    "0x20/RECOVERY_ACTION_STARTED/"

                                    "0x10/RECOVERY_ACTION_FAILED/";

/* The final attribute specification says to display the rest of the

 * bytes in dump format.

 */

      char        extra_data[_R_]   "%t";

}

/* FORMATTING SECTION */

format

SCSI interface error: Adapter Serial Number/LUN = %unit_ser_no%/\

%lun%

 

\tRecovery Status: %recovery_stat%

\tSense Bytes:

%sense_bytes%

     

\tRecommended repair action:

\t\t%repair_action%          

 

%extra_data%

 

The command

       evltc SCSIadap.t -f

will create the file 12565.to in the same directory as SCSIadap.t and the following will be displayed (on stdout):

 

evl_log_write(LOG_LOCAL1, 0x3115, severity, flags,

      "char[]", 8, unit_ser_no,

      "ushort", lun,

      "char[]", 12, sense_bytes,

      "uchar", recovery_stat,

      "char[]", _R_, extra_data,

      "endofdata");

 

 

 

  FILES                                                                 

       /var/evlog/templates       Formatting template repository.

                                                       

                                                                 

6.3                Filtering of Event Records

 

There are no plans to implement this feature.

 

A filter registry file /var/evlog/filter_registry, if it exists, contains entries associating filter names     with filter expressions, separated by a comma.  For example:

                               

                ifres,    facility==LOCAL1 && data contains "interface reset"

               

associates the name "ifres" with the filter expression shown. When a user issues a command and specifies the -filter option (or -screen option), either a full filter expression can be specified or a filter name which is defined in the /var/evlog/filter_registry, and the associated filter expression will be applied.

 

In addition, a user can define an environment variable FILTER_REGISTRY specifying a pathname for a user-created filter registry.  When a command is issued with the -filter option, the command will first check the filter registry specified by FILTER_REGISTRY, if one exists, and if the filter name is not found, /var/evlog/filter_registry will be checked (if it exists).  If the filter name does not exist in the either place, the command will fail.

 

It should be noted that the term "query" in the POSIX standard is synonymous with the term "filter" used in this document.   Also note that in addition to attributes defined in the POSIX standard, an additional pseudo attribute can be used -- age>"n" or age<"n", where "n" is a numeric value followed by an optional qualifier.  If  "n" is a number followed by the letters 's', 'm', 'h', or 'd', then "n" indicates the number of seconds, minutes, hours, or days, respectively.  If only a numeric value is specified for "n", then it indicates "n number of days".

 

.

6.4          Event Notification
                                                         

There are 2 separate daemons associated with event notification.  A high-level description of each of the daemons is followed by a more detailed design description. 

 

6.4.1        Overview

 

evlnotifyd provides the basic registration mechanism for event notification, monitors the event log and private log for events that match the notification criteria, and notifies the appropriate client(s) when there is a match.  

 

When a client successfully registers, evlnotifyd records the request in its internal list of notifications.  A registration will fail if the user associated with the registration does not have read permission for either the event log (/var/evlog/eventlog) or the private log (/var/evlog/privatelog).

 

When an event is logged that matches a particular registration, evlnotifyd sends notification to the client.  The client then performs some action in response to the notification (for example, execute a command or shell script).

 

 

 evlactiond is one of evlnotifyd's clients, and provides support for the evlnotify - Event Notification command.  During bootup, it reads entries from the persistent action registry (/var/evlog/action_registry) and registers with the evlnotifyd daemon to receive notification of the indicated events. 

 

Additional notifications may be registered, modified, or deleted each time that the evlnotify command is executed from the command line or shell script, depending upon whether or not the user has the required permissions.

 

When evlactiond receives a notification from the evlnotifyd daemon, it determines which notify_action to execute. The notify_action is an arbitrary command line or script.  The command line may contain %recid% which will be replaced by the matching record's id.  The evlactiond which executes the notify_action does not wait for the it to complete.  This may require that the notify_action re-entrant, depending upon its purpose.

 

 

6.4.2        Detailed Design

Appendix D siginfo.h header file may be a useful reference when reading this section.

6.4.2.1       evlnotifyd  Server Design

The notification server, evlnotifyd,  is a daemon that

  1. accepts notification requests from client processes;
  2. reads event records as they are logged; and
  3. signals client processes when events of interest are logged.

 

The evlnotifyd daemon does not execute commands associated with events.  The action daemon evlactiond , which is a client of this notification daemon, does that.  See  evlactiond Action Daemon for details.  Also, this section describes signal-based notification (where sigev_notify is set to SIGEV_SIGNAL).  See Threads-Based Notification for a description of threads-based notification.

 

 evlnotifyd's general algorithm is as follows:

  1. Do whatever forking, file-descriptor fussing, etc. is necessary to make us a well-behaved daemon with file descriptors 0-2 mapped to stdin, stdout, and stderr, respectively. 
  2. Open a socket to evlogd and read new events via the socket as they are also being written to the event log or private log.
  3. Create a socket, bind it to a well-known pathname, and listen() for client connection requests on that socket.
  4. Run select() so that we block until one of the following events occurs:

·         There’s a new record to be read from evlogd.

·         There’s activity on the “listen” socket – i.e., a client process has executed a connect() request for that socket.

·         There’s activity on one of the client sockets – specifically, the client is sending a request or has closed the socket.

  1. Take the indicated action(s):

·         If a new record has been logged, read it and determine which notification requests, if any, are enabled and match this record.  For each such request, use Linux’s rt_sigqueueinfo system call to send the appropriate signal and siginfo object to the indicated process.  Also, based on the flags argument passed to posix_log_notify_add():

                                                                           i.      If POSIX_LOG_ONCE_ONLY is set - remove request after first notification is sent.

                                                                          ii.      If POSIX_LOG_SEND_RECID is set - client can call posix_log_siginfo_recid() to obtain associated record id.

 iii.      If POSIX_LOG_SEND_SIGVAL is set - the value of notification->sigev_value passed to posix_log_notify_add() is returned to the client as si_value in the sigval struct arg passed to rt_sigqueuinfo().

                                                                        iv.      Any combination of the above flags is allowed.

·         Members of the siginfo structure are set as follows:

·         si_signo is set to the signal value passed by the client when registering.

·         IF POSIX_LOG_SEND_RECID is set, si_errno is set to the matching log_recid value

·         si_code is set to SI_QUEUE.

·         If POSIX_LOG_SEND_SIGVAL is set, si_value is set to a client-defined value which was passed by the client when registering.

·         If a client is trying to connect on our “listen” socket, execute accept() on that socket to create a new socket that is connected to the client’s socket.  Add that new socket to the list of file descriptors to be monitored by select().

·         If there is a message on a client socket, then process that message.  The most interesting message is a new notification request, which is discussed in some detail below.  Other messages are discussed under “Client-Server Conversations.”

  1. Go to step 5.

 

6.4.2.1.1        Processing a New Notification Request

A notification request from a client contains the following information:

a)       The text of the query (filter) that specifies what type of event record should trigger notification.  Null queries are permitted; they match all records.

b)       The sigevent object, which specifies which signal to send to the client and what si_value to send along with it.  The following fields in sigevent are set as follows:

o        sigev_value may be set to client-defined value

o        sigev_signo is set to signal number (in range 32-63)

o        sigev_notify is set to SIGEV_SIGNAL. 

c)       One or more flags:  POSIX_LOG_ONCE_ONLY, POSIX_LOG_SEND_RECID, POSIX_LOG_SEND_SIGVAL.

 

 

Given this info, the server performs the following steps:

·         evlnotifyd saves it's uid, gid, and groups

·         evlnotifyd sets its uid, gid, and groups to the client's uid, gid, and groups

·         evlnotifyd attempts to open private log.  If successful, client's request is granted.  If unsuccessful, attempt to open standard event log.  If successful, client's request is granted.  If unsuccessful, client's request is denied.

·         evlnotifyd restores it's save uid, gid, and groups.

 

6.4.2.2        Client Design

The posix_log_notify functions, or “client-side notification functions”, share a data structure used as a  "notification list".  The notification list contains a “notification record” for each successful call to posix_log_notify_add().  posix_log_notify_remove() removes the specified notification record from the notification list.

6.4.2.2.1        posix_log_notify_add()

After validating its args, this function sends a nmtNewRequest message (see Types of Messages) to the server.  (If this is the first request, we must first connect() to the server.)  Assuming the server accepts the request, we create a notification record -- containing all the info we’ll need to respond to subsequent operations on this notification record by posix_log_notify_get() and posix_log_notify_remove() – and add it to the notification list.

 

Note that the client must mark its socket as close-on-exec, since POSIX says all of a process’s notification requests are deleted when the process execs.   However, the preferred client behaviors are to (1) call posix_log_notify_remove() to explicitly remove a notification request and (2) call fork() and have the child call exec(), which does not remove the parent's notification.

 

If the evlnotifyd dies, then it must re-establish its list of notifications when it is restarted.   First, it reads the data from the file where the notification requests were backed-up.  It then verifies that the process ids, and corresponding procCmd strings, are still active.  If any are not active, or the process id is found but the procCmd string is different, then their notification requests are removed.  This ensures that a different process does not have the same process id as one which originally registered for notification.  

 

After evlnotifyd dies and is restarted, previously established sockets between evlnotifyd and its clients are lost.  As a result, evlnotifyd will check that the process which it is about to send notification to is still active by checking that its process id and procCmd string both match the process which registered.  If both do not match, then the registration is removed from the list, and notification is not sent. 

 

 

6.4.2.3       Client-Server Conversations

6.4.2.3.1        Types of Messages

 

 

All messages sent by the client should be the same length, to make server-side processing easier.

 

6.4.2.3.2        Creating a Notification Request

 

The nmtNewRequest message can be of fixed length even though the query string can be arbitrarily long.  The nmtNewRequest message could contain the length of the query string.  After getting that length out of the nmtNewRequest  message, the server would read that many bytes from the client.  The server will wait for the query string in the next select call.

6.4.2.3.3        Getting the Status of a Notification Request

Client sends a nmtGetRequestStatus request.  Server sends a nmtRequestStatus message.  Status on success is nrsEnabled or nrsDisabled.  If server can’t find such a request, status is nrsNoRequest.

6.4.2.3.4        Removing a Notification Request

Client sends a nmtRmRequest request.  Server sends a nmtRequestStatus message.  Status is either nrsRemoved (success) or nrsNoRequest.

 

6.4.2.4       evlactiond Client

The evlactiond daemon provides support for the evlnotify - Event Notification command.

 

6.4.2.4.1        Registering for event notification

Whether a notification request is received via the evlnotify command, or read from the persistent action registry (/var/evlog/action_registry), the user that is attempting to register must have access to at least one of the 2 log files.  In addition to verifying that the user has read access to at least one of the 2 log files, an additional check is performed using a mechanism similar to the 'crontab' command:

·         If the file /var/evlog/notifyreg.allow exists, then users must be listed therein in order to register a new notification, modify an existing notification, or delete a notification, or list notifications.

·         Otherwise, if the file /var/evlog/notifyreg.deny exists, but notifyreg.allow file does not exist, then users that are listed therein will not be allowed to add, modify, delete, or list notifications.  All others will be allowed.

·         If neither the .allow or .deny files exist, then all users can add , list, or modify/remove notifications.

Note that notifications can only be modified or deleted by the users that created them.

 

evlactiond passes the following values to posix_log_notify_add():

·         The query arg contains the query object returned by posix_log_query_create()

·         The notification arg (sigevent struct) contains the following:

o        sigev_value is set to a value when combined with sigev_signo, uniquely identify this request.

o        sigev_signo is set to a value between  32 an 63, when combined with the value of sigev_value, uniquely identify this request.

o        sigev_notify is set to SIGEV_SIGNAL

·         The flags arg is set as follows:

o        POSIX_LOG_SEND_RECID and POSIX_LOG_SEND_SIGVAL are always set

o        POSIX_LOG_ONCE_ONLY may be set

 

6.4.2.4.2        Processing an event notification

Whenever notification is received by evlactiond, it examines si_signo and si_value (from the siginfo struct) to identify which user's notify action to invoke.

When the evlactiond daemon launches a command line in response to a notification, it does not wait for the command/script to complete before continuing.  If there’s a possibility that the command/script won’t complete before it’s launched again, it should be “re-entrant” or it should be set POSIX_LOG_ONCE_ONLY.  (It can re-register itself as it finishes if it’s once-only.)

 

The command line can provide at least %recid% (which would be replaced by the record’s ID).  The user will be able to determine where the event was written as follows:

For example, if 3 events are logged to the standard event log, then 3 are logged to the private event log, then 3 more to the standard event log, they might be numbered as follows:  1,3,5,6,8,10,11,13,15.

 

Similar substitutions of other attributes in the fixed portion of the event record could be provided, but the evlactiond daemon would need to read the event record to get that information.  This design assumes that the record id is sufficient since the user can easily read the event record from the log.

 

The command line will be executed as follows:

 

The command line will always be executed with the user ID/group ID of the user that registered the action.  If the user is root, it can specify other uids.

 

Default environment variables and working directory will be stored into a default "profile" (/var/evlog/action_profile) which can be edited by the System Administrator.  The variables can then be modified by the action command or script, if desirable.

 

stdin is always /dev/null, and stdout and stderr defaults to /dev/null, but can modified with the action command or script.

 

 

6.4.2.5       Threads-Based Notification

Previous sections do not address thread-based notification -- i.e., what do we do if the value of sigev_notify is SIGEV_THREAD in the sigevent object passed to posix_log_notify_add()? 

 

One possible implementation is to have the client-side notification API dedicate one signal number (and signal handler) to thread-based notification.  When posix_log_notify_add specifies a sigevent with a sigev_notify of SIGEV_THREAD, the API code saves a copy of that sigevent and makes up a new sigevent to send to evlnotifyd.  That sigevent would specify a sigev_notify of SIGEV_SIGNAL and the dedicated signal number.  To evlnotifyd, this would look like any other signal-based notification request.  Arrival of a matching event would cause the dedicated signal handler in the client process to be invoked via the usual mechanism.  That handler would in turn call pthread_create(), passing it the appropriate start-routine, sigval*, and thread attributes from the original sigevent.

 

A signal number must be "dedicated", and the user's code would have to avoid using that signal.

 

 

 

6.4.3        API Functions

All are described in the POSIX standard

 

6.4.4        User Commands

6.4.4.1       evlnotify - Event Notification

            

SYNOPSIS 

evlnotify –l|--list                   

      evlnotify –a|--add notify-action [-o|--once-only] [-f|--filter filter]

   [-p|--persistent] [-u|--uid userid]                              

      evlnotify –d|--delete notify-id ...                  

      evlnotify –c|--change new-notify-action notify-id                  

      evlnotify –F|--file cmd-file 

 

                                                                      

DESCRIPTION    

                                                     

The evlnotify command lets you register actions to be taken when a specified event occurs.  An action (command or shell script) will be executed on behalf of the user who registered it, except that if user is “root”, root has the option of specifying an alternate user id (other than “root”).

 

The default environment settings are specified in /var/evlog/action_profile, which can be modified only by root.  The action command or script can alter its environment.  The initial default is as follows:

 

            PATH=/usr/bin:/bin:. 

PWD=/tmp

               

A user attempting to issue this command must have access to at least one of the log files (/var/evlog/eventlog or /var/evlog/privatelog).  In addition to verifying that the user has read access to at least one of the log files, an additional check is performed using a mechanism similar to the 'crontab' command:

·         If the file /var/evlog/notifyreg.allow exists, then the users listed therein can issue this command.

·         Otherwise, if the file /var/evlog/notifyreg.deny exists, but the notifyreg.allow file does not exist, then users listed therein will not be allowed to issue this command.  All others will be allowed.

·         If neither the notifyreg.allow nor notifyreg.deny files exist, then all users can issue this command.

Note that notifications can only be modified or deleted by the users that created them.

 

      The are no command restrictions for "root".

                                                                     

evlnotify accepts the following options:

 

-l, --list                                          

Lists the currently registered notifications.  The list output consists of the following fields:                   

                                                                     

          Notify Id : filter : action : user id : once-only : persistent

 (once-only=1 if once-only) (persistent=1 if persistent registration)                       

             

For user id of "root", all registered notifications will be listed.  For all other users, only the notifications containing a user id matching that of the user specifying the --list option will be displayed.

                                                        

     -a, --add notify-action [-o|-once-only][-f|--filter filter]

[-p|--persistent][-u|--uid userid]

     

Registers notify-action as the command line to be executed when an event matching the specified filter is logged. The command line may contain %recid% which will be replaced by the matching event record's id.  The evlactiond executes the notify-action but does not wait for it to complete.  This may require making the notify-action script re-entrant, depending upon its purpose.                                                   

                                                                     

            The –-once-only option lets you specify that the action     

            is to be performed only once when the first matching event occurs.     

            The default is for the action to be performed each time a matching

event occurs. 

 

The –-persistent option saves the registration to the /var/evlog/action_registry file, so that when the system reboots, the persistent registrations will be restored.

                 

The --filter option specifies a filter name or filter (query) expression.  Only events matching the filter will trigger the nofify-action.  See Query and Filter Expression Syntax Rules for details.  All event record attributes from the fixed portion of the event record can be specified.                                   

            If no filter is specified, then every new event received is considered a match. 

             

The --uid option is only allowed if user is root. userid specifies an alternative to "root" as the user id which executes the notify-action.

                                                                             

     -d, --delete notify-id ...                                

Removes each of the specified notifications.  For user id of 'root', any registered notifications can be removed.  For all other users, only the notifications containing a user id matching that of the user specifying the --delete option can be deleted.  The notify-id's that the user is allowed to delete can be viewed with the --list command.                                                 

                                                                            

     -c, --change new-notify-action notify-id                               

Changes the action to be taken when an event matches the filter with identifier of notify-id in the action registry.  new-notify-action replaces the existing action.  The notify-id's that the user is allowed to change can be viewed with the --list command.  For user id of "root", any registered notifications can be changed.  For all other users, only the notifications containing a user id matching that of the user specifying the --change option can be changed.

                                               

     -F, --file cmd-file                                                      

Allows you to register actions according to the options stored in the cmd-file. Each line in the file is executed as an option to the evlnotify command, and therefore must conform to the convention and permissions defined for the other evlnotify options.  For example, a typical entry in the file may look like this:

 

  --add '/etc/mail_sysadm %recid%' --filter 'severity==CRIT' --persistent         

                                                                         

                   

          

EXAMPLES                                                                

 

Example 1.

 

evlnotify -a '/etc/mail_sysadm %recid%' -f 'severity=CRIT' -p              

                                                                             

            This example registers an action for subsequent                 

            occurrence of events whose severity is critical.            

            When such an event occurs, the script /etc/mail_sysadm is       

executed, and the record id is passed as an argument.  An entry is also added to /var/evlog/action_registry.

 

 

Example 2.

                                                                                                                                  

  evlnotify --list                                                 

1:severity=EMERG:/sbin/evlview -f 'recid=%recid%' -o /tmp/emerg_log:root:1:1     

      2:severity=CRIT:/home/admin/testscript %recid%:joeusr:0:0

    

                                                                            

      The fields are described above in the description of          

the -list option.  The first item in the list, Notify ID 1, indicates that when an emergency event is logged the /sbin/evlview command is executed with options that will cause the event record to be appended to the /tmp/emerg_log file.  User id is "root".  Since the "once only" indicator is set to '1', this action will take place only once.  Also, since the persistent indicator is set to '1', this indicates that the registration is persistent, meaning that is it read from the action_registry (/var/evlog/action_registry) and restored on every boot-up.                                  

 

Notify ID 2 indicates that when a critical event is logged, /home/admin/testscript is executed.  User id is "joeusr".

 

             

                                         

FILES   

        /var/evlog/eventlog            Standard Event Log

        /var/evlog/privatelog          Private Log                                   

        /var/evlog/action_registry     Persistent Action registry

        /var/evlog/action_profile      Default environment for notify_action       

        /var/evlog/notifyreg.allow     Users allowed to register

        /var/evlog/notifyreg.deny      Users not allowed to register                                                                                          

 

 

6.5      Log Management

 

Two active system-wide logs, stored in binary format, are provided: /var/evlog/eventlog and /var/evlog/privatelog.   A user command is provided so that specific events can be removed from the active event logs, and the space reclaimed, thus helping to limit the maximum size of the active logs.  For example, events of low severity or older than 2 weeks can be deleted and the log file compacted and truncated to reclaim the freed space. 

   The following operations affect the size and/or content of the log:

·         Logging an event advances the write offset.  New event records are always appended to the end of the log file.  This operation increases the size of the event log.

·         Compacting and truncating the log moves undeleted event records toward the beginning of the file, thus reusing space previously occupied by records chosen for deletion, and setting the log's actual size to the new write offset.  This operation reduces the size of the event log.

Compaction and truncation, which is initiated with the "evlogmgr -c" command, performs a significant number of steps to ensure the integrity and availability of event logging during and after the log management operation:

 

1.    Create a query object from the filter expression provided by the user.

2.    Log a "start" event (defined in the POSIX standard as POSIX_LOG_MGMT_STARTMAINT).

3.    Lock the log file.

4.    Create a backup copy of the original log file.  Create a compressed backup copy if the user has specified that option.

·         If there is insufficient space to create a backup, and the --force option is not specified, the log file is unlocked and the command returns an error without any changes to the log file.

·         If the --force option is specified, this function continues even if it is unable to create a backup copy.

5.    Set the "generation number" in the header of the log file to an odd value.

6.    Perform compaction by moving unmarked records to fill the space occupied by the records selected for deletion, and truncates the log file.  The sequential order of events in the event log is maintained during this process and the record ids of the remaining event records are left unchanged.

7.    Set the "generation number" in the header of the log file to an even value.

8.    Unlock the log file.

9.    Delete the backup copy of the log file (if a backup was created in step 4).

10.Destroy the query object created in step 1.

11.Log an "end" event (defined in the POSIX standard as POSIX_LOG_MGMT_ENDMAINT).

 

After step 3, and until step 8 completes, calls to posix_log_open() will return EBUSY.  Calls to posix_log_seek() and posix_log_read() will return EBADF, indicating that the caller should attempt to re-open the log at a later time.  Applications should also register for the POSIX_LOG_MGMT_STARTMAINT and POSIX_LOG_MGMT_ENDMAINT events to know explicitly when the log is not available.

 

If the evlogmgr command is terminated with ctrl-c the operation is aborted and the original log file is restored from the backup file. If a backup log file is discovered during bootup, evlogd will rename it and use it as the active log file, thus assuming that the original log file was corrupted, possibly due to a system crash.

               

Although you are strongly discouraged from using the --force option, which skips creating a backup copy, in some rare cases there may not be adequate disk space to create even a compressed backup of the log file.  In this case use of the --force option may be the only option available for freeing disk space (short of deleting files).  If compaction fails and there is no backup available, then the     --fix option is available to restore the log file to a fully usable state.  This may require removing data that can no longer be interpreted accurately as event records.

                                                                         

6.5.1        User Commands

6.5.1.1       evlogmgr - Event Log Manager

                                                                            

    SYNOPSIS

 

         evlogmgr -c|--compact filter  [-F|--force] [-C|--compr-bak]

             [[-p|--private] | [-l|--log srclogfile]]          

 

         evlogmgr -f|--fix               

             [[-p|--private] | [-l|--log srclogfile]]

 

         evlogmgr –s|-–show-status filter

             [[-p|--private] | [-l|--log srclogfile]]

                                                                        

    DESCRIPTION                                                            

The evlogmgr command performs log management on the event log, the private log, or optionally, a log file that you specify.  You also specify which events are to be deleted.  The space freed by deleted events is re-used for undeleted events (referred to as compaction) and the log file is truncated, thus reducing its overall size. 

 

You must have root permission to use this command.         

                                                                          

evlogmgr accepts the following options:

 

      -c, --compact filter [-F|--force] [-C|--compr-bak] [[-p|--private] | [-l|--log srclogfile]]

 

Deletes event records in the event log matching the specified filter, fills space freed by deleting the event records (by moving later records into the free space), and then truncates the log thus establishing a new write offset for new events.  The sequential order of events in the event log is maintained during this process and the record ids of the remaining event records are left unchanged.  See Query and Filter Expression Syntax Rules for more information about the filter.

 

Before the compaction process begins, a backup copy of the log file is created if space is available.  Following successful completion, the backup copy is deleted.  If the evlogmgr command is issued from the command-line, and the user does a ctrl-c, then the active log file is restored from the backup copy.  In the event that the system reboots before compaction completes, the active log file is restored from the backup copy (after reboot).

 

Unless the --private or --log options are used, log management is performed on /var/evlog/eventlog.

 

The --force option should only be used as a last resort.  If space is not available to create a backup (compressed or uncompressed), then this option forces compaction to occur without first creating a backup of the log file.  If compaction does not complete successfully, then the --fix command (see below) may be able to restore the log file to a usable state.

 

The --compr-bak option specifies that the backup log file created prior to compacting the original log file should be compressed.  Choosing this option will take longer, but limited space may require its use.

 

The --private option specifies that compaction should be performed on /var/evlog/privatelog.  This option is not valid in combination with the --log option.

 

The --log option specifies an alternate log file to be compacted.  This option is not valid in combination with the --private option.

   

-f, --fix [[-p|--private] | [-l|--log srclogfile]]

 

This option is used to repair a corrupted log file.  Its use should only be required in cases where the --force option was used and the log management tasks terminated before completion.

Each record in the event log is validated, and any records that are deemed invalid are deleted and replaced by other valid records in the log.  The total number of bytes deleted is reported by this command.

 

Some of the error messages that will indicate the need to repair the log include:

 

      Input/output error                       (from evlview)

 

      Failed to count record for deletion.     (from evlogmgr -s)

 

      Failed to compact log                    (from evlogmgr -c)

 

Unless the --private or --log options are used, repair is performed on /var/evlog/eventlog.

 

The --private option specifies that repair should be performed on /var/evlog/privatelog.  This option is not valid in combination with the --log option.

 

The --log option specifies an alternate log file to be repaired.  This option is not valid in combination with the --private option.

 

                                                                          

 -s, --show-status filter [[-p|--private] | [-l|--log srclogfile]]

 

Shows how many records in the event log match the filter, and the total number of records in the log.   See Query and Filter Expression Syntax Rules for more information about the filter.  

      

Unless the --private or --log options are used, status is shown for /var/evlog/eventlog.

 

The --private option specifies that status should be shown for /var/evlog/privatelog.  This option is not valid in combination with the --log option.

 

The --log option specifies that status should be shown for an alternate log file.  This option is not valid in combination with the --private option.

                                                          

 

      EXAMPLES

     

      Example 1.

  

  Run evlogmgr -c from a cron job.  See "man 5 crontab" for more details.

 

    # Everyday at 2:00 am run evl log manager and remove records that are older than 30 days
    0 2 * * * root /sbin/evlogmgr -c 'age > "30d"'
 
    # Everyday  at 1:00 am run evl log manager and remove records with severity=DEBUG
    0 1 * * * root /sbin/evlogmgr -c "severity=DEBUG"

                                                                                      

         

      Example 2.

                 

        Issuing the following command:

           

              evlogmgr -c 'severity=DEBUG' -C

 

        results in the following events being appended to the event log:

 

recid=589, size=74, format=STRING, event_type=2, facility=LOGMGMT,

severity=NOTICE, uid=root, gid=root, pid=18653, pgrp=18653,

time=Thu 09 May 2002 12:59:08 PM PDT, flags=0x0, thread=0x400, processor=0

Log compaction on /var/evlog/eventlog starts at Thu May 09 12:59:08 2002

 

recid=591, size=69, format=STRING, event_type=3, facility=LOGMGMT,

severity=NOTICE, uid=root, gid=root, pid=18653, pgrp=18653,

time=Thu 09 May 2002 12:59:09 PM PDT, flags=0x0, thread=0x400, processor=0

Log compaction on /var/evlog/eventlog ended. 48 events were removed.     

 

            

      Example 3.

 

        Issuing the following command:   

                                     

            evlogmgr -s 'severity=DEBUG'

     

        Displays the following:

     

            Total number of records is 294.

            Number of records matching the filter is 48.

            Log file size would be reduced by 5.00 kbytes

 

     

      Example 4.

 

        Issuing the following command for a corrupted log file:

           

            evlogmgr --fix

 

        Displays the following:

     

            Found a corrupted event record. Trying to resync with next good record...

            Log repair finished, problem fixed.  Discarded 6 bytes.    

 

     

     FILES                                                                 

          /var/evlog/eventlog           Standard Event log 

          /var/evlog/privatelog         Private Event Log                            

         

 

  

 

 

6.6      Query and Filter Expression Syntax Rules

A simple query or filter expression is a single test of the form "attribute-name op val", where

-- attribute-name is the name of an event attribute,

-- op is a comparison operator such as == or <, and

-- val is the reference value for the test – typically a symbolic constant, an integer constant, or a string literal.

An event record is said to pass the test if the comparison between the reference value and the value of the named attribute in the event record evaluates to true (non-zero).

More complex queries can be constructed by combining queries using operators such as && and || (“and” and “or”, respectively), or by negating a query using the '!' operator.  An event record is said to match a query if the query expression evaluates to true (non-zero) for that record.

 

Columns 1-5 of the following table have the same meaning as in Table 20-9 in the POSIX draft standard.  The last column, “Std?”, contains a “y” (yes) if this row of the table is required by the standard, or N (no) if it represents an extension in Linux event logging.

 

posix_log_entry Member

Attribute Name

Operand Type

Required Operations

Interpretation of attr_name op val

Std?

log_recid

recid

Integer

=, !=, <, <=, >, >=

Integer comparison

y

log_size

size

Integer

=, !=, <, <=, >, >=

Integer comparison

y

log_format

format

Integer

=, !=, <, <=, >, >=

Integer comparison.  val shall be an integer constant; one of the format names listed in Table 20-4, with the “POSIX_LOG_” prefix removed (e.g., BINARY); or an implementation-defined format name.

y

log_event_type

event_type

Integer

=, !=, <, <=, >, >=

Integer comparison.  val shall be an integer constant; one of the event-type names listed in Table 20-6, with the “POSIX_LOG_” prefix removed (e.g., MGMT_TIMEMARK); or an implementation-defined event-type name.

y

log_facility

facility

String

=, !=

strcmp of string representation of log_facility with val.  val shall be a string literal; one of the facility names listed in Table 20-2, with the “LOG_” prefix removed (e.g., AUTH, CRON, DAEMON); or an implementation-defined facility name.

y

~, !~

regexec comparison of string representation of log_facility with regular expression val.

y

Integer

=, !=, <, <=, >, >=

Integer comparison.

N

log_severity

severity

Severity

=, !=, <, <=, >, >=

posix_log_severity_compare of log_severity with val.  val shall be one of the severity names listed in Table 20-3, with the “LOG_” prefix removed (e.g., EMERG, ALERT, CRIT); or an implementation-defined severity name.

y

log_uid

uid

Integer

=, !=, <, <=, >, >=

Integer comparison

y

String

=, !=

strcmp of string representation of log_uid with val.

y

log_gid

gid

Integer

=, !=, <, <=, >, >=

Integer comparison

y

String

=, !=

strcmp of string representation of log_gid with val

y

log_pid

pid

Integer

=, !=, <, <=, >, >=

Integer comparison

y

log_pgrp

pgrp

Integer

=, !=, <, <=, >, >=

Integer comparison

y

log_time

time

Integer

=, !=, <, <=, >, >=

Interpret val as a time_t, and perform integer comparison with log_time.tv_sec

y

String

=, !=, contains

String comparison of string representation of log_time with val.

N

~, !~

regexec comparison of string representation of log_time with  regular expression val.

N

age (see notes)

Integer

=, !=, <, <=, >, >=

Comparison of the age[3] of the event record, in days, with val.

N

String

=, !=, <, <=, >, >=

Comparison of the age of the event record with the time span indicated by val.  val shall consist of a decimal integer followed by the letter ‘s’ (seconds), ‘m’ (minutes), ‘h’ (hours), or ‘d’ (days).[4]

N

log_flags

flags

Integer

&

log_flags & val.  val shall be an integer constant or the name TRUNCATE,

KERNEL, or INTERRUPT.

y

log_thread

thread

String

=, !=

strcmp of string representation of log_thread with val

y

Integer

=, !=, <, <=, >, >=

Integer comparison.

N

log_processor

processor

String

=, !=

strcmp of string representation of log_processor with val

y

~, !~

regexec comparison of string representation of log_processor with  regular expression val.

Y

Integer

=, !=, <, <=, >, >=

Integer comparison.

N

None

data

String

=, !=

If the value of log_format is POSIX_LOG_STRING, strcmp of the variable portion of the record with val; otherwise zero.

Y

contains

Evaluates to 1 if the value of log_format is POSIX_LOG_STRING and the substring val appears in the variable portion of the record; otherwise zero.

Y

~, !~

If the value of log_format is POSIX_LOG_STRING, regexec comparison of the variable portion of the record with the regular expression val; otherwise zero.

Y

None

host

 

 

 

 

 

 

Notes regarding "age":

 

·         The age of an event record is "now" (as returned by time()) minus the event record's timestamp.  "now" is computed each time that the query is evaluated against an event record.

·         If a letter does not follow the numeric value (ie. 'age >"7d" '), then the numeric value is interpreted as "number of days:.

 

 

6.6.1 Extensions to the POSIX Standard

 

In addition to the extensions to the POSIX standard shown in the table above, two new values were added to the purpose argument for posix_log_query_create() (not added to the draft POSIX standard, but as an extension for Linux Event Logging):

·         EVL_PRPS_RESTRICTED - indicates that query expression is to be used for a Restricted Logging Filter (see 6.2.1.1  Restricted Logging).

·         EVL_PRPS_TEMPLATE - indicates that the query expression includes attribute names that are not attribute names defined in posix_log_entry, but should still be accepted by posix_log_create_query() as valid.  The attributes will be defined when a formatting template is applied which defines the attribute names.  The "attribute name" can be a simple name (e.g. "employee") or a reference to a struct member (e.g. "employee.addr.city").
 

 

 

 

6.7      Modifications to the Linux Kernel

 

A kernel patch is required in order to provide event logging features in kernel-space, and does the following:

                1.     Adds a kernel buffer for event logging (default size is 128K, but is configurable).

2.        Adds the new functions specified for writing event records from kernel-space --  posix_log_write(), posix_log_printf(),  posix_log_vprintf, evl_writek(),and  evl_vwritek().

3.        Adds the new functions specified for registering facility and generating facility code -- evl_register_facility() and evl_gen_facility_code().

4.        Modifies printk() to log messages to the new kernel buffer (as POSIX event records) in addition to continuing to write them into the static buffer that klogd reads from.   Forwarding of printk() messages must be enabled during kernel configuration (it is disabled by default).

5.         Modifies  do_syslog()  to add an option for reading events from the  kernel buffer.

6.        Adds an option in kernel configuration to enable or disable event logging.

If the kernel patch is applied, but event logging is configured as disabled during kernel configuration, the functions described above will return ENOSYS.   One method of handling this condition is for the callers of these functions in the kernel to check the return value on their first attempt to use them, and if ENOSYS is returned then use printk(), which will always be available regardless of  how the kernel is configured. 

 

6.7.1        Enhanced printk

 

An additional pair of kernel patches for selected versions of the kernel provide all of the features previously described, but also add

 the following features:

 

·         The existing printk() function is renamed and "wrapped" with a printk macro. The macro captures source file name, function name, and line number where printk() is called, and includes this information in an event record, along with the original printk() message.  Additionally, a checksum is computed from the source file name, function name, and printk format string and set as the log_event_type in the event records generated from printk() calls.  The capturing of caller location information in the event record must be enabled during kernel configuration, and printk messages (without any of the caller location info) are still written to the static buffer that klogd() reads from (as described above).

 

·         Another patch is required to modify the printk() arg lists in some device drivers and other kernel code to remove directives (#ifdef's) which are not allowed in macros.   For example…

                               

   printk("generic options"
# ifdef AUTOPROBE_IRQ
       "AUTOPROBE_IRQ"
# else
       "AUTOSENSE"
# endif
       );
 
…must be unwrapped to…
 
# ifdef AUTOPROBE_IRQ
   printk("generic options"      "AUTOPROBE_IRQ");
# else
   printk("generic options"      "AUTOSENSE");
# endif

 

                       …if printk() is a macro.  

 

 

 

6.8      Modifications to syslog

 

Refer to Appendix B Overview of Syslog 1.3 (for Linux) and the man page for syslog for an explanation of current functionality. 

In order to log syslog messages to /var/evlog/eventlog and /var/evlog/privatelog, the syslog() API call defined in the GNU C Library could be modified to pass POSIX event records to the evlogd daemon.   However, since recompiling glibc is risky and time-consuming, an additional library is provided with the evlog package that "wraps around" glibc.  Basically, it redefines syslog(), vsyslog() and openlog().  If this library is always loaded before glibc, then any program making calls to any of these three glibc functions will call the new library's functions instead.  This concept is similar to that used by libsafe (see http://www.research.avayalabs.com/project/libsafe/index.html). 

The library is loaded before glibc by editing /etc/ld.so.conf or defining the LD_PRELOAD environment variable (see man ld.so for more details).  The library, when loaded, will find the actual address of syslog(), vsyslog() and openlog(); and then when users call the library's syslog(), it calls a function to create a POSIX event record and then the original glibc syslog.  This is significant because there is no glibc functionality in this extra library; thus glibc can change without affecting event logging.

Even with the changes described, not all syslog messages will necessarily be logged to the event logs, due to the fact that the syslogd daemon can receive events via UNIX domain sockets (up to 19) other than /dev/log.

 

 

7         Appendices

7.1      Appendix A  POSIX 1003.25 **DRAFT**

Go to:  http://evlog.sourceforge.net/posix_evlog.html  and http://evlog.sourceforge.net/posix_rationale.html.

 

7.2      Appendix B Overview of Syslog 1.3 (for Linux)

This section presents a summary of the most significant features of sysklogd.  Please see the man pages for sysklogd-1.3 for complete descriptions.

 

Sysklogd provides two system utilities which provide support for system logging and kernel message trapping. Support of both internet and unix domain sockets enables this utility package to support both local and remote logging.

 

System logging is provided by a version of syslogd derived from the stock BSD sources. Support for kernel logging is provided by the klogd  utility which allows kernel logging to be conducted in either a standalone fashion or as a client of syslogd.

 

Every logged message contains at least a time and a hostname field, normally a program name field, too, but that depends on how trusty the logging program is.

 

The main configuration file /etc/syslog.conf  is read at startup, and when the syslogd receives a HUP signal.  Any lines that begin with the hash mark (``#'') and empty lines are ignored.  See syslog.conf for details.
 

Syslogd Options


The most significant options are:

-h    permit forwarding to defined forwarding hosts (see -r).  Default is to NOT forward.
-r    enables receipt of messages from the network using an internet domain socket with the syslog service.  Default is to NOT receive.  Typically used for a centralized logging host.

-l    hostname only log simple hostname (ie. me) and not full name (ie. me.beaverton.ibm.com). Use ":" for multiple hostnames.
-s   domainlist  domainnames that should be stripped off before logging.  Use ":" for multiple domainnames


 
 

Remote Logging of syslog messages


The -h and -r options permit remote-logging of messages from one or more hosts to a central
host, where the message is written to a disk file.   The central host uses the -r option, and the individual hosts use the -h option.  syslogd both sends and listens for messages on port 514/udp.  Specification of which messages are forwarded is described under  syslog.conf .

 

If the remote host and sending host are in the same domain, only the simple hostname is logged (me vs. me.somewhere.usa.com).  If the hosts are in different domains, this same behavior can be forced (ie. only log simple hostname) by using the -s option.

To prevent "loops", no messages received by a remote host are sent out to another (or the same) remote host.

 

If remote hostname cannot be resolved at startup, syslogd will retry to resolve 10 times, to allow the name-server time to become active.

 

There is a potential for the syslogd to be used as a conduit for a denial of service attack.  In addition, a large flood of messages can also cause the log files to consume all of the remaining space within a filesystem.  See the sysklogd man pages for suggestions to address this exposure.
 

syslog.conf

The syslog.conf file is the main configuration file which specifies the rules for logging.  Each rule consists of a selector field and an action field.

 

The selector field is encoded as a combination of severity, which specifies the severity of the condition being reported, and facility, which generally identifies the source of the message.   Valid values for each are shown, as defined in /usr/include/sys/syslog.h:

severity codes

#define LOG_EMERG           0       /* emerg - system is unusable*/
#define LOG_ALERT            1       /* alert - action must be taken immediately */
#define LOG_CRIT               2       /* crit - critical conditions */
#define LOG_ERR                 3       /* err - error conditions */
#define LOG_WARNING     4       /* warn - warning conditions */
#define LOG_NOTICE          5       /* notice - normal but significant condition */
#define LOG_INFO               6       /* info - informational */
#define LOG_DEBUG            7       /* debug - debug-level messages */

facility codes

#define LOG_KERN         (0<<3)  /* kern - kernel messages */
#define LOG_USER          (1<<3)  /* user - random user-level messages */
#define LOG_MAIL          (2<<3)  /* mail - mail system */
#define LOG_DAEMON   (3<<3)  /* daemon - system daemons */
#define LOG_AUTH          (4<<3)  /* auth - security/authorization messages */
#define LOG_SYSLOG     (5<<3)  /* syslog - messages generated internally by syslogd */
#define LOG_LPR             (6<<3)  /* lpr - line printer subsystem */
#define LOG_NEWS         (7<<3)  /* news - network news subsystem */
#define LOG_UUCP          (8<<3)  /* uucp - UUCP subsystem */
#define LOG_CRON         (9<<3)  /* cron - clock daemon */
#define LOG_AUTHPRIV (10<<3) /* authpriv - security/authorization messages (private) */
#define LOG_FTP             (11<<3) /* ftp - ftp daemon */

        /* other codes through 15 reserved for system use */
#define LOG_LOCAL0      (16<<3) /* local0- reserved for local use */
#define LOG_LOCAL1      (17<<3) /* local1- reserved for local use */
#define LOG_LOCAL2      (18<<3) /* local2 - reserved for local use */
#define LOG_LOCAL3      (19<<3) /* local3 - reserved for local use */
#define LOG_LOCAL4      (20<<3) /* local4 - reserved for local use */
#define LOG_LOCAL5      (21<<3) /* local5 - reserved for local use */
#define LOG_LOCAL6      (22<<3) /* local6 - reserved for local use */
#define LOG_LOCAL7      (23<<3) /* local7 - reserved for local use */

An example of specifying priority and facility in a call to syslog():

syslog(LOG_NOTICE|LOG_AUTH, "Login was disabled for %d minutes", minutes);

Note that syslog uses the same formatting characters as printf (in this case %d) except that %m will be replaced by the error message string corresponding to the current value of errno.

 

The action field describes the "logfile" where the message will be written.  "logfile" can be an actual file with fully qualified pathname, but it can also be one of the following:

·         Named pipe

·         Terminal/console

·         Remote host (see  Remote Logging for a description)

·         List of users

·         Everyone logged on

 

The behavior of the original BSD syslogd is that all messages of the specified priority and higher are logged according to the given action.  The Linux version of syslogd behaves the same, with some new modifiers.  An example of  entries in the syslog.conf file:

kern.emerg             /usr/log/user_logfile_emerg
kern.alert                /usr/log/user_logfile_alert

which states that messages from facility of kern, with a priority of emerg will be logged to /usr/log/user_logfile_emerg, and with a priority of emerg and higher will be logged to /usr/log/user_logfile_alert.  This means that emerg messages will be logged to /usr/log/user_logfile_alert and to/usr/log/user_logfile_emerg.  To prevent the duplicate  logging of emerg messages, the "=" modifier can be used:

kern.emerg                  /usr/log/user_logfile_emerg
kern.=alert                  /usr/log/user_logfile_alert

which states that alert messages, but not emerg, or any other priority, are logged to /usr/log/user_logfile_alert.

An example of specifying messages that are to be forwarded to a remote host:

kern.*                       @central-logger

which states that all messages from the kernel are forwarded to a remote host called central-logger.  See  Remote Logging for how to setup remote-logging.

 

A common practice is to specify the following in syslog.conf:

 

      authpriv.*                         /var/log/secure

 

where the secure file has more restrictive read access than the other message files.              

                               

See the syslog.conf man page for complete desciptions and other examples.

Additional syslog options

If not explicitly called, opening of the system logger is performed automatically by syslog()..  However, calls to openlog() directly prior to calling syslog() provides addition options which include:

·         Adding a string, which typically identifies the program name, and is included in the message when it is logged

·         Writing the message to stderr in addition to the log file.

·         Writing the message to the system console if there is an error while logging.

·         Including the PID with each message.

 

klogd

klogd can either log messages through syslogd, or log messages to a separate file (by specifying the -f file option).

 

If kernel messages are directed through the syslogd daemon, the klogd daemon has the ability to assign the approproiate syslog priority to the message, if a priority value is included.  Valid values for priority, as defined in /usr/include/linux/kernel.h:

#define KERN_EMERG        "<0>"  /* system is unusable                   */
#define KERN_ALERT         "<1>"   /* action must be taken immediately     */
#define KERN_CRIT            "<2>"   /* critical conditions                  */
#define KERN_ERR              "<3>"   /* error conditions                     */
#define KERN_WARNING  "<4>"   /* warning conditions                   */
#define KERN_NOTICE       "<5>"   /* normal but significant condition     */
#define KERN_INFO            "<6>"   /* informational                        */
#define KERN_DEBUG         "<7>"   /* debug-level messages                 */

An example of kernel logging using this scheme:

printk(KERN_DEBUG "IRQ %d ", irq);

Because of C’s concatenation of adjacent string literals, this is the same as printk(“<7>IRQ%d”, irq).

By default, klogd does not write messages to the console (except for panics).  This behavior can be modified with the -c option.  For example,

klogd -c 3

will cause messages with priority of emerg (0), alert (1) , and crit (2) to be displayed on the console.

The -o option provides a "one-shot" mode, which causes klogd to read and log all messages that are found in the kernel message buffers, and then terminate.  For example, this could be useful for logging bootup errors into a different file than steady-state run-time errors.

 

Several options, such as -i, -I, -p, and -k are related to klogd resolving kernel numeric address to their symbolic forms, for easier debugging, as described in the klogd man page.
 

logger command

Logger provides a shell command interface to syslog.  For example,

logger -i -p local7.info This is just messing around

Results in the following message written to the specified file for facility=local7 and priority=info.

Sep 29 14:34:50 w-smlinux1 guest[13017]: This is just messing around

where 13017 is the process id, which was logged due to the -i option.
 

Log File Management / logrotate command

One feature provided by syslogd that helps to reduce the volume of logged messages, especially if a flood of identical messages gets logged, is the counting of duplicates.  For example, issuing the command:

logger   -p local7.info This is just messing around

22 times causes the following to be written to the log file:

Oct  2 12:35:12 w-smlinux1 guest: This is just messing around
Oct  2 12:36:26 w-smlinux1 last message repeated 21 times

Another user-controlled method of managing log files is use of the logrotate command, which provides automatic rotation, compression, removal, and mailing of log files.   Each log file may be handled daily, weekly, monthly, or when it grows too large.   The command is typically run as a daily cron job.

 

The actions performed by logrotate are defined in configuration files.  An example of what is contained in a configuration file (default is /etc/logrotate.conf):

# THE FIRST ENTRIES APPLY GLOBALLY TO ALL LOG FILES
# rotate log files weekly
weekly

# keep 2 weeks worth of backlogs
rotate 2

# send errors to root
errors root

# create new (empty) log files after rotating old ones
create

# Compress rotated log files.
 compress

# LOGGING ACTIONS FOR SPECIFC FILES OVERRIDE GLOBAL ACTIONS
# They can be specified here or in include files

# Critical and higher messages gets mailed to root daily, uncompressed.
/var/log/critical_and_higher_msg_file {
       daily
       create
#  Do not compress
       nocompress
#  Keep 14 days worth of backlogs
       rotate 14
# Mail just-rotated file to root
       mailfirst root
}

# RPM packages drop log rotation information into this directory
include /etc/logrotate.d

 For syslog, the file /etc/logrotate.d/syslog would contain the following:

postrotate
# syslogd performs re-initialization
    /usr/bin/killall -HUP syslogd
endscript

 

As an example, using the above logrotate.conf file, you would see the following in /var/log:

-rw-------    1 root     root          410 Oct  2 12: 56 critical_and_higher_msg_file
-rw-------    1 root     root          497 Oct  1 04:02 critical_and_higher_msg_file.1
-rw-------    1 root     root          681 Sep 30 04:02 critical_and_higher_msg_file.2
-rw-------    1 root     root          681 Sep 29 04:02 critical_and_higher_msg_file.3
....up to... critical_and_higher_msg_file.14

 

Associated Files

·         /etc/syslog.conf   -   Configuration File

·         /dev/log  -  Unix domain socket where syslog() messages are written, and where syslogd reads

·         /var/run/syslogd.pid  -   Contains process id of syslogd.

·         /proc/ksmg  -  One source for kernel messages (if prpc file system is not mounted klogd uses a system call to obtain kernel messages).

·         /var/run/klogd.pid  -  Contains process id of klogd.

·         /boot/System.map   /System.map  /usr/src/linux/System.map  -  Default locations for kernal system maps.

 

7.3      Appendix C Issues and New Requirements

This list has been moved to a new location.

 

 

7.4      Appendix D siginfo.h header file

To assist in understanding Event Notification,  siginfo.h is provided here.  

 #ifndef _I386_SIGINFO_H

#define _I386_SIGINFO_H

 

#include <linux/types.h>

 

/* XXX: This structure was copied from the Alpha; is there an iBCS version?  */

 

typedef union sigval {

       int sival_int;

       void *sival_ptr;

} sigval_t;

 

#define SI_MAX_SIZE  128

#define SI_PAD_SIZE  ((SI_MAX_SIZE/sizeof(int)) - 3)

 

typedef struct siginfo {

       int si_signo;

       int si_errno;

       int si_code;

 

       union {

              int _pad[SI_PAD_SIZE];

 

              /* kill() */

              struct {

                     pid_t _pid;          /* sender's pid */

                     uid_t _uid;          /* sender's uid */

              } _kill;

 

              /* POSIX.1b timers */

              struct {

                     unsigned int _timer1;

                     unsigned int _timer2;

              } _timer;

 

              /* POSIX.1b signals */

              struct {

                     pid_t _pid;          /* sender's pid */

                     uid_t _uid;          /* sender's uid */

                     sigval_t _sigval;

              } _rt;

 

              /* SIGCHLD */

              struct {

                     pid_t _pid;          /* which child */

                     uid_t _uid;          /* sender's uid */

                     int _status;         /* exit code */

                     clock_t _utime;

                     clock_t _stime;

              } _sigchld;

 

              /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */

              struct {

                     void *_addr; /* faulting insn/memory ref. */

              } _sigfault;

 

              /* SIGPOLL */

              struct {

                     int _band;    /* POLL_IN, POLL_OUT, POLL_MSG */

                     int _fd;

              } _sigpoll;

       } _sifields;

} siginfo_t;

 

/*

 * How these fields are to be accessed.

 */

#define si_pid             _sifields._kill._pid

#define si_uid             _sifields._kill._uid

#define si_status    _sifields._sigchld._status

#define si_utime     _sifields._sigchld._utime

#define si_stime     _sifields._sigchld._stime

#define si_value     _sifields._rt._sigval

#define si_int             _sifields._rt._sigval.sival_int

#define si_ptr             _sifields._rt._sigval.sival_ptr

#define si_addr            _sifields._sigfault._addr

#define si_band            _sifields._sigpoll._band

#define si_fd        _sifields._sigpoll._fd

 

#ifdef __KERNEL__

#define __SI_MASK    0xffff0000

#define __SI_KILL    (0 << 16)

#define __SI_TIMER   (1 << 16)

#define __SI_POLL    (2 << 16)

#define __SI_FAULT   (3 << 16)

#define __SI_CHLD    (4 << 16)

#define __SI_RT            (5 << 16)

#define __SI_CODE(T,N)     ((T) << 16 | ((N) & 0xffff))

#else

#define __SI_KILL    0

#define __SI_TIMER   0

#define __SI_POLL    0

#define __SI_FAULT   0

#define __SI_CHLD    0

#define __SI_RT            0

#define __SI_CODE(T,N)     (N)

#endif

 

/*

 * si_code values

 * Digital reserves positive values for kernel-generated signals.

 */

#define SI_USER            0             /* sent by kill, sigsend, raise */

#define SI_KERNEL    0x80          /* sent by the kernel from somewhere */

#define SI_QUEUE     -1            /* sent by sigqueue */

#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */

#define SI_MESGQ     -3            /* sent by real time mesq state change */

#define SI_ASYNCIO   -4            /* sent by AIO completion */

#define SI_SIGIO     -5            /* sent by queued SIGIO */

 

#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)

#define SI_FROMKERNEL(siptr)      ((siptr)->si_code > 0)

 

/*

 * SIGILL si_codes

 */

#define ILL_ILLOPC   (__SI_FAULT|1)       /* illegal opcode */

#define ILL_ILLOPN   (__SI_FAULT|2)       /* illegal operand */

#define ILL_ILLADR   (__SI_FAULT|3)       /* illegal addressing mode */

#define ILL_ILLTRP   (__SI_FAULT|4)       /* illegal trap */

#define ILL_PRVOPC   (__SI_FAULT|5)       /* privileged opcode */

#define ILL_PRVREG   (__SI_FAULT|6)       /* privileged register */

#define ILL_COPROC   (__SI_FAULT|7)       /* coprocessor error */

#define ILL_BADSTK   (__SI_FAULT|8)       /* internal stack error */

#define NSIGILL            8

 

/*

 * SIGFPE si_codes

 */

#define FPE_INTDIV   (__SI_FAULT|1)       /* integer divide by zero */

#define FPE_INTOVF   (__SI_FAULT|2)       /* integer overflow */

#define FPE_FLTDIV   (__SI_FAULT|3)       /* floating point divide by zero */

#define FPE_FLTOVF   (__SI_FAULT|4)       /* floating point overflow */

#define FPE_FLTUND   (__SI_FAULT|5)       /* floating point underflow */

#define FPE_FLTRES   (__SI_FAULT|6)       /* floating point inexact result */

#define FPE_FLTINV   (__SI_FAULT|7)       /* floating point invalid operation */

#define FPE_FLTSUB   (__SI_FAULT|8)       /* subscript out of range */

#define NSIGFPE            8

 

/*

 * SIGSEGV si_codes

 */

#define SEGV_MAPERR  (__SI_FAULT|1)       /* address not mapped to object */

#define SEGV_ACCERR  (__SI_FAULT|2)       /* invalid permissions for mapped object */

#define NSIGSEGV     2

 

/*

 * SIGBUS si_codes

 */

#define BUS_ADRALN   (__SI_FAULT|1)       /* invalid address alignment */

#define BUS_ADRERR   (__SI_FAULT|2)       /* non-existant physical address */

#define BUS_OBJERR   (__SI_FAULT|3)       /* object specific hardware error */

#define NSIGBUS            3

 

/*

 * SIGTRAP si_codes

 */

#define TRAP_BRKPT   (__SI_FAULT|1)       /* process breakpoint */

#define TRAP_TRACE   (__SI_FAULT|2)       /* process trace trap */

#define NSIGTRAP     2

 

/*

 * SIGCHLD si_codes

 */

#define CLD_EXITED   (__SI_CHLD|1) /* child has exited */

#define CLD_KILLED   (__SI_CHLD|2) /* child was killed */

#define CLD_DUMPED   (__SI_CHLD|3) /* child terminated abnormally */

#define CLD_TRAPPED  (__SI_CHLD|4) /* traced child has trapped */

#define CLD_STOPPED  (__SI_CHLD|5) /* child has stopped */

#define CLD_CONTINUED      (__SI_CHLD|6) /* stopped child has continued */

#define NSIGCHLD     6

 

/*

 * SIGPOLL si_codes

 */

#define POLL_IN            (__SI_POLL|1) /* data input available */

#define POLL_OUT     (__SI_POLL|2) /* output buffers available */

#define POLL_MSG     (__SI_POLL|3) /* input message available */

#define POLL_ERR     (__SI_POLL|4) /* i/o error */

#define POLL_PRI     (__SI_POLL|5) /* high priority input available */

#define POLL_HUP     (__SI_POLL|6) /* device disconnected */

#define NSIGPOLL     6

 

/*

 * sigevent definitions

 *

 * It seems likely that SIGEV_THREAD will have to be handled from

 * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the

 * thread manager then catches and does the appropriate nonsense.

 * However, everything is written out here so as to not get lost.

 */

#define SIGEV_SIGNAL 0      /* notify via signal */

#define SIGEV_NONE   1      /* other notification: meaningless */

#define SIGEV_THREAD 2      /* deliver via thread creation */

 

#define SIGEV_MAX_SIZE     64

#define SIGEV_PAD_SIZE     ((SIGEV_MAX_SIZE/sizeof(int)) - 3)

 

typedef struct sigevent {

       sigval_t sigev_value;

       int sigev_signo;

       int sigev_notify;

       union {

              int _pad[SIGEV_PAD_SIZE];

 

              struct {

                     void (*_function)(sigval_t);

                     void *_attribute;    /* really pthread_attr_t */

              } _sigev_thread;

       } _sigev_un;

} sigevent_t;

 

#define sigev_notify_function     _sigev_un._sigev_thread._function

#define sigev_notify_attributes   _sigev_un._sigev_thread._attribute

 

#ifdef __KERNEL__

#include <linux/string.h>

 

extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)

{

       if (from->si_code < 0)

              memcpy(to, from, sizeof(siginfo_t));

       else

              /* _sigchld is currently the largest know union member */

              memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));

}

 

extern int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from);

 

#endif /* __KERNEL__ */

 

#endif

 

 

 7.5      Appendix E   Date and Time Formats

 

For commands that display date and time, for example evlview, the format is based on the setting of the LANG environment variable. 

If LANG is not set, or is set to "C", the date format is the same as shown in the examples in this specification.   Examples of some other formats are as follows:

 

English - United States

$ export LANG=en_US       

$ evlview -t 1 -S %time%

Mon 04 Feb 2002 11:52:18 AM PST

 

Spanish  - Mexico

$ export LANG=es_MX  

$ evlview -t 1 -S %time%

lun 04 feb 2002 11:52:18 PST

 

German - Germany

$ export LANG=de_DE

$ evlview -t 1 -S %time%

Mon 04 Feb 2002 11:52:18 PST

 

French - France

$ export LANG=fr_FR

$ evlview -t 1 -S %time%

lun 04 fév 2002 11:52:18 PST

 

English - India

$ export LANG=en_IN

$ evlview -t 1 -S %time%

Monday 04 February 2002 11:52:18 AM PST

 

LANG not set

$ unset LANG

$ evlview -t 1 -S %time%

Mon Feb  4 11:52:18 2002

 

 7.6      Appendix F   Facility Names and Facility Code creation

 

This section describes the rules for defining a facility name, the conversion that takes place to create a canonical name, and the algorithm for generating a unique facility code from the canonical name.

 

  1. The maximum length of a facility name is defined by POSIX_LOG_MEMSTR_MAXLEN.
  2. A facility name can contain any character, ASCII or otherwise, except null.  (Control characters are of course discouraged.)
  3. There is a "canonical" form for facility names.  A facility name is converted to its canonical form as follows:

a.       The following bytes are passed through unchanged: ASCII digits, ASCII lowercase letters, period, underscore, and any bytes outside the ASCII code set.

b.       Uppercase ASCII letters are converted to lowercase.

c.       A space character is converted to an underscore.

d.       Any other ASCII character is converted to a period.

  1. An unsigned integer value based on 32-bit CRC is computed from the facility's canonical name.  This unsigned integer value is used as the "facility code" and is stored in event records in the log_facility member.  Both the facility name and facility integer value are stored in the facility registry.
  2. The evlfacility command and API functions will refuse to create an entry in the facility registry whose canonical name is the same as an existing facility's canonical name (or whose CRC matches another facility's code).
  3. For matching facility names in a name lookup (such as used by posix_log_strtofac() or evlfacility -c), we are case-insensitive only for ASCII letters.  All other characters must match exactly.  Note that even though "Jim's facility" and "Jim/s facility" boil down to the same canonical name, they don't match in a name lookup.  However, if one of these names were in the registry, you couldn't add the other, since their canonical names match.

 

Some examples:

 

Facility Name

Canonical name

Facility code

KERN or kern

kern

0

JimK or jimk

jimk

0xffacc9d7

Larry's CD Driver

larry.s_cd_driver

0x65bb7c9e

MAN~ANA

maN~ana

0x4bf79738

 

 

 

8         Revision History

 

Revision

Date

Author

Description

0.71

May 8, 2001

Larry Kessler

·         Removed return of EINVAL for invalid facility argument passed to evl_logk(), evl_printk(), and evl_writek(), since any facility value is accepted by these functions..

·         Add reserved log_event_type of EVL_BUFFER_OVERRUN

·         Added example of event logged when buffer overrun condition occurs

·         Modified minimum facility values defined for /var/evlog/facility_registry so that they match facility values in sys/syslog.h

0.72

May 11, 2001

 Larry Kessler

Added linelen argument to evl_format_evrec_fixed()

0.73

May 30, 2001

Larry Kessler

  • Added new options to evlconfig command:
    • -add_facility
    • -del_facility
    • -list_facreg
    • -repl_facreg
    • Consolidated -screen_kernel, -screen_root, and -screen_apps into a single command:  -screen
  • Changes to evlview command:
    • Removed -format option
    • Modified -out option to only write to file in binary
    • Added -specf option

0.74

June 4, 2001

Larry Kessler

  • Remove underscores from command names to be more Linux-like.
  • Changed descriptions of time and date display to match Linux 'date' command.

0.75

June 11,2001

Larry Kessler

  • Added  "private" to Facility Registry
  • Added -add_priv and del_priv options to evlconfig command.
  • Updated description of evlview to better describe options.
  • Updated sections describing screening of events to reflect a limited set of attributes available with the evlconfig -screen command.
  • Removed return of ECANCELED from kernel and user space write functions.
  • Removed EVL_LOGGED_BY_PROXY from evl_flags
  • evl_writek(), evl_printk(), evl_logk() - changed ENOTSUP return to ENOSYS to better align with POSIX definitions.
  • Removed -help option from evlsend command.

 

  • Defined permission required for:
    • evlconfig
    • evlsend
    • evlview
    • evltemplate (still TBD)
    • evlfilter (still TBD)
    • evlnotify (still TBD)
    • evlogmgr

 

1.0

June 22, 2001

Larry Kessler

·         "wchar" and "wstring" are not supported by evl_writek()

·         Kernel buffer size changed to a kernel configuration parameter

o        evl_set_bufsize() removed

o        evlconfig -setbuf option removed

·         Removed reserved space from Log Management

·         Condensed Issues and New Requirements section into a summary, and added items 7, 8, and 9.

·         Removed PREFIX3 from Formatting template section

·         Added pseudo attribute for filter expressions:  age>"n" and age<"n"

·         Removed evl_filter command and added environment variable to allow users to create their own filter names, or to use the system-level filter names.

·         Updated Event notification to check user permission prior to allowing registration for event notification.  Also, added list of TBDs.

1.1

July 30, 2001

Jim Keniston

·         Added "import" to Formatting Templates section

1.2

August 6, 2001

Larry Kessler

·         Moved facility register command options from evlconfig command, to new 'evlfacreg' command

·         Under evlconfig command:

o         dup count or time can be 0, thus removing them from the discarding algorithm

o        Allow all event record header attributes to be included in event screen

o        "screen" is now stored in evlog.conf, not a separate file

·         Removed -debug option from all commands.

·         Significantly updated Event Notification section

·         Added Appendix D

1.3

August 7, 2001

Jim Keniston

·         Replaced evltemplate command with evltc command.

·         Replaced prior Template Management functions with 2 new ones.

1.4

August 8, 2001

Larry Kessler

·         Remove evl_get_bufsize()

1.4.1

August 10, 2001

Larry Kessler

Very minor change to what Child does under evl_actiond processing a notification.

1.4.2

August 20, 2001

Larry Kessler

Changes to evlnotify command

·         Added  "-action" option to be used with notify_action

·         Removed -gid as option

·         For -list, only root can view all.  Users can only list their own registrations.

·         For -remove, only root can remove any.  Users can only remove their own registrations.

1.4.3

August  27, 2001

Larry

Kessler

Added "persistent" setting to evlnotify -list option.

 

1.5

August 31, 2001

Larry Kessler

·         Changed all command options to use single-letter / full option name convention (ie. –f|--filter).

·         Renamed evl_logk() to posix_log_write() in kernel-space

1.6

September 7, 2001

Larry Kessler, Jim Keniston

·         Added new section "Query and Filter Expression Syntax Rules"

·         Minor corrections to command option descriptions

1.7

September 14, 2001

Larry Kessler

·         Replaced evl_printk() with posix_log_printf() to be consistent with changing evl_logk() to posix_log_write()

·         All kernel and user-space write functions now have a  flags argument.

·         Changed all prefixes of PXLOG_ to POSIX_LOG_ to comply with changes to draft POSIX standard

1.7.1

September 25, 2001

Larry Kessler

·         Changed evlfac command to evlfacility.  Added -k, --kernel to indicate the Facility logs from the kernel.

 

1.7.2

September 26, 2001

Larry Kessler

·         Added -change option to evlfacility command, which replaces several other options.

1.8

November 8, 2001

Larry Kessler

Jim Keniston

·         Added -o | --output option to evlconfig command

·         Added -b | --templates and -B |  --notemplates options to evlview command

·         Updated Formatting template APIs.

·         Removed Appendix C (Issues and New Requirements) since this list is kept on a separate web link - http://evlog.sourceforge.net/not_yet_available.html

·         Added  6.4.2.6   Extensions to the POSIX Standard   for event notification.

·         Added evl_vwritek() and posix_log_vprintf() in kernel space;  evl_log_vwrite() and posix_log_vprintf() in user space.

·         Added description of "syslog wrapper" in section 6.8 Modifications to Syslog

1.9

November 12, 2001

Jim Keniston

·         In the “Formatting Templates” section, documented support for cpp directives, typedefs, aligned attributes, and string/wstring template formats.

·         Edited the discussions of evlview -b and -B.

·         Added descriptions of evltc -n, -c, and -D/-U/-I.  Added discussion of invoking evltc with a binary file name.

1.10

December 21, 2001

Jim Keniston

·         In the “Formatting Templates” section: added schar to the table of data types, and adjusted char entry accordingly; documented support for C-style type names (e.g., “unsigned short”).

·         Added description of evlatt_getstructfromarray().  Added refs to this and evl_getArrayAttVal() to discussion of evl_getinfo().

·         Fixed a few typos.

1.20

February 18, 2002

Larry Kessler

Jim Keniston

·         For Formatting templates, added descriptions for event_type of "default", added descriptions for referencing members of structs, added statements about the use of templates in multithreaded environments, and added a return of EINVAL for evltemplate_initmgr() if it is called more than once by the same process.

·         Moved a section describing extensions to the POSIX standard under section 6.6.

·         Under Log Management, combined deletion and compact function in a function that does both.  Also, removed --delete option from evlogmgr command.

·         Various updates to reflect a fundamental change where user-space events are no longer written to the kernel, but passed directly to the evlogd daemon via UNIX domain socket.

·         Removed --value option from the evlfacility command.  This was removed to prevent users from "reserving" facility integer values so that a consistent algorithm for generating unique facility codes based on facility names (text strings) could be added at a later time.

·         Added APENDIX E - Date and Time formats

1.21

February 20, 2002

Larry Kessler

·         Added section 6.2.3.4, new functions for registering facilities.

1.30

March 11, 2001

Larry Kessler

·         Added new log_flags definitions for EVL_INITIAL_BOOT_EVENT and EVL_KERNTIME_LOCAL

·         Added new event_type EVLOG_REGISTER_FAC

·         Added --verify option to evlfacility command

·         Updated facility registration function descriptions, and separated kernel from user-space versions.

·         For formatting templates, added a new section describing use of templates with log_formats of  POSIX_LOG_NODATA and POSIX_LOG_STRING.

·         Numerous changes to reflect a change in the naming convention for formatting template .to files from eventtype_facility.to to facility.to

·         Added Appendix F.  Facility names and facility code creation

1.40

June 6, 2002

Larry Kessler

·         Rewrite of Log Management section (Section 6.5).

·         Added EVL_INTERRUPT and EVL_PRINTK for log_flags in event record header.

·         Removal of  "6.3 Filtering of Event Records" since there are no plans to provide this.

·         Added 6.7.1 Enhanced printk

·         Added "host" as a new non-standard attribute for evlview.

·         Addition of new evlview options:  --newlines,    --private, --datefmt, --syslog, and --recid.

 

1.41

December 6, 2002

Jim Keniston

·         Revised template-related documentation: effect of $LANG on template search; .to files now named using hex numbers, not decimal; Heather's enhancements formatting of array attributes; const structs

 



[1] Note that if the dimension attribute is zero, the array attribute is formatted as a null string, and the array is assumed to occupy no space in the event record.  Thus a “Boolean” dimension attribute (taking the value zero or one) can be used to indicate the presence or absence of one or more other “array” attributes.

[2] Since it’s a low-precision timer (1 Hz), we’ll probably just leave it in place once it’s started, rather than turning it on and off multiple times per second.  Once it expires, it won’t be restarted until duplicates start accumulating again.

[3] The age of an event record is “now” (as returned by time()) minus the record’s time stamp.  “Now” is computed each time the query is evaluated against a record, not once at the time of the call to posix_log_query_add().

[4] For example, ‘age > 7’ is equivalent to ‘age > “7d”’.