UnixSyslogInterface.st
author Claus Gittinger <cg@exept.de>
Tue, 09 Jul 2019 20:55:17 +0200
changeset 24417 03b083548da2
parent 24134 f9943388947a
child 25290 6cc4b317c2ab
permissions -rw-r--r--
#REFACTORING by exept class: Smalltalk class changed: #recursiveInstallAutoloadedClassesFrom:rememberIn:maxLevels:noAutoload:packageTop:showSplashInLevels: Transcript showCR:(... bindWith:...) -> Transcript showCR:... with:...

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 2018 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.  This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic' }"

"{ NameSpace: Smalltalk }"

MiniLogger subclass:#UnixSyslogInterface
	instanceVariableNames:''
	classVariableNames:'LOG_EMERG LOG_ALERT LOG_CRIT LOG_ERR LOG_WARNING LOG_NOTICE
		LOG_INFO LOG_DEBUG LOG_KERN LOG_USER LOG_MAIL LOG_DAEMON LOG_AUTH
		LOG_SYSLOG LOG_LPR LOG_NEWS LOG_UUCP LOG_CRON LOG_AUTHPRIV
		LOG_FTP LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4
		LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_PID LOG_CONS LOG_ODELAY
		LOG_NDELAY LOG_PERROR PriorityMapping DefaultSyslogFacility
		DefaultSyslogFacilityString PriorityToStringMapping UseCommand'
	poolDictionaries:''
	category:'System-Debugging-Support'
!

!UnixSyslogInterface class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2018 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.  This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.

"
!

documentation
"
    This logger logs messages via the Unix/Linux syslog system call
    (so it is not available in Windows).
    It uses any log method implemented in the syslog system call, e.g.
    logging via network.

    [author:]
        Stefan Vogel

    [class variables:]
        DefaultSyslogFacility   Integer     the default facility of syslog (e.g. self LOG_LOCAL0).
                                            This is different from the Logger facility arg.

    [see also:]
        MiniLogger
"
!

examples
"
                                                            [exBegin]
    Logger := self.
    self info:'%1 info demo » (%2%)' with:'stx' with:16.
    self warning:'%1 warning demo (%2%)' with:'stx' with:16.
    self error:'%1 error demo (%2%)' with:'stx' with:16.
    self fatal:'%1 fatal demo (%2%)' with:'stx' with:16.
    Logger := MiniLogger.
                                                            [exEnd]

                                                            [exBegin]
    self openlog:'stx' option:0 facility:self LOG_USER.
    self syslog:self LOG_WARNING message:'%1 demo (%2%)' arguments:#('stx' 16).
    self closelog.
                                                            [exEnd]
"
! !

!UnixSyslogInterface class methodsFor:'initialization'!

initialize

    "/ Priorities
    PriorityMapping := Dictionary new.
    PriorityMapping 
        at:FATAL    put:0;     "/ LOG_EMERG: system is unusable
                               "/ 1 LOG_ALERT: action must be taken immediately  
                               "/ 2 LOG_CRIT: critical conditions  
        at:ERROR    put:3;     "/ LOG_ERR: error conditions 
        at:WARNING  put:4;     "/ LOG_WARNING: warning conditions 
        at:WARN     put:4;
                               "/ 5 LOG_NOTICE: normal but significant condition  
        at:INFO     put:6;     "/ LOG_INFO: informational
        at:DEBUG    put:7;     "/ LOG_DEBUG: informational
        at:TRACE0   put:7;     "/ LOG_DEBUG: informational
        at:TRACE1   put:7;     "/ LOG_DEBUG: informational
        at:TRACE2   put:7;     "/ LOG_DEBUG: informational
        at:TRACE3   put:7;     "/ LOG_DEBUG: informational
        at:ENTER    put:7;     "/ LOG_DEBUG: informational
        at:LEAVE    put:7.     "/ LOG_DEBUG: informational

    "/ Facilities
    LOG_KERN   := (0<<3).  "/ kernel messages 
    LOG_USER   := (1<<3).  "/ random user-level messages  
    LOG_MAIL   := (2<<3).  "/ mail system  
    LOG_DAEMON := (3<<3).  "/ system daemons  
    LOG_AUTH   := (4<<3).  "/ security/authorization messages  
    LOG_SYSLOG := (5<<3).  "/ messages generated internally by syslogd  
    LOG_LPR    := (6<<3).  "/ line printer subsystem  
    LOG_NEWS   := (7<<3).  "/ network news subsystem  
    LOG_UUCP   := (8<<3).  "/ UUCP subsystem  
    LOG_CRON   := (9<<3).  "/ clock daemon  
    LOG_AUTHPRIV := (10<<3). "/ security/authorization messages (private)  
    LOG_FTP    := (11<<3). "/ ftp daemon  

           "/ other codes through 15 reserved for system use  
    LOG_LOCAL0 := (16<<3). "/ reserved for local use  
    LOG_LOCAL1 := (17<<3). "/ reserved for local use  
    LOG_LOCAL2 := (18<<3). "/ reserved for local use  
    LOG_LOCAL3 := (19<<3). "/ reserved for local use  
    LOG_LOCAL4 := (20<<3). "/ reserved for local use  
    LOG_LOCAL5 := (21<<3). "/ reserved for local use  
    LOG_LOCAL6 := (22<<3). "/ reserved for local use  
    LOG_LOCAL7 := (23<<3). "/ reserved for local use

    "/ Options
    LOG_PID    := 16r01.    "/ log the pid with each message 
    LOG_CONS   := 16r02.    "/ log on the console if errors in sending  
    LOG_ODELAY := 16r04.    "/ delay open until first syslog() (default)  
    LOG_NDELAY := 16r08.    "/ don't delay open  
    LOG_PERROR := 16r20.    "/ log to stderr as well

    DefaultSyslogFacility := LOG_LOCAL4.
    DefaultSyslogFacilityString := 'local4'.
    PriorityToStringMapping := #('emerg' 'alert' 'crit' 'err' 'warning' 'notice' 'info' 'debug').

    "/ no access to FFI / ObjectFileLoader here; do this lazy, when actually needed
    UseCommand := nil.

    "Created: / 24-02-2018 / 15:37:22 / stefan"
    "Modified: / 22-07-2018 / 15:21:01 / Stefan Vogel"
    "Modified: / 24-10-2018 / 19:38:10 / Claus Gittinger"
! !

!UnixSyslogInterface class methodsFor:'accessing'!

defaultSyslogFacility
    ^ DefaultSyslogFacility
!

defaultSyslogFacility:anInteger
    "set the default facility of syslog (e.g. self LOG_LOCAL0).
     This is different from the Logger facility arg."

    DefaultSyslogFacility := anInteger.

    "Modified (comment): / 28-06-2018 / 11:37:16 / Stefan Vogel"
! !

!UnixSyslogInterface class methodsFor:'accessing-facilities'!

LOG_AUTH
    ^ LOG_AUTH
!

LOG_AUTHPRIV
    ^ LOG_AUTHPRIV
!

LOG_CRON
    ^ LOG_CRON
!

LOG_DAEMON
    ^ LOG_DAEMON
!

LOG_FTP
    ^ LOG_FTP
!

LOG_KERN
    ^ LOG_KERN
!

LOG_LOCAL0
    ^ LOG_LOCAL0
!

LOG_LOCAL1
    ^ LOG_LOCAL1
!

LOG_LOCAL2
    ^ LOG_LOCAL2
!

LOG_LOCAL3
    ^ LOG_LOCAL3
!

LOG_LOCAL4
    ^ LOG_LOCAL4
!

LOG_LOCAL5
    ^ LOG_LOCAL5
!

LOG_LOCAL6
    ^ LOG_LOCAL6
!

LOG_LOCAL7
    ^ LOG_LOCAL7
!

LOG_LPR
    ^ LOG_LPR
!

LOG_MAIL
    ^ LOG_MAIL
!

LOG_NEWS
    ^ LOG_NEWS
!

LOG_SYSLOG
    ^ LOG_SYSLOG
!

LOG_USER
    ^ LOG_USER
!

LOG_UUCP
    ^ LOG_UUCP
! !

!UnixSyslogInterface class methodsFor:'accessing-options'!

LOG_CONS
    ^ LOG_CONS
!

LOG_NDELAY
    ^ LOG_NDELAY
!

LOG_ODELAY
    ^ LOG_ODELAY
!

LOG_PERROR
    ^ LOG_PERROR
!

LOG_PID
    ^ LOG_PID
! !

!UnixSyslogInterface class methodsFor:'accessing-priorities'!

LOG_ALERT
    ^ LOG_ALERT
!

LOG_CRIT
    ^ LOG_CRIT
!

LOG_DEBUG
    ^ LOG_DEBUG
!

LOG_EMERG
    ^ LOG_EMERG
!

LOG_ERR
    ^ LOG_ERR
!

LOG_INFO
    ^ LOG_INFO
!

LOG_NOTICE
    ^ LOG_NOTICE
!

LOG_WARNING
    ^ LOG_WARNING
! !

!UnixSyslogInterface class methodsFor:'api'!

apiSyslog:priority format:format message:message
    <cdecl: int 'syslog' (int char* char*) >
    ^ self primitiveFailed.

    "
        self openlog:'stx2' option:0 facility:self LOG_LOCAL7.
        self syslog:self LOG_WARNING message:'stx %% demo'.
        self closelog.
    "

    "Created: / 27-06-2018 / 23:11:57 / Stefan Vogel"
!

closelog
    <cdecl: int 'closelog' (void) >
    ^ self primitiveFailed.

    "Created: / 24-02-2018 / 13:35:20 / stefan"
    "Modified: / 24-02-2018 / 22:54:55 / stefan"
!

libraryName
    ^ 'libc.so.6'

    "Created: / 24-02-2018 / 13:39:49 / stefan"
    "Modified: / 22-07-2018 / 15:22:49 / Stefan Vogel"
!

openlog:ident option:option facility:facility
    <cdecl: int 'openlog' (char* int int) >
    ^ self primitiveFailed.

    "
        self new openlog:'stx' option:0 facility:0.
        self new closelog.
    "

    "Created: / 24-02-2018 / 13:27:11 / stefan"
    "Modified: / 24-02-2018 / 22:55:01 / stefan"
! !

!UnixSyslogInterface class methodsFor:'logging'!

syslog:priority message:message arguments:argArray
    self apiSyslog:priority format:'%s' message:(message bindWithArguments:argArray).


    "
        self openlog:'stx' option:0 facility:self LOG_USER.
        self syslog:self LOG_WARNING message:'%1 demo (%2%)' arguments:#('stx' 16).
        self closelog.
    "

    "Created: / 24-02-2018 / 23:16:05 / stefan"
    "Modified: / 27-06-2018 / 23:13:23 / Stefan Vogel"
! !

!UnixSyslogInterface class methodsFor:'private'!

basicLog:message severity:severity facility:facility originator:originator attachment:attachment
    |priority messageAsSent|

    priority := PriorityMapping at:severity ifAbsent:5.
    messageAsSent := 
            '%1%2%3: %4'
                bindWith:(facility ? 'STX')
"/                with:'' "/ severity name
"/                with:'' "/ (Timestamp now printStringFormat:(self timestampFormat))
                with:(originator notEmptyOrNil ifTrue:'+' ifFalse:[''])
                with:originator
                with:message.

    messageAsSent := messageAsSent string.  "take care of Texts"

    UseCommand isNil ifTrue:[
        "/ determine if a shell-command should be used, or if an FFI call can be used
        "/ if we have FFI support, we do not have to use the command.
        "/ No reference to ObjectFileLoader (in different package) here.
        "/ otherwise, standalone programs without libcomp will no longer work
        "/ (especially tests in stc/tests)
        UseCommand := [
                          self closelog. "/ an FFI-call
                          false.
                      ] on:(Error "PrimitiveFailure, ObjectFileLoader::ObjectFileLoadError") do:[
                          true.
                      ].
    ].
    
    UseCommand ifTrue:[
        "if we do not support FFI, use a comman interface"
        OperatingSystem 
"/ --id doesn't work with RedHat 7.0
"/            executeCommand:('/usr/bin/logger --id=%1 -p %2.%3' 
            executeCommand:('/usr/bin/logger -p %2.%3' 
                             bindWith:OperatingSystem getProcessId 
                                 with:DefaultSyslogFacilityString with:(PriorityToStringMapping at:priority+1))
            inputFrom:messageAsSent readStream
            outputTo:nil
            errorTo:Transcript.
        ^ self.
    ].

    messageAsSent containsNon7BitAscii ifTrue:[
        messageAsSent := OperatingSystem encodePath:messageAsSent.
    ].
    self apiSyslog:(priority bitOr:DefaultSyslogFacility) format:'%s' message:messageAsSent.

    "
        self warning:'%1 warning demo » (%2%)' with:'stx' with:16.
        self fatal:'%1 fatal demo (%2%)' with:'stx' with:16.
        self closelog.
    "

    "Created: / 28-06-2018 / 11:08:04 / Stefan Vogel"
    "Modified: / 12-09-2018 / 12:31:13 / Stefan Vogel"
    "Modified: / 24-10-2018 / 19:39:05 / Claus Gittinger"
! !

!UnixSyslogInterface class methodsFor:'queries'!

canLog
    ^ true

    "Created: / 28-06-2018 / 11:55:46 / Stefan Vogel"
! !

!UnixSyslogInterface class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !


UnixSyslogInterface initialize!