Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6
github.com/emersion/go-smtp v0.24.0
github.com/google/uuid v1.6.0
github.com/icinga/icinga-go-library v0.9.1-0.20260623130323-faef23cbd4c9
github.com/icinga/icinga-go-library v0.9.1-0.20260630080726-15d47aff49f8
github.com/jhillyerd/enmime v1.3.0
github.com/jmoiron/sqlx v1.4.0
github.com/okzk/sdnotify v0.0.0-20180710141335-d9becc38acbd
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/icinga/icinga-go-library v0.9.1-0.20260623130323-faef23cbd4c9 h1:HyeACIYSpROzA9bUghELjzsCwnHzM48M6oD2zgKMlfA=
github.com/icinga/icinga-go-library v0.9.1-0.20260623130323-faef23cbd4c9/go.mod h1:XFsuZEn2hrE3YXQ3NHqnI2UkjdZgJJWb/7D/+VH6MsE=
github.com/icinga/icinga-go-library v0.9.1-0.20260630080726-15d47aff49f8 h1:YZ+N5qKN9tB6JPUno3oVcVE9TAayAIOZAG8hmVkgYBQ=
github.com/icinga/icinga-go-library v0.9.1-0.20260630080726-15d47aff49f8/go.mod h1:XFsuZEn2hrE3YXQ3NHqnI2UkjdZgJJWb/7D/+VH6MsE=
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
Expand Down
6 changes: 2 additions & 4 deletions internal/channel/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,8 @@ func (c *Channel) Notify(contact *recipient.Contact, i contracts.Incident, ev *e
Severity: i.IncidentSeverity(),
},
Event: &plugin.Event{
Time: ev.Time,
Type: ev.Type,
Username: ev.Username,
Message: ev.Message,
Time: ev.Time,
Message: ev.Message,
},
}

Expand Down
62 changes: 23 additions & 39 deletions internal/event/event.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package event

import (
"errors"
"fmt"
"net/url"
"regexp"
Expand All @@ -10,20 +9,12 @@ import (
"time"

baseEv "github.com/icinga/icinga-go-library/notifications/event"
"github.com/icinga/icinga-go-library/types"
"github.com/icinga/icinga-notifications/internal/pool"
"github.com/icinga/icinga-notifications/internal/utils"
"github.com/theory/jsonpath"
"go.uber.org/zap/zapcore"
)

// ErrSuperfluousStateChange indicates a superfluous state change being ignored and stopping further processing.
var ErrSuperfluousStateChange = errors.New("ignoring superfluous state change")

// ErrSuperfluousMuteUnmuteEvent indicates that a superfluous mute or unmute event is being ignored and is
// triggered when trying to mute/unmute an already muted/unmuted incident.
var ErrSuperfluousMuteUnmuteEvent = errors.New("ignoring superfluous (un)mute event")

// Event received of a specified Type for internal processing.
//
// This is a representation of an event received from an external source with additional metadata with sole
Expand Down Expand Up @@ -68,53 +59,42 @@ func (e *Event) CompleteURL(icingaWebBaseUrl *url.URL) {
// Validate validates the current event state.
// Returns an error if it detects a misconfigured field.
func (e *Event) Validate() error {
if len(e.Tags) == 0 {
return fmt.Errorf("invalid event: tags must not be empty")
if err := e.Event.Validate(); err != nil {
return err
}

for tag := range e.Tags {
if len(tag) > 255 {
return fmt.Errorf("invalid event: tag %q is too long, at most 255 chars allowed, %d given", tag, len(tag))
}
if e.Time.IsZero() {
return fmt.Errorf("invalid event: time must not be empty")
}

if e.SourceId == 0 {
return fmt.Errorf("invalid event: source ID must not be empty")
}

if e.Severity != baseEv.SeverityNone && e.Type != baseEv.TypeState {
return fmt.Errorf("invalid event: if 'severity' is set, 'type' must be set to %q", baseEv.TypeState)
}
if e.Type == baseEv.TypeMute && (!e.Mute.Valid || !e.Mute.Bool) {
return fmt.Errorf("invalid event: 'mute' must be true if 'type' is set to %q", baseEv.TypeMute)
}
if e.Type == baseEv.TypeUnmute && (!e.Mute.Valid || e.Mute.Bool) {
return fmt.Errorf("invalid event: 'mute' must be false if 'type' is set to %q", baseEv.TypeUnmute)
}
if e.Mute.Valid && e.Mute.Bool && e.MuteReason == "" {
return fmt.Errorf("invalid event: 'mute_reason' must not be empty if 'mute' is set")
}

if e.Type == baseEv.TypeUnknown {
return errors.New("invalid event: missing type")
}

return nil
}

// SetMute alters the event mute and mute reason.
func (e *Event) SetMute(muted bool, reason string) {
e.Mute = types.Bool{Valid: true, Bool: muted}
e.MuteReason = reason
}

// MarshalLogObject implements the [zapcore.ObjectMarshaler] interface to allow logging the event as a structured object.
func (e *Event) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
encoder.AddString("name", e.Name)
encoder.AddTime("time", e.Time)
encoder.AddInt64("source_id", e.SourceId)
encoder.AddString("type", e.Type.String())
encoder.AddString("severity", e.Severity.String())

if e.Muted.Valid {
encoder.AddBool("muted", e.Muted.Bool)
encoder.AddString("muted_reason", e.MutedReason)
}
if e.OpenOrEscalate() {
encoder.AddBool("incident", true)
}
if e.CloseIncident() {
encoder.AddBool("close", true)
}
if e.NotifyRecipients() {
encoder.AddBool("notify", true)
}

return encoder.AddObject("tags", zapcore.ObjectMarshalerFunc(func(objectEncoder zapcore.ObjectEncoder) error {
for key, value := range e.Tags {
objectEncoder.AddString(key, value)
Expand All @@ -130,6 +110,10 @@ func (e *Event) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
// field and are not part of the CompleteRelations field. For filter columns that do have matching
// nodes, it caches the evaluated nodes for potential later use during rules evaluation.
func (e *Event) ExtractMissingRelations(filterColumns ...[]string) []string {
if len(filterColumns) == 0 {
return nil
}

if e.evaluatedRelations == nil {
e.evaluatedRelations = make(map[string]jsonpath.NodeList)
}
Expand Down
Loading
Loading