12    Administering the Basic System Event Channels

This chapter explains how system events are logged and describes how to configure the basic system event logging channels. Information on managing log files is included.

The following topics are discussed in this chapter:

12.1    Understanding the Basic Event-Logging Facilities

The operating system uses three mechanisms to log system events:

You can review events detected and recorded by syslogd and binlogd using the Event Manager, DECevent, or the error report formatter, uerf.

The Event Manager is the recommended method of administering system events. See Chapter 13 for information on configuring Event Manager. The Event Manager viewer, evmviewer, provides a graphical user interface for selecting, filtering, and displaying system events. See EVM(5) and evmviewer(8) for more information.

System events are often returned in a binary format. To render such events in a readable text format, use a translation tool such as:

The log files created by the event-logging facilities are protected and owned by root, and belong to the adm group. You must have the proper authority to examine the files.

The following sections describe the event-logging facilities.

12.1.1    System Event Logging

The primary event-logging facility uses the syslog function to log system-wide events in ASCII format. The syslog function uses the syslogd daemon to collect the messages that are logged by the various kernel, command, utility, and application programs. The syslogd daemon logs the messages to a local file or forwards the messages to a remote system, as specified in the /etc/syslog.conf file.

When you install the operating system, the /etc/syslog.conf file is created and specifies the default event-logging configuration. The /etc/syslog.conf file specifies the file names that are the destination for the event messages, which are in ASCII format. Section 12.2.1.1 discusses the /etc/syslog.conf file. See syslog.conf(4) for more information.

The /etc/syslog.auth file specifies which remote hosts are allowed to forward syslog messages to the local host. For system security, only messages coming from remote hosts listed in this file are logged by the syslogd daemon. If the /etc/syslog.auth file is not present, then event forwarding from all remote hosts is enabled.

The /etc/syslog_evm.conf file specifies which syslogd messages are forwarded from the syslogd daemon to the Event Manager, in the form of Event Manager events. Those syslogd messages are posted to the Event Manager daemon, evmd, by syslogd if the syslogd forwarding function is turned on with the -e option. Event forwarding is always on by default. Use the -E option to turn it off if required. Events are posted with the Event Manager name of sys.unix.syslog.facility.

See syslog.auth(4) and syslog_evm.conf(4) for more information.

12.1.2    Binary Event Logging

The binary event-logging facility detects hardware and software events in the kernel and logs the detailed information in binary format records. Some events that are logged by the binary event-logging facility are logged by the syslog function also, in a less detailed message.

The binary event-logging facility uses the binlogd daemon to collect various event-log records. The binlogd daemon logs these records to a local file or forwards them to a remote system, as specified in the /etc/binlog.conf default configuration file, which is created when you install your system. Section 12.2.1.3 discusses the /etc/binlog.conf file.

DECevent (or Compaq Analyze) translates binary events to ASCII reports from entries in the system's binary event log files. Invoke DECevent by entering the dia command at the command line. Entering the command without options immediately causes DECevent to access and translate the contents of the event log files, displaying the events as shown in Example 12-1. Events scroll up the terminal screen until all events are displayed or you press [Ctrl/c].

Example 12-1:  Sample Translated Event

**** V3.3  ****************** ENTRY  4 ************************    [1]
Logging OS                              2[OS]    [2]
System Architecture                     2.
Alpha Event sequence number             440. 
Timestamp of occurrence                 22-AUG-2002 18:24:31    [3] 
Host name                               Host Name
 
System type register      x0000001B     AlphaServer 800 or 1000A 
Number of CPUs (mpnum)    x00000001 
CPU logging event (mperr) x00000000 
 
Event validity    [4]                 1. O/S claims event is valid
Event severity                         5. Low Priority
Entry type                             301. Shutdown ASCII
Message Type                           -1.    - (minor class) 
SWI Minor class                        9. 
ASCII Message SWI Minor sub class      2. Shutdown  ASCII Message 
System halted by root:  System going down @ 6:24PM on 22 Aug 
Please log off in good time [5]

  1. The number of the event in the translated log. This number may be based on the selection or filtering of events. [Return to example]

  2. Identification of the operating system ([OS]) and system architecture. [Return to example]

  3. The time stamp (date and system clock time) that indicates when the event occurred and the name of the system on which it occurred (<host name>). [Return to example]

  4. Information about the validity, severity, and type of event. In this case, an informational message that the system shut down. [Return to example]

  5. The actual message logged by the event, which may have been displayed to a terminal or console also at the time the event occurred. [Return to example]

For information about administering the DECevent utility, see the following documentation:

Compaq Analyze is a rules-based hardware fault management diagnostic application that provides error event analysis and translation. The multi-event correlation analysis feature of Compaq Analyze provides you with the capability to analyze events stored in the binary system event log or other specified binary log files. When Compaq Analyze is installed, you can launch its GUI interface directly from the SysMan Station by selecting the Host Icon and selecting Compaq Analyze from the Tools menu.

12.2    Configuring Event Logging

You can change the default configuration by modifying the configuration files as described in this section. For example, you can change the configuration so that only important, system-critical events are logged and informational events are ignored. You can choose to concentrate on certain subsystems, such as mail or print services, and control how and where event messages are logged. The optimum method of monitoring system events is to use Event Manager, as described in Chapter 13. Event Manager enables you to consolidate and filter events.

To enable system and binary event-logging, the special files must exist and the event-logging daemons must be running. See Section 12.2.3 and Section 12.2.4 for more information.

The file /var/adm/syslog.dated and other files in /var/adm directory are context-dependent symbolic links (CDSLs), which facilitate joining single systems into clusters. The CDSL for the syslog directory is /var/cluster/members/member0/adm/syslog.dated. Take care not to break symbolic links when working with these files. See Chapter 6 for more information on CDSLs.

12.2.1    Editing the Configuration Files

If you do not want to use the default system or binary event-logging configuration, you can edit the /etc/syslog.conf or /etc/binlog.conf configuration file to specify how the system should log events. Specify the following data in the files:

The following sections describe how to edit the configuration files.

12.2.1.1    Editing the syslog.conf File

If you want the syslogd daemon to use a configuration file other than the default, you must specify the file name in the syslogd command, for example:

# syslogd -f config_file

The following is an example of the default /etc/syslog.conf file:

#
# syslogd config file
#
# facilities: kern user mail daemon auth syslog lpr binary
# priorities: emerg alert crit err warning notice info debug
#
# [1]  [2]                            [3]
kern.debug               /var/adm/syslog.dated/kern.log
user.debug               /var/adm/syslog.dated/user.log
daemon.debug             /var/adm/syslog.dated/daemon.log
auth.crit;syslog.debug   /var/adm/syslog.dated/syslog.log
mail,lpr.debug           /var/adm/syslog.dated/misc.log
msgbuf.err               /var/adm/crash.dated/msgbuf.savecore
kern.debug               /var/adm/messages
kern.debug               /dev/console
*.emerg                  *

Each /etc/syslog.conf file entry has the following entry syntax:

  1. Specifies the facility, which is the part of the system that generates the message. [Return to example]

  2. Specifies the severity level. The syslogd daemon logs all messages of the specified severity level plus all messages of greater severity. For example, if you specify level err, all messages of levels err, crit, alert, and emerg or panic are logged. [Return to example]

  3. Specifies the destination where the messages are logged. This can be a log file or a device such as /dev/console. [Return to example]

The syslogd daemon ignores blank lines and lines that begin with a number sign (#). Specify # as the first character in a line to include comments in the /etc/syslog.conf file or to disable an entry.

The facility and severity level are separated from the destination by one or more tab characters or spaces.

You can specify more than one facility and its severity level by separating them with semicolons. In the preceding example, messages from the auth facility of crit severity level and higher and messages from the syslog facility of debug severity level and higher are logged to the /var/adm/syslog.dated/syslog.log file.

You can specify more than one facility by separating them with commas. In the preceding example, messages from the mail and lpr facilities of debug severity level and higher are logged to the /var/adm/syslog.dated/misc.log file.

Facilities

You can specify the following facilities:

kern

Messages generated by the kernel. These messages cannot be generated by any user process.

user

Messages generated by user processes. This is the default facility.

mail

Messages generated by the mail system.

daemon

Messages generated by the system daemons.

auth

Messages generated by the authorization system, for example, login, su, and getty.

lpr

Messages generated by the line printer spooling system, for example, lpr, lpc, and lpd.

local0, local1, through local7

Reserved for local use.

mark

Receives a message of priority info every 20 minutes, unless a different interval is specified with the syslogd -m command.

msgbuf

Kernel syslog message buffer recovered from a system crash. The savecore command and the syslogd daemon use the msgbuf facility to recover system event messages from a crash.

*

Messages generated by all parts of the system.

Severity Levels

You can specify the following severity levels, which are listed in order of highest to lowest severity:

emerg or panic

A panic condition. These messages are broadcast to all users.

alert

A condition, such as a corrupted system database, that you should correct immediately.

crit

A critical condition, such as a hard device error.

err

An error message.

warning or warn

A warning message.

notice

A condition that is not an error condition, but is handled as a special case.

info

An informational message.

debug

A message containing information that is used to debug a program.

none

A mechanism to disable a specific facility's messages.

Destinations

You can specify the following message destinations:

Full pathname

Appends messages to the specified file. Direct each facility's messages to separate files; for example: kern.log, mail.log, or lpr.log.

Host name preceded by an at sign (@)

Forwards messages to the syslogd daemon on the specified host. Messages are not forwarded if the -R option is specified when the syslogd daemon is started. See Section 12.2.2 for more information.

List of users separated by commas

Writes messages to the specified users if they are logged in.

*

Writes messages to all the users who are logged in.

Daily Log Files

You can specify that the syslogd daemon create daily log files by using the following syntax to specify the pathname of the message destination:

/var/adm/syslog.dated/{file}

The file variable specifies the name of the log file, for example, mail.log or kern.log.

If you specify a /var/adm/syslog.dated/file pathname destination, each day the syslogd daemon creates a subdirectory under the /var/adm/syslog.dated directory and a log file in the subdirectory using the following syntax:

/var/adm/syslog.dated/date/file

The syslogd daemon automatically creates a new date directory every 24 hours, when you boot the system, or when the syslogd daemon is restarted or reconfigured. You can find the latest logs in the /var/adm/syslog.dated/current directory. The current directory is a symbolic link to the latest date directory.

For example, to create a daily log file of all mail messages of level info or higher, edit the /etc/syslog.conf file and include a line similar to the following:

mail.info		/var/adm/syslog.dated/mail.log
 

If you specify the previous line in the /etc/syslog.conf, the syslogd daemon creates the following daily directory and file:

/var/adm/syslog.dated/11-Jan-12:10/mail.log

12.2.1.2    Configuring syslog to Use Event Manager

By default, syslogd is configured with the -e option to forward events to Event Manager. (See Section 12.2.4). You can select which syslog events are forwarded to the Event Manager by modifying the syslog_evm.conf file. If the file does not exist, or if it exists but contains no subscription entries, no syslog messages are posted to the Event Manager.

The default syslog_evm.conf file contains entries similar to those shown in Example 12-2, which excludes the informational file header.

Example 12-2:  Sample syslog_evm.conf File Entries

[1]  [2]
*.emerg
# above forwards all emergency events to EVM  [3]
kern.info+   [4]
user.notice+
mail.notice+
daemon.notice+
auth.notice+
syslog.notice+

  1. The first part of each line item specifies which facility generated the message, such as kern for kernel. An asterisk (*) indicates that all facilities are selected. In this case, *.emerg ensures that all messages of emergency priority are forwarded to Event Manager.

    You can choose which events are forwarded by creating an entry for a facility, or removing an existing entry. Entries are based on the keywords in the facility table in Section 12.2.1.1. [Return to example]

  2. The second part of each item specifies the priority of messages, based on the keywords in the severity level table in Section 12.2.1.1. [Return to example]

  3. You can add comments, preceded by a number sign (#). However, you cannot mix forwarding entries and comments in the same line [Return to example]

  4. The plus sign (+) appended to a priority indicates that the specified priority and all higher priority messages are forwarded. If you want to choose individual severity levels for a facility, such as warning, critical and emergency, create a line for each priority. [Return to example]

Events are posted with the Event Manager name of sys.unix.syslog.facility.

See syslog_evm.conf(4) and Chapter 13 for more information.

12.2.1.3    Editing the binlog.conf File

If you want the binlogd daemon to use a configuration file other than the default, specify the file name with the binlogd -fconfig_file command. The binlogd daemon forwards all events to the Event Manager. You can filter and select binlog events using Event Manager utilities, as described in Chapter 13.

You can forward binlogd events to a remote host. See binlogd(8) for information on the remote logging options. The -R and -r options are important because they control the creation of an inet port for remote access.

The following is an example of a /etc/binlog.conf file:

#
# binlogd configuration file
#
# format of a line:   event_code.priority         destination
#
# where:
# event_code - see codes in binlog.h and man page, * = all events
# priority   - severe, high, low, * = all priorities
# destination - local file pathname or remote system hostname
#
#
*.*			/usr/adm/binary.errlog
dumpfile		/usr/adm/crash/binlogdumpfile
102.high		/usr/adm/disk.errlog
[1]  [2]                   [3]

Each entry in the /etc/binlog.conf file, except the dumpfile event class entry, contains three fields:

  1. Specifies the event class code that indicates the part of the system generating the event. [Return to example]

  2. Specifies the severity level of the event. Do not specify a severity level if you specify dumpfile for an event class. [Return to example]

  3. Specifies the destination where the binary event records are logged. [Return to example]

The binlogd daemon ignores blank lines and lines that begin with a number sign (#). You can specify # as the first character in a line to include comments in the file or to disable an entry.

The event class and severity level are separated from the destination by one or more tab characters or spaces.

You can specify the following event class codes:

Class Code Description
General
* Specifies all event classes.
dumpfile Specifies the recovery of the kernel binary event log buffer from a crash dump. A severity level cannot be specified.
Hardware-Detected Events
100 CPU machine checks and exceptions, or generalized exception fault
101 Memory
102 Disk
103 Tape
104 Device controller
105 Adapter
106 Bus
107 Stray interrupt
108 Console event
109 Stack dump
110 Generalized machine state
113 Double error halt
115 (Un)correctable environmental
120 Reporting of correctables disabled
195 StorageWorks Command Console (SWCC)
196 I2O block storage
198 SWXCR RAID controller
199 SCSI CAM
Software-Detected Events
201 CI port-to-port-driver
202 System communications services
203 LSM note
204 LSM warning
205 LSM continuation
206 AdvFS domain panic
Informational ASCII Messages
250 Generic informational ASCII message
Operational Events
300 Startup ASCII message
301 Shutdown ASCII message
302 ASCII Panic message
310 Time stamp
350 Diagnostic status ASCII message
351 Repair and maintenance ASCII message
400 Filterlog event. (Use only with filterlog)

Severity Levels

You can specify the following severity levels:

*

All severity levels

severe

Unrecoverable events that are usually fatal to system operation

high

Recoverable events or unrecoverable events that are not fatal to system operation

low

Informational events

Destinations

You can specify the following destinations:

Full pathname

Specifies the file name to which the binlogd daemon appends the binary event records.

@hostname

Specifies the name of the host, preceded by an at sign (@), to which the binlogd daemon forwards the binary event records. If you specify dumpfile for an event class, you cannot forward records to a host.

Operational timestamp (310) events are not forwarded automatically.

12.2.2    Remote Messages and syslog Security

Unless the domain host name of a remote host is entered in the local /etc/syslog.auth file, the local system does not log any syslog messages from that remote host. If you intend to make syslogd secure on your system, and you have configured or intend to configure other hosts to forward syslog messages to the system, complete the following steps:

  1. Use the su command to become the superuser (root).

  2. Create the /etc/syslog.auth file using a text editor.

  3. Add the names of any remote hosts that are allowed to forward syslog messages to the local system to the /etc/syslog.auth file. Host names must meet the following criteria:

  4. Ensure that the /etc/syslog.auth is owned by root.

    # chown root /etc/syslog.auth
    

  5. Ensure that the /etc/syslog.auth have its permissions set to 0600.

    # chmod 0600 /etc/syslog.auth
    

Specify the -R option when starting the daemon if you do not want the syslogd daemon to create an inet port to listen for events being sent by remote hosts. To make this the default mode of operation, edit the startup command line in the /sbin/init.d/syslog file. Using the -R option means that the syslogd daemon cannot forward events to other systems.

See syslog.auth(4) and syslogd(8) for more information.

12.2.3    Creating the Special Files

The syslogd daemon cannot log kernel messages unless the /dev/klog character special file exists. If the /dev/klog file does not exist, create it as follows:

# /dev/MAKEDEV /dev/klog

Also, the binlogd daemon cannot log local system events unless the /dev/kbinlog character special file exists. If the /dev/kbinlog file does not exist, create it as follows:

# /dev/MAKEDEV /dev/kbinlog

See MAKEDEV(8) for more information.

12.2.4    Starting and Stopping the Event-Logging Daemons

The syslogd and binlogd daemons are started automatically by the init program during system startup. However, you must ensure that the daemons are started. You can specify options when you start the daemons also.

12.2.4.1    The syslogd Daemon

You must ensure that the init program starts syslogd daemon. If the syslogd daemon does not start, or if you want to specify options with the command that starts the syslogd daemon, you must edit the /sbin/init.d/syslog file. When you edit the file, you either must include or modify the syslogd command line. You also can invoke the command manually.

The command that starts the syslogd daemon has the following syntax:

/usr/sbin/syslogd [-b rcvbufsz] [-d] [ -e | -E ] [-f config_file] [-m mark_interval] [-p path] [ -r | -R ] [-s]

The initialization of the daemon uses only the -e option by default. The -e option configures the daemon to forward events to the Event Manager automatically. You can verify the current syslogd configuration using the ps command as follows:

# /sbin/ps agx | grep syslogd
261 ??    S    0:00:10  usr/sbin/syslogd -e

See syslogd(8) for information on the command options.

Note

You must ensure that the /var/adm directory is mounted, or the syslogd daemon does not work correctly.

The syslogd daemon reads messages from the following:

Messages from other programs use the openlog, syslog, and closelog calls.

When the syslogd daemon is started, it creates the /var/run/syslog.pid file, where the syslogd daemon stores its process identification number. Use the process identification number to stop the syslogd daemon before you shut down the system.

During normal system operation, the syslogd daemon is called if data is put in the kernel syslog message buffer, located in physical memory. The syslogd daemon reads the /dev/klog file and gets a copy of the kernel syslog message buffer. The syslogd daemon starts at the beginning of the buffer and sequentially processes each message that it finds. Each message is prefixed by facility and priority codes, which are the same as those specified in the /etc/syslog.conf file. The syslogd daemon then sends the messages to the destinations specified in the file.

To stop the syslogd event-logging daemon, use the following command:

# kill `cat /var/run/syslog.pid` 

Using the following command, you can apply changes to the /etc/syslog.conf configuration file without restarting the daemon:

# kill -HUP `cat /var/run/syslog.pid` 

12.2.4.2    The binlogd Daemon

You must ensure that the init program starts the binlogd daemon. If the binlogd daemon does not start, or if you want to specify options with the command that starts the binlogd daemon, edit the /sbin/init.d/binlog file and either include or modify the binlogd command line. You can invoke the command manually also. The binlogd command supports the following options

/usr/sbin/syslogd [-d] [-f config_file] [ -r | -R ]

See binlogd(8) for information on command options.

The binlogd daemon reads binary event records from the following:

When the binlogd daemon starts, it creates the /var/run/binlogd.pid file, where the binlogd daemon stores its process identification number. Use the process identification number to stop or reconfigure the binlogd daemon.

During normal system operation, the binlogd daemon is called if data is put into the kernel's binary event-log buffer or if data is received on the Internet domain socket. The binlogd daemon then reads the data from the /dev/kbinlog special file or from the socket. Each record contains an event class code and a severity level code. The binlogd daemon processes each binary event record and logs it to the destination specified in the /etc/binlog.conf file.

To stop the binlogd daemon, use the following command:

# kill `cat /var/run/binlogd.pid` 

You can apply changes to the /etc/binlog.conf configuration file without restarting the daemon by using the following command:

# kill -HUP `cat /var/run/binlogd.pid` 

12.2.5    Configuring the Kernel Binary Event Logger

To configure the kernel binary event logger, modify the default keywords and rebuild the kernel. You can:

The /sys/data/binlog_data.c file defines the binary event-logger configuration. The default configuration specifies a buffer size of 24K bytes, enables binary event logging, and disables the logging of kernel ASCII messages. You can modify the configuration by changing the values of the binlog_bufsize and binlog_status keywords in the file.

The binlog_bufsize keyword specifies the size of the kernel buffer that the binary event logger uses. The size of the buffer can be between 8 kB (8,192 bytes) and 1 MB (1,048,576 bytes). Small system configurations, such as workstations, can use a small buffer. Large server systems that use many disks may need a large buffer.

The binlog_status keyword specifies the behavior of the binary event logger. You can specify the following values for the binlog_status keyword:

0 (zero)

Disables the binary event logger.

BINLOG_ON

Enables the binary event logger.

BINLOG_ASCIION

Enables the logging of kernel ASCII messages into the binary event log if the binary event logger is enabled. This value must be specified with the BINLOG_ON value as follows: int binlog_status = BINLOG_ON | BINLOG_ASCII;

You must rebuild and boot the new kernel after you modify the /sys/data/binlog_data.c file.

12.3    Recovering Event Logs After a System Crash

You can recover unprocessed messages and binary event-log records from a system crash when you reboot the system.

The msgbuf.err entry in the /etc/syslog.conf file specifies the destination of the kernel syslog message buffer msgbuf that is recovered from the dump file. The default /etc/syslog.conf file entry for the kernel syslog message buffer file follows:

msgbuf.err            /var/adm/crash/msgbuf.savecore
 

The dumpfile entry in the /etc/binlog.conf file specifies the file name destination for the kernel binary event-log buffer that is recovered from the dump file. The default /etc/binlog.conf file entry for the kernel binary event-log buffer file follows:

dumpfile              /usr/adm/crash/binlogdumpfile
 

If a crash occurs, the syslogd and binlogd daemons cannot read the /dev/klog and /dev/kbinlog special files and process the messages and binary event records. When you reboot the system, the savecore command runs and, if a dump file exists, recovers the kernel syslog message and binary event-log buffers from the dump file. After savecore runs, the syslogd and binlogd daemons are started.

The syslogd daemon reads the syslog message buffer file, verifies that its data is valid, and then processes it in the same way that it normally processes data from the /dev/klog file, using the information in the /etc/syslog.conf file.

The binlogd daemon reads the binary event-log buffer file, verifies that its data is valid, and then processes the file in the same way that it processes data from the /dev/kbinlog special file, using the information in the /etc/binlog.conf file.

After the syslogd and binlogd daemons are finished with the buffer files, the files are deleted.

12.4    Managing Log Files

On a well maintained system, the size of the various log files should not become a problem when you:

The /var/spool/cron/crontabs/root file contains the following model entry for managing log files:

0 2 * * 0 /usr/lbin/logclean /var/adm/wtmp > /dev/null
 
 

You can use the cron daemon to specify that other log files be deleted. However, you should take care that important log files are stored or archived according to your local site requirements.

The following is an example of a crontab file entry that cleans up the older logs in the /var/adm/syslog.dated directory:

40 4 * * * find /var/adm/syslog.dated/* -depth -type d -ctime +7 -exec rm -rf {}\;
 

This entry causes all directories under the /var/adm/syslog.dated directory (and their contents) that were created more than seven days ago to be deleted every day at 4:40. See Chapter 3 and crontab(1) for more information.

12.5    Startup Log Messages in /var/adm/messages

The number of messages stored depends on the size of the message buffer used to store boot-log messages, which is controlled by the msgbuf_size kernel attribute. The minimum default value for this attribute is 8K bytes, for systems with up to 128 MB of physical memory. For systems with greater than 128 MB of physical memory, the value of msgbuf_size is calculated and set automatically at 64 bytes for every 1MB of memory. For example, in a system with 512 MB, the value is 512 * 64 bytes, or 32,768 bytes , which is equivalent to 32K bytes.

For large systems with many adapters and devices, the default value may be insufficient, causing messages to be dropped from the /var/adm/messages file. For large-memory systems that have few devices, the value can be too high and you may want to reclaim the buffer space.

If your system's boot-log record is incomplete, or if you want to reduce the assigned value to reclaim the buffer space, use the following procedure to modify the value of the msgbuf_size attribute:

  1. Invoke the dxkerneltuner graphical user interface from the command line.

  2. Select the generic subsystem and select Select Subsystem. The Subsystem Attributes dialog box labeled generic opens.

  3. Locate the msgbuf_size and enter the new value for the Boot Time Value.

  4. Select OK to apply the changes and close the dialog box.

  5. Select Reset All from the Option menu in the main window.

  6. Select Exit from the File menu in the main window.

You can use the sysconfig and sysconfigdb commands to implement this change instead, as described in Chapter 4.