Sunday, November 2, 2014

Unix Prog: Daemon Error Logging

1. Unix Syslog Architecture

syslogd is a daemon process. When it starts up, it reads one config file to determine which classes of messages to go to which destination. 

1) user process can call "syslog" system call to write to /dev/log which will interact with syslogd to write logs
2) remote process which is connected to this host by TCP/IP could also send log messages to UDP port 514. But note that syslog function doesn't generate the UDP datagrams.

2. System Calls:

System Definition:

 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/syslog.h  
 ......  
 /* Close descriptor used to write to system logger.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void closelog (void);  
   
 /* Open connection to system logger.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void openlog (const char *__ident, int __option, int __facility);  
   
 /* Set the log mask level. */  
 extern int setlogmask (int __mask) __THROW;  
   
 /* Generate a log message using FMT string and option arguments.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern void syslog (int __pri, const char *__fmt, ...)  
    __attribute__ ((__format__ (__printf__, 2, 3)));  
   
 #ifdef __USE_BSD  
 /* Generate a log message using FMT and using arguments pointed to by AP.  
   
   This function is not part of POSIX and therefore no official  
   cancellation point. But due to similarity with an POSIX interface  
   or due to the implementation it is a cancellation point and  
   therefore not marked with __THROW. */  
 extern void vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap)  
    __attribute__ ((__format__ (__printf__, 2, 0)));  
 ......  

Calling openlog and closelog is optional. If openlog is not called, the first time syslog is called, openlog will be called automatically.

Calling openlog lets us specify an ident that is added to each log message, which is normally the name of the program. And option(2nd argument is a bitmask specifying options. facility(3rd argument) is to let the configuration file specify that messages from different facilities are to be handled differently.

options and facilities:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/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 internally 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 */  
   
 #define LOG_NFACILITIES 24   /* current number of facilities */  
 #define LOG_FACMASK   0x03f8 /* mask to extract facility part */  
                 /* facility of pri */  
 #define LOG_FAC(p)   (((p) & LOG_FACMASK) >> 3)  
 ......  
 /*  
  * Option flags for openlog.  
  *  
  * LOG_ODELAY no longer does anything.  
  * LOG_NDELAY is the inverse of what it used to be.  
  */  
 #define LOG_PID     0x01  /* log the pid with each message */  
 #define LOG_CONS    0x02  /* log on the console if errors in sending */  
 #define LOG_ODELAY   0x04  /* delay open until first syslog() (default) */  
 #define LOG_NDELAY   0x08  /* don't delay open */  
 #define LOG_NOWAIT   0x10  /* don't wait for console forks: DEPRECATED */  
 #define LOG_PERROR   0x20  /* log to stderr as well */  
 ......  

For syslog, first argument(priority) is the combination of "priorities" and "facilities", and character %m in the 2nd argument will be replaced by the error message corresponding to the errno variable value.

Priorities:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/syslog.h  
 ......  
 /*  
  * priorities/facilities are encoded into a single 32-bit quantity, where the  
  * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility  
  * (0-big number). Both the priorities and the facilities map roughly  
  * one-to-one to strings in the syslogd(8) source code. This mapping is  
  * included in this file.  
  *  
  * priorities (these are ordered)  
  */  
 #define LOG_EMERG    0    /* system is unusable */  
 #define LOG_ALERT    1    /* action must be taken immediately */  
 #define LOG_CRIT    2    /* critical conditions */  
 #define LOG_ERR     3    /* error conditions */  
 #define LOG_WARNING   4    /* warning conditions */  
 #define LOG_NOTICE   5    /* normal but significant condition */  
 #define LOG_INFO    6    /* informational */  
 #define LOG_DEBUG    7    /* debug-level messages */  
   
 #define LOG_PRIMASK   0x07  /* mask to extract priority part (internal) */  
                 /* extract priority */  
 #define LOG_PRI(p)   ((p) & LOG_PRIMASK)  
 #define LOG_MAKEPRI(fac, pri)  ((fac) | (pri))  
 ......  

setlogmask can setup the priorities mask to allow only masked logs to be written to file.

setlogmask arguments:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/syslog.h  
 ......  
 /*  
  * arguments to setlogmask.  
  */  
 #define LOG_MASK(pri)  (1 << (pri))      /* mask for one priority */  
 #define LOG_UPTO(pri)  ((1 << ((pri)+1)) - 1) /* all priorities through pri */  
 ......  

2. Example:
syslog.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<syslog.h>  
   
 int main(int argc, char* argv[])  
 {  
  // Add the identical string "testlog" in front of each message  
  // Options: Add the process id to identify each message  
  //     If log is error in being sent, output to console  
  // Facility: random user-level messages  
  openlog("testlogging", LOG_PID | LOG_CONS, LOG_USER);  
  syslog(LOG_ERR, "My logs with LOG_ERR!");  
  syslog(LOG_ALERT, "My logs with LOG_ALERT!");  
  syslog(LOG_ALERT | LOG_DAEMON, "My logs with LOG_DAEMON"); // with different facility  
   
  // Only LOG_CRIT is masked, meaning that only LOG_CRIT logs are written to file  
  setlogmask(LOG_MASK(LOG_CRIT));  
  syslog(LOG_ALERT, "My logs with LOG_ALERT!");  
  syslog(LOG_CRIT, "My logs with LOG_CRIT!");  
   
  // From LOG_EMERG to(including) LOG_CRIT are masked  
  setlogmask(LOG_UPTO(LOG_CRIT));  
  syslog(LOG_EMERG, "My logs with LOG_EMERG!");  
  syslog(LOG_ALERT, "My logs with LOG_ALERT!");  
  syslog(LOG_CRIT, "My logs with LOG_CRIT!");  
  closelog();  
   
  exit(0);  
 }  

shell:
 ubuntu@ip-172-31-23-227:~$ ./log.out  
 ubuntu@ip-172-31-23-227:~$ grep "testlogging" /var/log/syslog  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_ERR!  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_ALERT!  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_DAEMON  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_CRIT!  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_EMERG!  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_ALERT!  
 Nov 2 23:51:56 ip-172-31-23-227 testlogging[30275]: My logs with LOG_CRIT!  

No comments:

Post a Comment