vitess.io/vitess@v0.16.2/go/event/syslogger/syslogger.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  /*
    18  Package syslogger uses the event package to listen for any event that
    19  implements the Syslogger interface. The listener calls the Syslog method on the
    20  event, which should return a severity and a message.
    21  
    22  The tag for messages sent to syslog will be the program name (os.Args[0]),
    23  and the facility number will be 1 (user-level).
    24  
    25  For example, to declare that your event type MyEvent should be sent to syslog,
    26  implement the Syslog() method to define how the message should be formatted and
    27  which severity it should have (see package "log/syslog" for details).
    28  
    29  	import (
    30  		"fmt"
    31  		"log/syslog"
    32  		"syslogger"
    33  	)
    34  
    35  	type MyEvent struct {
    36  		field1, field2 string
    37  	}
    38  
    39  	func (ev *MyEvent) Syslog() (syslog.Priority, string) {
    40  		return syslog.LOG_INFO, fmt.Sprintf("event: %v, %v", ev.field1, ev.field2)
    41  	}
    42  	var _ syslogger.Syslogger = (*MyEvent)(nil) // compile-time interface check
    43  
    44  The compile-time interface check is optional but recommended because usually
    45  there is no other static conversion in these cases. See:
    46  
    47  http://golang.org/doc/effective_go.html#blank_implements
    48  */
    49  package syslogger
    50  
    51  import (
    52  	"fmt"
    53  	"log/syslog"
    54  	"os"
    55  
    56  	"vitess.io/vitess/go/event"
    57  	"vitess.io/vitess/go/vt/log"
    58  )
    59  
    60  // Syslogger is the interface that events should implement if they want to be
    61  // dispatched to this package.
    62  type Syslogger interface {
    63  	// Syslog should return a severity (not a facility) and a message.
    64  	Syslog() (syslog.Priority, string)
    65  }
    66  
    67  // syslogWriter is an interface that wraps syslog.Writer so it can be faked.
    68  type syslogWriter interface {
    69  	Alert(string) error
    70  	Crit(string) error
    71  	Debug(string) error
    72  	Emerg(string) error
    73  	Err(string) error
    74  	Info(string) error
    75  	Notice(string) error
    76  	Warning(string) error
    77  }
    78  
    79  // writer holds a persistent connection to the syslog daemon
    80  var writer syslogWriter
    81  
    82  func listener(ev Syslogger) {
    83  	// Ask the event to convert itself to a syslog message.
    84  	sev, msg := ev.Syslog()
    85  
    86  	// Call the corresponding Writer function.
    87  	var err error
    88  	switch sev {
    89  	case syslog.LOG_EMERG:
    90  		if writer != nil {
    91  			err = writer.Emerg(msg)
    92  		} else {
    93  			log.Errorf(msg)
    94  		}
    95  	case syslog.LOG_ALERT:
    96  		if writer != nil {
    97  			err = writer.Alert(msg)
    98  		} else {
    99  			log.Errorf(msg)
   100  		}
   101  	case syslog.LOG_CRIT:
   102  		if writer != nil {
   103  			err = writer.Crit(msg)
   104  		} else {
   105  			log.Errorf(msg)
   106  		}
   107  	case syslog.LOG_ERR:
   108  		if writer != nil {
   109  			err = writer.Err(msg)
   110  		} else {
   111  			log.Errorf(msg)
   112  		}
   113  	case syslog.LOG_WARNING:
   114  		if writer != nil {
   115  			err = writer.Warning(msg)
   116  		} else {
   117  			log.Warningf(msg)
   118  		}
   119  	case syslog.LOG_NOTICE:
   120  		if writer != nil {
   121  			err = writer.Notice(msg)
   122  		} else {
   123  			log.Infof(msg)
   124  		}
   125  	case syslog.LOG_INFO:
   126  		if writer != nil {
   127  			err = writer.Info(msg)
   128  		} else {
   129  			log.Infof(msg)
   130  		}
   131  	case syslog.LOG_DEBUG:
   132  		if writer != nil {
   133  			err = writer.Debug(msg)
   134  		} else {
   135  			log.Infof(msg)
   136  		}
   137  	default:
   138  		err = fmt.Errorf("invalid syslog severity: %v", sev)
   139  	}
   140  	if err != nil {
   141  		log.Errorf("can't write syslog event: %v", err)
   142  	}
   143  }
   144  
   145  func init() {
   146  	var err error
   147  	writer, err = syslog.New(syslog.LOG_INFO|syslog.LOG_USER, os.Args[0])
   148  	if err != nil {
   149  		log.Errorf("can't connect to syslog")
   150  		writer = nil
   151  	}
   152  
   153  	event.AddListener(listener)
   154  }