Skip to content

Commit

Permalink
icinga2: Enhance debug logging
Browse files Browse the repository at this point in the history
This commit implements the `zapcore.ObjectMarshalerFunc` interface for
all API / event stream response result types that we currently sprintf
the entire Object with `#%v` and allows us to lazily encode all
necessary fields without bloating the debug logs with useless
information.
  • Loading branch information
yhabteab authored and julianbrost committed Jul 16, 2024
1 parent 3989f71 commit 645a007
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 4 deletions.
64 changes: 64 additions & 0 deletions internal/icinga2/api_responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package icinga2
import (
"encoding/json"
"fmt"
"go.uber.org/zap/zapcore"
"strconv"
"time"
)
Expand Down Expand Up @@ -80,6 +81,14 @@ type CheckResult struct {
ExecutionEnd UnixFloat `json:"execution_end"`
}

// MarshalLogObject implements the zapcore.ObjectMarshaler interface.
func (cr *CheckResult) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
encoder.AddInt("exit_status", cr.ExitStatus)
encoder.AddInt("state", cr.State)
encoder.AddString("output", cr.Output)
return nil
}

// Downtime represents the Icinga 2 API Downtime object.
//
// NOTE:
Expand All @@ -106,6 +115,21 @@ type Downtime struct {
IsFixed bool `json:"fixed"`
}

// MarshalLogObject implements the zapcore.ObjectMarshaler interface.
func (d *Downtime) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
encoder.AddString("host", d.Host)
if d.Service != "" {
encoder.AddString("service", d.Service)
}

encoder.AddString("author", d.Author)
encoder.AddBool("fixed", d.IsFixed)
encoder.AddBool("was_cancelled", d.WasCancelled())
encoder.AddTime("remove_time", d.RemoveTime.Time())
encoder.AddString("comment", d.Comment)
return nil
}

// WasCancelled returns true when the current downtime was cancelled prematurely by a user.
func (d *Downtime) WasCancelled() bool {
return d.RemoveTime.Time().After(time.UnixMilli(0))
Expand Down Expand Up @@ -139,6 +163,31 @@ type HostServiceRuntimeAttributes struct {
AcknowledgementLastChange UnixFloat `json:"acknowledgement_last_change"`
}

// MarshalLogObject implements the zapcore.ObjectMarshaler interface.
func (hsra *HostServiceRuntimeAttributes) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
encoder.AddString("name", hsra.Name)
if hsra.Host != "" {
encoder.AddString("host", hsra.Host)
}

encoder.AddInt("state", hsra.State)
encoder.AddInt("state_type", hsra.StateType)
encoder.AddBool("in_downtime", hsra.DowntimeDepth != 0)
encoder.AddBool("acknowledged", hsra.Acknowledgement != AcknowledgementNone)
encoder.AddTime("last_state_change", hsra.LastStateChange.Time())
err := encoder.AddArray("groups", zapcore.ArrayMarshalerFunc(func(encoder zapcore.ArrayEncoder) error {
for _, group := range hsra.Groups {
encoder.AppendString(group)
}
return nil
}))
if err != nil {
return err
}

return encoder.AddObject("check_result", &hsra.LastCheckResult)
}

// ObjectQueriesResult represents the Icinga 2 API Object Queries Result wrapper object.
//
// https://icinga.com/docs/icinga-2/latest/doc/12-icinga2-api/#object-queries-result
Expand Down Expand Up @@ -184,6 +233,21 @@ type StateChange struct {
Acknowledgement bool `json:"acknowledgement"`
}

// MarshalLogObject implements the zapcore.ObjectMarshaler interface.
func (sc *StateChange) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
encoder.AddTime("timestamp", sc.Timestamp.Time())
encoder.AddString("host", sc.Host)
if sc.Service != "" {
encoder.AddString("service", sc.Service)
}

encoder.AddInt("state", sc.State)
encoder.AddInt("state_type", sc.StateType)
encoder.AddBool("in_downtime", sc.DowntimeDepth != 0)
encoder.AddBool("acknowledged", sc.Acknowledgement)
return encoder.AddObject("check_result", &sc.CheckResult)
}

// Acknowledgement represents the Icinga 2 API Event Stream AcknowledgementSet or AcknowledgementCleared
// response for acknowledgements set/cleared on/from hosts/services.
//
Expand Down
10 changes: 6 additions & 4 deletions internal/icinga2/client_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func (client *Client) checkMissedChanges(ctx context.Context, objType string, ca

// Only process HARD states
if objQueriesResult.Attrs.StateType == StateTypeSoft {
client.Logger.Debugf("Skipping SOFT event, %#v", objQueriesResult.Attrs)
client.Logger.Debugw("Skipping SOFT event", zap.Inline(&objQueriesResult.Attrs))
continue
}

Expand Down Expand Up @@ -501,7 +501,7 @@ func (client *Client) listenEventStream() error {
case *StateChange:
// Only process HARD states
if respT.StateType == StateTypeSoft {
client.Logger.Debugf("Skipping SOFT State Change, %#v", respT)
client.Logger.Debugw("Skipping SOFT State Change", zap.Inline(respT))
continue
}

Expand All @@ -520,7 +520,8 @@ func (client *Client) listenEventStream() error {
if !respT.Downtime.IsFixed {
// This may never happen, but Icinga 2 does the same thing, and we need to ignore the start
// event for flexible downtime, as there will definitely be a triggered event for it.
client.Logger.Debugf("Skipping flexible downtime start event, %#v", respT)
client.Logger.Debugw("Skipping flexible downtime start event",
zap.Time("timestamp", respT.Timestamp.Time()), zap.Inline(&respT.Downtime))
continue
}

Expand All @@ -530,7 +531,8 @@ func (client *Client) listenEventStream() error {
if respT.Downtime.IsFixed {
// Fixed downtimes generate two events (start, triggered), the latter applies here and must
// be ignored, since we're going to process its start event to avoid duplicated notifications.
client.Logger.Debugf("Skipping fixed downtime triggered event, %#v", respT)
client.Logger.Debugw("Skipping fixed downtime triggered event",
zap.Time("timestamp", respT.Timestamp.Time()), zap.Inline(&respT.Downtime))
continue
}

Expand Down

0 comments on commit 645a007

Please sign in to comment.