[BACK]Return to ci_log.h CVS log [TXT][DIR] Up to [Development] / failsafe / FailSafe / cluster_services / include

File: [Development] / failsafe / FailSafe / cluster_services / include / ci_log.h (download)

Revision 1.2, Wed Mar 28 01:52:33 2001 UTC (16 years, 7 months ago) by scotth
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +5 -3 lines

Fix *_LOG macro definitions to be correct ANSI C preprocessor usage:
remove incorrect ## usage and replace with correct: space-char.
bugzilla #61.

/*
 * Copyright (c) 2000,2001 Silicon Graphics, Inc.  All Rights Reserved.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * 
 * Further, this software is distributed without any warranty that it is
 * free of the rightful claim of any third person regarding infringement
 * or the like.  Any license provided herein, whether implied or
 * otherwise, applies only to this software file.  Patent licenses, if
 * any, provided herein do not apply to combinations of this program with
 * other software, or any other product whatsoever.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
 * USA.
 * 
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 * Mountain View, CA 94043, or:
 * 
 * http://www.sgi.com 
 * 
 * For further information regarding this notice, see: 
 * 
 * http://oss.sgi.com/projects/GenInfo/NoticeExplan
 */
/*
 * ci_log.h
 *
 * This file contains all CHAOS logging constructs and constants.
 */
#ifndef	CI_LOG_H
#define	CI_LOG_H
#ident "$Id: ci_log.h,v 1.2 2001/03/28 01:52:33 scotth Exp $"

#include	<sys/types.h>
#include	<sys/param.h>
#include	<sys/time.h>
#include	<sys/stat.h>

#include	<stdio.h>
#include	<stdlib.h>
#include	<stdarg.h>
#include	<unistd.h>
#include        <string.h>

#include	<fcntl.h>
#include	<signal.h>
#include	<syslog.h>
#include	<assert.h>
#include	<errno.h>

#include	<ci_err.h>
#include	<pthread.h>
#include	<ci_pthread.h>
#include	<cdb.h>

/*
 * CI software uses this facility for logging and debugging.
 * CI logging can be enabled, altered or disabled dinamically.
 * Processes using the High Availability Services call the
 * main logging function (ci_log()) to "post log messages".
 * The CI log facility is responsible for filtering and
 * organizing messages. The main components of a log message
 * are listed below:
 *
 *	1)	local timestamp,
 *	2)	global logical timestamp,
 *	3)	CI error,
 *	4)	subsystem id,
 *	5)	process group id,
 *	6)	log level,
 *	7)	log string
 *
 * The first two components are automatically added by the CI
 * facility, everything else is specified by the client.
 * The last three components are used for filtering.
 * The CI log facility performs filtering based on a set of
 * variables. All the log messages are compared against
 * a "per-node" variable. If the log level in the message is
 * lower or equal to the value in the per-node variable the
 * message is accepted, otherwise the log level in the message
 * is compared againts a "per-subsystem" variable. Again if
 * the level is lower or equal the message is accepted,
 * otherwise the log level in the message is compared against
 * a "per-process group" level. If the message is lower or
 * equal the message is accepted, otherwise the message is
 * rejected.
 *
 * Log levels are defined as an integer from 1-20.
 * Level 0 is reserved,
 * Level 1 is for primary events, examples of Level 1 events
 * are hard failures and config changes,
 * Levels 2-10 are reserved for other events,
 * All the levels in the 1-10 range are defined as being of
 * interest to the system administrator.
 * Levels 11-20 are reserved for debugging.
 *
 * The CI log facility includes primitive to control the
 * frequency of duplicate logging messages, in the following
 * the term frequency will only refer to non duplicated events.
 *
 * By deafult the log level is set to 1 (CI_LOG_LVL_1).
 * Both frequency and severity should be used to determine
 * the level of admin log message (levels 1 to 10). Here're some
 * guidelines:
 *
 * frequency < one per hour			--->	low frequency,
 * one per hour < frequency < one per minute	--->	medium,
 * one per minute < frequency < one per second	--->	high,
 * one per second < frequency			--->	very high
 *
 * 
 * Events that are related to error conditions should be generally
 * considered high severity. Transient errors might be considered
 * medium severity. Configuration changes should be considered
 * either high or medium severity.
 *
 *
 *	Sev\Frq	|   low   |  medium  |   high   | very high
 *	----------------------------------------------------
 *	low	|    5    |    7     |    9	|    10    |
 *	----------------------------------------------------
 *	medium	|    1    |    3     |    5     |     7    |
 *	----------------------------------------------------
 *	high	|    1    |    1     |    1     |     1    |
 *	----------------------------------------------------
 *
 * The debug levels should be allocated using only the
 * frequency criterium. Here's a table:
 *
 *	Frequency			Levels
 *	--------------------------------------
 *	Low				11-13
 *	Medium				13-16
 * 	High				17-19
 *	Very High			20
 */

typedef struct ci_log_header_s {
	__uint32_t	magic[2];
	struct timeval	time;
	__uint64_t	gseq;
	__uint64_t	lseq;
	ci_err_t	err;
	__uint32_t	pid;
	__uint32_t	thrdid;
	__uint32_t	subsysid;
	__uint32_t	groupid;
	__uint32_t	level;
	size_t		size;
} ci_log_header_t;

#define	CI_LOG_HEADER_SIZE	(sizeof(ci_log_header_t))

/*
 * Has log config file. All the information about logging
 * is contained in a central config file.
 * Lines beginning with a '#' are considered comments.
 * Valid lines should be in the following format:
 *
 * <group> <subsys> <level> <mode> <hdr format> <debug mode> <file list>
 *
 * where:
 *
 * <group list>	 is a list of groups.  The special character '*' 
 *		 selects all groups. The list is formed by separating 
 *		 groupnames by commas. White spaces are *not* allowed.
 *
 * <subsys list> is a list of subsystems, the special character '*' selects 
 *		 all the subsystems, the special keyword 'logconf' selects 
 *		 internal logging. Subsystem list if formed by separating 
 *		 the subsystem names by commas. White spaces are *not*
 *		 allowed.
 *
 * <level> 	 is the selected logging level,
 *
 * <mode>	 selects whether the logging is performed in binary
 *		 or ASCII: the two possible values are "A" and "B",
 *
 * <hdr format>  choses the verbosity of the logging header preceding
 *		 each log message. The possible values are 'N', 'S',
 *		 'M', and 'L' - representing none, small, medium and
 *		 long respectively. Binary logging and syslog logging 
 *		 always use the long format. Stderr logging uses the
 *		 "none" format. Lower case letters can also be used in
 *		 which case the time string in the headers contains only
 *		 hh:mm:ss.msec information, day of the week and date
 *		 are not printed.
 *
 * <debug mode>  determines whether to print source filename and line
 *               number with the log message. Values can be 
 *                  'D' (debug - print source info)
 *               or 'P' (production - do not print debug info).
 *
 * <file list>	 is the list of files where the log records are to be
 *		 written, the special keywords "syslog" and "stderr"
 *		 are used to specify the SYSLOG facility and standard
 *		 error. Entries must be separated by comma, spaces and
 *		 and tabs are not allowed.
 *		 The pid of the calling process is added to the end of
 *		 the regular files.
 *
 * for example the line:
 *
 * cmsd,gcd	* 	2 B M D	/var/ha/log/all,syslog
 *
 * set the log level for the processes in the groups "cmsd" and "gcd" to 
 * 2 and writes all the messages created by the groups "cmsd" and "gcd" to 
 * the file "/var/adm/halog/all_<nodename>" and to SYSLOG.
 *
 * The same <name> may appear in several lines in the config
 * file. In that case the highest level is chosen and the output
 * is partitioned along the different bins. For example the lines:
 *
 * cmsd	*	  1 A 	S D syslog
 * cmsd	cms,ipc	  5 A	S P /var/ha/log/cms
 *
 * set the level to 5 (highest). Messages level 1 and lower will
 * go to syslog, messages up to level 5 will go to the file
 * "/var/ha/log/cms_<nodename>".
 *
 * The first valid line in the config file should contains
 * a specification to direct the messages from the log subsystem
 * to some file - the following line is an example. This is a
 * recommendation and not a requirement.
 *
 * * log 	0 A	L P /var/ha/log/loglog,<other files>
 *
 * The specified output bins will contain the error messages
 * generated by the logging facility. If one such line is not
 * found the logging facility will dump error messages in the
 * file "/var/ha/log/loglog".
 *
 * A single filename can appear on multiple lines, and thus there
 * could be conflicts in the log formats specified for a file. The
 * conflicts are resolved in the favor of longer headers over shorter
 * header and ascii output over binary output.
 *
 */

/* Log message format:
 * CI logging uses the following logging format.
 *
 * Time-string <group-name subsys-name pid:thrdid global-seqno 
 *              local-seqno src-filename:src-line-number>
 *             error-description log-message
 *
 * Time-string is the string returned by the ctime call appended by 
 * .msecs. In case lower case letters are used to specify header format,
 * the time string contains only hh:mm:ss.msec information. Logs to syslog
 * do not include this time string as syslog headers include their own time.
 * Milliseconds are however printed in syslog logs too.
 *
 * For 'S' and 's' header formats info enclosed inside <> is missing.
 * If 'M' and 'm' are chosen only the first three fileds appearing in
 * <> are printed.
 * For 'L' and 'l' header formats all fileds are printed.
 * Syslog logs do not print pid in ci headers since pid is already present
 * in syslog headers.
 *
 * Thread ids printed in the headers are logical thread ids 0,1,....,
 * and are obtained by calling ci_pthread_self(). Refer to ci_pthread.c 
 * for more details.
 *
 * If a log is printed with CI_SUCCESS no error-description will be printed.
 *
 * CI_LOG or equivalent macros must be used to be able to print source file
 * name and line numbers with log messages. If ci_log is called directly, 
 * file name will be printed as Unknown and line numbers will appear as 0.
 * The limit of maximum of pthreads that CI_LOG can support has been 
 * eliminated.
 */

/* Log levels */
/* The following hold wrt logging levels defined below:
        a. All CI_NORMAL, CI_ERROR0, and CI_ERROR1 msgs will be documented.
        b. Users will be running at level 2 (CI_ERROR1) by default.
        c. In general, different subsystems of CHAOS should log equal
           amounts of information, with some variations depending on the
           level of activity per subsystem.
        d. Depending on the option listed in the log config file, a log
           msg will be prepended by the file name and line number of the
           source line.
*/

#define CI_NORMAL	1	/* Normal operation messages that must */
				/* always be logged. */
#define CI_ERROR0	1	/* Unrecoverable errors, must be logged */
#define CI_ERROR1	2	/* Recoverable errors. */

#define CI_INFO0	5 	/* Informational messages that need to be
				   logged but not in SYSLOG. */
#define CI_INFO1	6	/* Details on logging from CI_INFO1. */
#define CI_INFO2	7	/* Informational messages that are not as
				   significant as INFO1/2. */

#define CI_DEBUG0      10	/* Used to log worthwhile positive events. */
#define CI_DEBUG1      11	/* Details on logging from CI_DEBUG0. */
#define CI_DEBUG2      12
#define CI_DEBUG3      13	/* Positive events with higher frequency. */
#define CI_DEBUG4      14       /* Details on logging from CI_DEBUG3. */
#define CI_DEBUG5      15
#define CI_DEBUG6      16       /* Data structure dumps, like msghdrs etc. */
#define CI_DEBUG7      17       /* Info msgs like fns called. */
#define CI_DEBUG8      18
#define CI_DEBUG9      19	/* Extremely high frequency messages, e.g.,
				 * messages during busy wait loop, amount
				   of memory allocated/freed. */
 
#define	CI_LOG_MAGIC	0xbacbacba

#define	CI_LOG_PATH_DEFAULT	CI_HALOG_DIR
#define	CI_LOG_CONFIG_DEFAULT	CI_HALOG_DIR "/config"
#define	CI_LOG_LOGLOG_DEFAULT	CI_HALOG_DIR "/loglog"

/*
 * The following definitions are used to generate a source
 * file that contains the names of the logging subsystems
 * and groups. The file is called ci_log_names.c.
 * When adding a new member just add a new define below,
 * the prefixes CI_LOG_SUB_ and CI_LOG_GRP_ are mandatory.
 * Remember to update the CI_LOG_MAX_ vars too.
 * Names of subsystems and groups are directly derived
 * from these by discarding the prefix and changing the rest
 * to lower case. For instance CI_LOG_SUB_SCRIPT is associated
 * with the name "script". The program used to generate
 * the file ci_log_names.c is part of the source tree.
 */

#define		CI_LOG_SUB_LOG		 0
#define		CI_LOG_SUB_TEST		 1
#define		CI_LOG_SUB_SCRIPT	 2
#define		CI_LOG_SUB_IPC		 3
#define		CI_LOG_SUB_CMS		 4
#define		CI_LOG_SUB_CMSD		 5
#define		CI_LOG_SUB_CONFIG	 6
#define		CI_LOG_SUB_GCS		 7
#define		CI_LOG_SUB_GCD		 8
#define 	CI_LOG_SUB_SRM		 9
#define		CI_LOG_SUB_MEM		10
#define		CI_LOG_SUB_IFD		11
#define		CI_LOG_SUB_FSD		12
#define		CI_LOG_SUB_CRS		13
#define		CI_LOG_SUB_MISC		14
#define		CI_LOG_SUB_AGENT	15
#define		CI_LOG_SUB_DIAGS	16
#define		CI_LOG_MAX_SUB		17

/* All cluster wide log groups must have the following prefix. */
#define		CI_LOG_GROUP_CLUSTER_PREFIX	"ha_"

#define		CI_LOG_GRP_NULL		 0
#define		CI_LOG_GRP_HA_CMSD	 1
#define		CI_LOG_GRP_CRSD	 	 2	
#define		CI_LOG_GRP_HA_GCD	 3
#define		CI_LOG_GRP_HA_IFD	 4
#define		CI_LOG_GRP_HA_SRMD	 5
#define		CI_LOG_GRP_HA_FSD	 6	
#define		CI_LOG_GRP_CLI		 7	
#define		CI_LOG_GRP_HA_SCRIPT	 8
#define		CI_LOG_GRP_TEST		 9
#define		CI_LOG_GRP_HA_AGENT	10
#define		CI_LOG_GRP_DIAGS	11
#define		CI_LOG_MAX_GRP		12

#define		CI_LOG_PREFIX	"<CI>"

#define		CI_LOG_MESSAGE_SIZE		2048
#define		CI_LOG_EVENT_NULL		0

#define		CI_LOG_HDR_NONE			0x1
#define		CI_LOG_HDR_SMALL		0x2
#define		CI_LOG_HDR_MEDIUM		0x3
#define		CI_LOG_HDR_LONG			0x4
#define		CI_LOG_HDR_MASK			0x7
#define		CI_LOG_HDR_SMALL_TIME_MASK	0x8

#define		CI_LOG_HDRSIZE_MERGE(h1, h2) \
		(((h1) & (h2) & CI_LOG_HDR_SMALL_TIME_MASK) | \
	 	 ((((h1) & CI_LOG_HDR_MASK) > ((h2) & CI_LOG_HDR_MASK)) ? \
	  	  ((h1) & CI_LOG_HDR_MASK) : ((h2) & CI_LOG_HDR_MASK)))

/*	prototypes from log/lib/src/ci_log.c	*/
boolean_t	ci_log_config_ongoing(void);
ci_err_t	ci_log_register(char *groupname, __uint32_t stderrlevel,
				char *logpath);
ci_err_t	ci_log_reinit(void);
ci_err_t	cicdb_log_register(cdb_handle_t dbhdl, char *groupname, 
				   __uint32_t stderrlevel, char *logpath);
ci_err_t	cicdb_log_reinit(cdb_handle_t);
ci_err_t	ci_log_register_general(char *groupname, 
					__uint32_t stderrlevel, 
					char *logpath, boolean_t log_restart);
void		ci_log_stderr(__uint32_t level, char hdrsize, 
			      char *subsyslist);
ci_err_t	ci_log(__uint32_t level, __uint32_t subsysid, ci_err_t err, 
		       const char *format, ...);
ci_err_t	ci_vlog(__uint32_t level, __uint32_t subsysid, ci_err_t err, 
			const char *format, va_list);
ci_err_t	ci_log_standalone(int, uint32_t, uint32_t, boolean_t, 
				  uint32_t, ci_err_t, uint32_t, 
				  const char *, ...);
ci_err_t	ci_vlog_standalone(int, uint32_t, uint32_t, boolean_t, 
				   uint32_t, ci_err_t, uint32_t, 
				   const char *, va_list);
ci_err_t	ci_log_fsync(void);
char		*ci_log_group_name_get(__uint32_t groupid);
char		*ci_log_subsys_name_get(__uint32_t subsysid);
ci_err_t	ci_log_group_id_get(char *groupname, __uint32_t *groupid);
ci_err_t	ci_log_subsys_id_get(char *subsysname, __uint32_t *subsysid);
int		ci_log_format(char *outbuf, ci_log_header_t *hdr, char *inmsg,
			      boolean_t syslogformat, int hdrsize, 
			      boolean_t debug);
void 		ci_log_filter_enable(void);
void 		ci_log_filter_disable(void);
int		ci_log_grp_cnt(void);
char		*ci_log_grp_getname(int);
boolean_t	ci_log_group_isvalid(char *group);
boolean_t	ci_log_group_is_cluster_specific(char *group);
boolean_t	ci_log_mode_isvalid(char *mode);
boolean_t	ci_log_hdrsize_isvalid(char *hdrsize);
boolean_t	ci_log_debug_isvalid(char *debug);
uint32_t	ci_log_my_groupid(void);

/* Defining the CI_LOG macro that most subsystems will use instead of 
 * calling ci_log directly. CI_LOG must be invoked using double
 * parentheses, i.e., 
 *    ci_log(foo, bar, blah,...);
 * should be replaced by 
 *    CI_LOG((foo, bar, blah,...));
 */

#define CI_LOG_START ci_pthread_set_log_info(__FILE__, __LINE__)

#define CI_LOG_END ci_pthread_reset_log_info()

#define CI_LOG(args) (CI_LOG_START, ci_log args, CI_LOG_END)

#endif	/* CI_LOG_H */