Compare commits

...

2 Commits

Author SHA1 Message Date
dave 2e262a63a8 add nagios mode
Gitea/etcdmtr/pipeline/head This commit looks good Details
2024-03-12 21:08:14 -07:00
dave 15b1dffa32 add fatalhandler to logger, called to handle a fatal log message 2024-03-12 21:08:07 -07:00
2 changed files with 57 additions and 26 deletions

View File

@ -25,6 +25,7 @@ type EtcdMtrArgs struct {
Timeout int `short:"t" long:"timeout" description:"Operation timeout in seconds"`
ExpectedMembers int `short:"m" long:"members" description:"Expect at least this many members"`
Debug bool `long:"debug" description:"Show debug output and etcd messages"`
Nagios bool `long:"nagios" description:"Output nagios/nrpe format"`
}
type Client struct {
@ -107,17 +108,33 @@ func main() {
logger := etcdmtr.NewRootLogger()
if args.Nagios {
fatalHandler := func(logger *etcdmtr.ELog, exitCode int, message string, a ...any) {
code2name := []string{"OK", "WARNING", "CRITICAL", "UNKNOWN"}
msg := fmt.Sprintf(message, a...)
fmt.Printf("%s - %s\n", code2name[exitCode], msg)
os.Exit(exitCode)
}
logger.FatalHandler = fatalHandler
logger.Level = etcdmtr.LOGLEVEL_SILENCE
if args.ExpectedMembers < 1 {
logger.Fatalc(3, "--nagios requires --members > 0")
}
}
if args.Version {
logger.Fatalc(1, "0.0.1")
logger.Fatalc(0, "0.0.1")
}
if len(positionals) < 1 {
logger.Fatal("must specify endpoints")
logger.Fatalc(3, "must specify endpoints")
}
if !args.Insecure {
if args.ClientKey == "" || args.ClientCert == "" || args.ServerCA == "" {
logger.Fatal("must set --insecure if not passing --client-cert, --client-key, and --ca")
logger.Fatalc(3, "must set --insecure if not passing --client-cert, --client-key, and --ca")
}
}
@ -127,7 +144,7 @@ func main() {
client, err := NewClient(positionals, args.ClientCert, args.ClientKey, args.ServerCA, args.Debug)
if err != nil {
logger.Fatal("couldn't get client: %s", err.Error())
logger.Fatalc(3, "couldn't get client: %s", err.Error())
}
etcd, err := client.GetEtcd()
@ -160,23 +177,31 @@ func main() {
is_leader, err := contactMember(contextCtx, client, endpoint)
if err != nil {
logger.Warning("couldn't reach member %s: %s", endpoint, err)
logger.Error("couldn't reach member %s: %s", endpoint, err)
memberErrors = append(memberErrors, err)
continue
}
logger.Info("reached member %s - is leader? %v", endpoint, is_leader)
}
if args.Nagios {
if numMembers != args.ExpectedMembers {
}
}
if args.ExpectedMembers > 0 {
if numMembers != args.ExpectedMembers {
logger.Error("found different number of members than expected: %d", numMembers)
os.Exit(1)
logger.Fatalc(2, "found %d members, expected %d", numMembers, args.ExpectedMembers)
}
if len(memberErrors) > 0 {
logger.Error("encountered an error when contacting %d members", len(memberErrors))
os.Exit(1)
logger.Fatalc(2, "couldn't contact %d members", len(memberErrors))
}
}
if args.Nagios {
logger.Fatalc(0, "found %d members", numMembers)
}
}
func contactMember(ctx context.Context, client *Client, endpoint string) (bool, error) {
@ -188,7 +213,7 @@ func contactMember(ctx context.Context, client *Client, endpoint string) (bool,
status, err := etcd.Status(ctx, endpoint)
if err != nil {
return false, fmt.Errorf("couldn't reach member: %s", err)
return false, err
}
return status.Leader == status.Header.MemberId, nil
}

View File

@ -87,11 +87,12 @@ func (f *LogFormat) AppendTimestamp(format string) *LogFormat {
}
type ELog struct {
parent *ELog
name string
Level LogLevel
Format *LogFormat
Output io.Writer
parent *ELog
name string
Level LogLevel
Format *LogFormat
Output io.Writer
FatalHandler func(*ELog, int, string, ...any)
}
func NewRootLogger() *ELog {
@ -110,11 +111,17 @@ func NewRootLogger() *ELog {
)
}
func FatalHandler(logger *ELog, exitCode int, message string, a ...any) {
_, _ = logger.Log(LOGLEVEL_FATAL, message, a)
os.Exit(exitCode)
}
func NewRootLoggerWithFormat(format *LogFormat) *ELog {
return &ELog{
name: "main",
Format: format,
Output: os.Stderr,
name: "main",
Format: format,
Output: os.Stderr,
FatalHandler: FatalHandler,
}
}
@ -126,7 +133,7 @@ func (e *ELog) GetLogger(name string) *ELog {
}
}
func (e *ELog) _Log(level LogLevel, message string, a ...any) (n int, err error) {
func (e *ELog) Log(level LogLevel, message string, a ...any) (n int, err error) {
return e._DoLog(level, nil, message, a...)
}
@ -169,23 +176,23 @@ func (e *ELog) _DoLog(level LogLevel, path []string, message string, a ...any) (
}
func (e *ELog) Debug(message string, a ...any) (n int, err error) {
return e._Log(LOGLEVEL_DEBUG, message, a...)
return e.Log(LOGLEVEL_DEBUG, message, a...)
}
func (e *ELog) Info(message string, a ...any) (n int, err error) {
return e._Log(LOGLEVEL_INFO, message, a...)
return e.Log(LOGLEVEL_INFO, message, a...)
}
func (e *ELog) Warning(message string, a ...any) (n int, err error) {
return e._Log(LOGLEVEL_WARNING, message, a...)
return e.Log(LOGLEVEL_WARNING, message, a...)
}
func (e *ELog) Error(message string, a ...any) (n int, err error) {
return e._Log(LOGLEVEL_ERROR, message, a...)
return e.Log(LOGLEVEL_ERROR, message, a...)
}
func (e *ELog) Critical(message string, a ...any) (n int, err error) {
return e._Log(LOGLEVEL_CRITICAL, message, a...)
return e.Log(LOGLEVEL_CRITICAL, message, a...)
}
func (e *ELog) Fatal(message string, a ...any) (n int, err error) {
@ -193,8 +200,7 @@ func (e *ELog) Fatal(message string, a ...any) (n int, err error) {
}
func (e *ELog) Fatalc(exitCode int, message string, a ...any) (n int, err error) {
_, _ = e._Log(LOGLEVEL_FATAL, message, a...)
os.Exit(exitCode)
e.FatalHandler(e, exitCode, message, a...)
return 0, nil
}