SLA reporting: additionally write relevant history events to dedicated SLA tables

This commit is contained in:
Julian Brost 2021-08-24 11:16:39 +02:00
parent 7cd6fd98ce
commit e9bd5cd40f
5 changed files with 89 additions and 6 deletions

View file

@ -0,0 +1,26 @@
package history
import (
"github.com/go-redis/redis/v8"
"github.com/icinga/icingadb/pkg/icingadb/v1/history"
"github.com/icinga/icingadb/pkg/structify"
"github.com/icinga/icingadb/pkg/types"
"reflect"
)
var slaStateStructify = structify.MakeMapStructifier(reflect.TypeOf((*history.SlaHistoryState)(nil)).Elem(), "json")
func stateHistoryToSlaEntity(entry redis.XMessage) ([]history.UpserterEntity, error) {
slaStateInterface, err := slaStateStructify(entry.Values)
if err != nil {
return nil, err
}
slaState := slaStateInterface.(*history.SlaHistoryState)
if slaState.StateType != types.StateHard {
// only hard state changes are relevant for SLA history, discard all others
return nil, nil
}
return []history.UpserterEntity{slaState}, nil
}

View file

@ -359,12 +359,14 @@ var syncPipelines = map[string][]stageFunc{
writeOneEntityStage((*v1.HistoryNotification)(nil)), // history (depends on notification_history)
},
"state": {
writeOneEntityStage((*v1.StateHistory)(nil)), // state_history
writeOneEntityStage((*v1.HistoryState)(nil)), // history (depends on state_history)
writeOneEntityStage((*v1.StateHistory)(nil)), // state_history
writeOneEntityStage((*v1.HistoryState)(nil)), // history (depends on state_history)
writeMultiEntityStage(stateHistoryToSlaEntity), // sla_history_state
},
"downtime": {
writeOneEntityStage((*v1.DowntimeHistory)(nil)), // downtime_history
writeOneEntityStage((*v1.HistoryDowntime)(nil)), // history (depends on downtime_history)
writeOneEntityStage((*v1.DowntimeHistory)(nil)), // downtime_history
writeOneEntityStage((*v1.HistoryDowntime)(nil)), // history (depends on downtime_history)
writeOneEntityStage((*v1.SlaHistoryDowntime)(nil)), // sla_history_downtime
},
"comment": {
writeOneEntityStage((*v1.CommentHistory)(nil)), // comment_history

View file

@ -80,6 +80,30 @@ func (*HistoryDowntime) TableName() string {
return "history"
}
type SlaHistoryDowntime struct {
DowntimeHistoryEntity `json:",inline"`
HistoryTableMeta `json:",inline"`
SlaHistoryDowntimeUpserter `json:",inline"`
DowntimeStart types.UnixMilli `json:"start_time"`
HasBeenCancelled types.Bool `json:"has_been_cancelled" db:"-"`
CancelTime types.UnixMilli `json:"cancel_time" db:"-"`
EndTime types.UnixMilli `json:"end_time" db:"-"`
}
// Init implements the contracts.Initer interface.
func (s *SlaHistoryDowntime) Init() {
s.DowntimeEnd.History = s
}
type SlaHistoryDowntimeUpserter struct {
DowntimeEnd SlaDowntimeEndTime `json:"-"`
}
// Upsert implements the contracts.Upserter interface.
func (h *SlaHistoryDowntimeUpserter) Upsert() interface{} {
return h
}
type DowntimeEventTime struct {
History *HistoryDowntime `db:"-"`
}
@ -109,6 +133,19 @@ func (et DowntimeEventTime) Value() (driver.Value, error) {
}
}
type SlaDowntimeEndTime struct {
History *SlaHistoryDowntime `db:"-"`
}
// Value implements the driver.Valuer interface.
func (et SlaDowntimeEndTime) Value() (driver.Value, error) {
if et.History.HasBeenCancelled.Valid && et.History.HasBeenCancelled.Bool {
return et.History.CancelTime.Value()
} else {
return et.History.EndTime.Value()
}
}
// Assert interface compliance.
var (
_ contracts.Entity = (*DowntimeHistoryEntity)(nil)
@ -117,5 +154,8 @@ var (
_ contracts.Initer = (*HistoryDowntime)(nil)
_ contracts.TableNamer = (*HistoryDowntime)(nil)
_ UpserterEntity = (*HistoryDowntime)(nil)
_ contracts.Initer = (*SlaHistoryDowntime)(nil)
_ UpserterEntity = (*SlaHistoryDowntime)(nil)
_ driver.Valuer = DowntimeEventTime{}
_ driver.Valuer = SlaDowntimeEndTime{}
)

View file

@ -33,9 +33,19 @@ func (*HistoryState) TableName() string {
return "history"
}
type SlaHistoryState struct {
HistoryTableEntity `json:",inline"`
HistoryTableMeta `json:",inline"`
EventTime types.UnixMilli `json:"event_time"`
StateType types.StateType `json:"state_type" db:"-"`
HardState uint8 `json:"hard_state"`
PreviousHardState uint8 `json:"previous_hard_state"`
}
// Assert interface compliance.
var (
_ UpserterEntity = (*StateHistory)(nil)
_ contracts.TableNamer = (*HistoryState)(nil)
_ UpserterEntity = (*HistoryState)(nil)
_ UpserterEntity = (*SlaHistoryState)(nil)
)

View file

@ -46,10 +46,15 @@ func badStateType(t interface{}) error {
return errors.Errorf("bad state type: %#v", t)
}
const (
StateSoft = StateType(0)
StateHard = StateType(1)
)
// stateTypes maps all valid StateType values to their SQL representation.
var stateTypes = map[StateType]string{
0: "soft",
1: "hard",
StateSoft: "soft",
StateHard: "hard",
}
// Assert interface compliance.