From a60ebc50553fcc89c6e5965090ec2b39a74bfb62 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Fri, 26 May 2023 09:47:01 +0200 Subject: [PATCH 1/7] Add `Icingadb#SlaLifecycle` --- pkg/icingadb/sla_lifecycle.go | 70 ++++++++++++++++++++++++++++++++ pkg/icingadb/v1/sla_lifecycle.go | 24 +++++++++++ 2 files changed, 94 insertions(+) create mode 100644 pkg/icingadb/sla_lifecycle.go create mode 100644 pkg/icingadb/v1/sla_lifecycle.go diff --git a/pkg/icingadb/sla_lifecycle.go b/pkg/icingadb/sla_lifecycle.go new file mode 100644 index 000000000..c71761e22 --- /dev/null +++ b/pkg/icingadb/sla_lifecycle.go @@ -0,0 +1,70 @@ +package icingadb + +import ( + "context" + "github.com/icinga/icinga-go-library/database" + "github.com/icinga/icinga-go-library/types" + v1 "github.com/icinga/icingadb/pkg/icingadb/v1" + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" + "time" +) + +// CreateSlaLifecyclesFromCheckables transforms the given checkables to sla lifecycle struct +// and streams them into a returned channel. +func CreateSlaLifecyclesFromCheckables( + ctx context.Context, subject database.Entity, g *errgroup.Group, entities <-chan database.Entity, isDeleteEvent bool, +) <-chan database.Entity { + slaLifecycles := make(chan database.Entity, 1) + + g.Go(func() error { + defer close(slaLifecycles) + + env, ok := v1.EnvironmentFromContext(ctx) + if !ok { + return errors.New("can't get environment from context") + } + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case checkable, ok := <-entities: + if !ok { + return nil + } + + sl := &v1.SlaLifecycle{ + EnvironmentMeta: v1.EnvironmentMeta{EnvironmentId: env.Id}, + CreateTime: types.UnixMilli(time.Now()), + DeleteTime: types.UnixMilli(time.Unix(0, 0)), + } + + if isDeleteEvent { + sl.DeleteTime = types.UnixMilli(time.Now()) + sl.CreateTime = types.UnixMilli(time.Unix(0, 0)) + } + + switch subject.(type) { + case *v1.Host: + sl.Id = checkable.ID().(types.Binary) + sl.HostId = sl.Id + case *v1.Service: + sl.Id = checkable.ID().(types.Binary) + sl.ServiceId = sl.Id + sl.HostId = checkable.(*v1.Service).HostId + default: + return errors.Errorf("sla lifecycle for type %T is not supported", checkable) + } + + select { + case slaLifecycles <- sl: + case <-ctx.Done(): + return ctx.Err() + } + } + } + }) + + return slaLifecycles +} diff --git a/pkg/icingadb/v1/sla_lifecycle.go b/pkg/icingadb/v1/sla_lifecycle.go new file mode 100644 index 000000000..3e8853a42 --- /dev/null +++ b/pkg/icingadb/v1/sla_lifecycle.go @@ -0,0 +1,24 @@ +package v1 + +import ( + "github.com/icinga/icinga-go-library/database" + "github.com/icinga/icinga-go-library/types" +) + +type SlaLifecycle struct { + EntityWithoutChecksum `json:",inline"` + EnvironmentMeta `json:",inline"` + HostId types.Binary `json:"host_id"` + ServiceId types.Binary `json:"service_id"` + CreateTime types.UnixMilli `json:"create_time"` + DeleteTime types.UnixMilli `json:"delete_time"` +} + +func NewSlaLifecycle() database.Entity { + return &SlaLifecycle{} +} + +// Assert interface compliance. +var ( + _ database.Entity = (*SlaLifecycle)(nil) +) From 31b757864f3217768170862c51057848aa1ca7ed Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 24 Oct 2024 17:03:23 +0200 Subject: [PATCH 2/7] Write `create` & `delete` sla events on config dumps --- cmd/icingadb/main.go | 23 +++++++-- pkg/icingadb/sla_lifecycle.go | 53 ++++++++++++++++++++ schema/mysql/schema.sql | 14 ++++++ schema/mysql/upgrades/1.3.0.sql | 86 +++++++++++++++++++++++++++++++ schema/pgsql/schema.sql | 21 ++++++++ schema/pgsql/upgrades/1.3.0.sql | 89 +++++++++++++++++++++++++++++++++ 6 files changed, 283 insertions(+), 3 deletions(-) diff --git a/cmd/icingadb/main.go b/cmd/icingadb/main.go index de2cbdcfc..0da321320 100644 --- a/cmd/icingadb/main.go +++ b/cmd/icingadb/main.go @@ -167,10 +167,15 @@ func run() int { synctx, cancelSynctx := context.WithCancel(ha.Environment().NewContext(hactx)) g, synctx := errgroup.WithContext(synctx) // WaitGroups for initial synchronization. - // Runtime updates must wait for initial synchronization to complete. + // Runtime updates and history pipelines must wait for the initial synchronization to + // complete by draining the `initConfigSyncDone` channel. configInitSync := sync.WaitGroup{} stateInitSync := &sync.WaitGroup{} + // A channel used to notify both the runtime updates and history pipelines workers + // about the successful initial config sync completion including the SLA lifecycles. + initConfigSyncDone := make(chan struct{}) + // Clear the runtime update streams before starting anything else (rather than after the sync), // otherwise updates may be lost. runtimeConfigUpdateStreams, runtimeStateUpdateStreams, err := rt.ClearStreams(synctx) @@ -243,7 +248,18 @@ func run() int { }) g.Go(func() error { + // Unblock the runtime updates and history pipelines workers. + defer close(initConfigSyncDone) + + // Wait for the actual initial config sync to finish before syncing the SLA lifecycles. configInitSync.Wait() + + logger.Info("Syncing Host and Service initial SLA lifecycle") + + if err := icingadb.SyncCheckablesSlaLifecycle(synctx, db); err != nil { + return err + } + telemetry.OngoingSyncStartMilli.Store(0) syncEnd := time.Now() @@ -279,7 +295,8 @@ func run() int { }) g.Go(func() error { - configInitSync.Wait() + // Wait for the initial config sync including the SLA lifecycles to finish! + <-initConfigSyncDone if err := synctx.Err(); err != nil { return err @@ -304,7 +321,7 @@ func run() int { g.Go(func() error { // Wait for config and state sync to avoid putting additional pressure on the database. - configInitSync.Wait() + <-initConfigSyncDone stateInitSync.Wait() if err := synctx.Err(); err != nil { diff --git a/pkg/icingadb/sla_lifecycle.go b/pkg/icingadb/sla_lifecycle.go index c71761e22..a27a25e3d 100644 --- a/pkg/icingadb/sla_lifecycle.go +++ b/pkg/icingadb/sla_lifecycle.go @@ -2,7 +2,10 @@ package icingadb import ( "context" + "fmt" + "github.com/icinga/icinga-go-library/backoff" "github.com/icinga/icinga-go-library/database" + "github.com/icinga/icinga-go-library/retry" "github.com/icinga/icinga-go-library/types" v1 "github.com/icinga/icingadb/pkg/icingadb/v1" "github.com/pkg/errors" @@ -10,6 +13,9 @@ import ( "time" ) +// slaLifecycleTable defines the table name of v1.SlaLifecycle type. +var slaLifecycleTable = database.TableName(v1.NewSlaLifecycle()) + // CreateSlaLifecyclesFromCheckables transforms the given checkables to sla lifecycle struct // and streams them into a returned channel. func CreateSlaLifecyclesFromCheckables( @@ -68,3 +74,50 @@ func CreateSlaLifecyclesFromCheckables( return slaLifecycles } + +// SyncCheckablesSlaLifecycle inserts one `create_time` sla lifecycle entry for each of the checkables from +// the `host` and `service` tables and updates the `delete_time` of each of the sla lifecycle entries whose +// host/service IDs cannot be found in the `host/service` tables. +// +// It's unlikely, but when a given Checkable doesn't already have a `create_time` entry in the database, the update +// query won't update anything. Likewise, the insert statements may also become a no-op if the Checkables already +// have a `create_time` entry with ´delete_time = 0`. +// +// This function retries any database errors for at least `5m` before giving up and failing with an error. +func SyncCheckablesSlaLifecycle(ctx context.Context, db *database.DB) error { + hostInsertStmtFmt := ` +INSERT INTO %[1]s (id, environment_id, host_id, create_time) + SELECT id, environment_id, id, %[2]d AS create_time + FROM host WHERE NOT EXISTS(SELECT 1 FROM %[1]s WHERE service_id IS NULL AND delete_time = 0 AND host_id = host.id)` + + hostUpdateStmtFmt := ` +UPDATE %[1]s SET delete_time = %[2]d + WHERE service_id IS NULL AND delete_time = 0 AND NOT EXISTS(SELECT 1 FROM host WHERE host.id = %[1]s.id)` + + serviceInsertStmtFmt := ` +INSERT INTO %[1]s (id, environment_id, host_id, service_id, create_time) + SELECT id, environment_id, host_id, id, %[2]d AS create_time + FROM service WHERE NOT EXISTS(SELECT 1 FROM %[1]s WHERE delete_time = 0 AND service_id = service.id)` + + serviceUpdateStmtFmt := ` +UPDATE %[1]s SET delete_time = %[2]d + WHERE delete_time = 0 AND service_id IS NOT NULL AND NOT EXISTS(SELECT 1 FROM service WHERE service.id = %[1]s.id)` + + return retry.WithBackoff( + ctx, + func(context.Context) error { + eventTime := time.Now().UnixMilli() + for _, queryFmt := range []string{hostInsertStmtFmt, hostUpdateStmtFmt, serviceInsertStmtFmt, serviceUpdateStmtFmt} { + query := fmt.Sprintf(queryFmt, slaLifecycleTable, eventTime) + if _, err := db.ExecContext(ctx, query); err != nil { + return database.CantPerformQuery(err, query) + } + } + + return nil + }, + retry.Retryable, + backoff.NewExponentialWithJitter(1*time.Millisecond, 1*time.Second), + db.GetDefaultRetrySettings(), + ) +} diff --git a/schema/mysql/schema.sql b/schema/mysql/schema.sql index a1db99084..fb66638e0 100644 --- a/schema/mysql/schema.sql +++ b/schema/mysql/schema.sql @@ -1334,6 +1334,20 @@ CREATE TABLE sla_history_downtime ( INDEX idx_sla_history_downtime_env_downtime_end (environment_id, downtime_end) COMMENT 'Filter for sla history retention' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; +CREATE TABLE sla_lifecycle ( + id binary(20) NOT NULL COMMENT 'host.id if service_id is NULL otherwise service.id', + environment_id binary(20) NOT NULL COMMENT 'environment.id', + host_id binary(20) NOT NULL COMMENT 'host.id (may reference already deleted hosts)', + service_id binary(20) DEFAULT NULL COMMENT 'service.id (may reference already deleted services)', + + -- These columns are nullable, but as we're using the delete_time to build the composed primary key, we have to set + -- this to `0` instead, since it's not allowed to use a nullable column as part of the primary key. + create_time bigint unsigned NOT NULL DEFAULT 0 COMMENT 'unix timestamp the event occurred', + delete_time bigint unsigned NOT NULL DEFAULT 0 COMMENT 'unix timestamp the delete event occurred', + + PRIMARY KEY (id, delete_time) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; + CREATE TABLE icingadb_schema ( id int unsigned NOT NULL AUTO_INCREMENT, version smallint unsigned NOT NULL, diff --git a/schema/mysql/upgrades/1.3.0.sql b/schema/mysql/upgrades/1.3.0.sql index 047903807..1cf613fd8 100644 --- a/schema/mysql/upgrades/1.3.0.sql +++ b/schema/mysql/upgrades/1.3.0.sql @@ -18,5 +18,91 @@ ALTER TABLE checkcommand_envvar MODIFY COLUMN envvar_key varchar(255) NOT NULL; ALTER TABLE eventcommand_envvar MODIFY COLUMN envvar_key varchar(255) NOT NULL; ALTER TABLE notificationcommand_envvar MODIFY COLUMN envvar_key varchar(255) NOT NULL; +CREATE TABLE sla_lifecycle ( + id binary(20) NOT NULL COMMENT 'host.id if service_id is NULL otherwise service.id', + environment_id binary(20) NOT NULL COMMENT 'environment.id', + host_id binary(20) NOT NULL COMMENT 'host.id (may reference already deleted hosts)', + service_id binary(20) DEFAULT NULL COMMENT 'service.id (may reference already deleted services)', + + -- These columns are nullable, but as we're using the delete_time to build the composed primary key, we have to set + -- this to `0` instead, since it's not allowed to use a nullable column as part of the primary key. + create_time bigint unsigned NOT NULL DEFAULT 0 COMMENT 'unix timestamp the event occurred', + delete_time bigint unsigned NOT NULL DEFAULT 0 COMMENT 'unix timestamp the delete event occurred', + + PRIMARY KEY (id, delete_time) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; + +-- Insert a sla lifecycle create_time entry for all existing hosts with the LEAST timestamp found in either +-- the sla_history_state or sla_history_downtime table, otherwise fallback to the current Unix timestamp. +INSERT INTO sla_lifecycle (id, environment_id, host_id, create_time) + SELECT host.id, + host.environment_id, + host.id, + -- In MySQL/MariaDB, LEAST() returns NULL if either event_time or downtime_start is NULL, which is not + -- desirable for our use cases. So we need to work around this behaviour by nesting some COALESCE() calls. + COALESCE(LEAST(COALESCE(MIN(event_time), MIN(downtime_start)), COALESCE(MIN(downtime_start), MIN(event_time))), UNIX_TIMESTAMP() * 1000) AS create_time + FROM host + LEFT JOIN sla_history_state shs on host.id = shs.host_id AND shs.service_id IS NULL + LEFT JOIN sla_history_downtime shd on host.id = shd.host_id AND shd.service_id IS NULL + GROUP BY host.id, host.environment_id + ON DUPLICATE KEY UPDATE sla_lifecycle.id = sla_lifecycle.id; + +-- Insert a sla lifecycle deleted entry for all not existing hosts with the GREATEST timestamp +-- found in either the sla_history_state or sla_history_downtime table. +INSERT INTO sla_lifecycle (id, environment_id, host_id, delete_time) + SELECT host_id AS id, + environment_id, + host_id, + MAX(event_time) AS delete_time + FROM (SELECT host_id, environment_id, MAX(event_time) AS event_time + FROM sla_history_state + WHERE service_id IS NULL AND NOT EXISTS(SELECT 1 FROM host WHERE id = host_id) + GROUP BY host_id, environment_id + UNION ALL + SELECT host_id, environment_id, MAX(downtime_end) AS event_time + FROM sla_history_downtime + WHERE service_id IS NULL AND NOT EXISTS(SELECT 1 FROM host WHERE id = host_id) + GROUP BY host_id, environment_id + ) AS deleted_hosts + GROUP BY host_id, environment_id HAVING MAX(event_time) IS NOT NULL + ON DUPLICATE KEY UPDATE sla_lifecycle.id = sla_lifecycle.id; + +-- Insert a sla lifecycle create_time entry for all existing services with the LEAST timestamp found in either +-- the sla_history_state or sla_history_downtime table, otherwise fallback to the current Unix timestamp. +INSERT INTO sla_lifecycle (id, environment_id, host_id, service_id, create_time) + SELECT service.id, + service.environment_id, + service.host_id, + service.id, + -- In MySQL/MariaDB, LEAST() returns NULL if either event_time or downtime_start is NULL, which is not + -- desirable for our use cases. So we need to work around this behaviour by nesting some COALESCE() calls. + COALESCE(LEAST(COALESCE(MIN(event_time), MIN(downtime_start)), COALESCE(MIN(downtime_start), MIN(event_time))), UNIX_TIMESTAMP() * 1000) AS create_time + FROM service + LEFT JOIN sla_history_state shs on service.id = shs.service_id + LEFT JOIN sla_history_downtime shd on service.id = shd.service_id + GROUP BY service.id, service.host_id, service.environment_id + ON DUPLICATE KEY UPDATE sla_lifecycle.id = sla_lifecycle.id; + +-- Insert a sla lifecycle deleted entry for all not existing hosts with the GREATEST timestamp +-- found in either the sla_history_state or sla_history_downtime table. +INSERT INTO sla_lifecycle (id, environment_id, host_id, service_id, delete_time) + SELECT service_id AS id, + environment_id, + host_id, + service_id, + MAX(event_time) AS delete_time + FROM (SELECT service_id, environment_id, host_id, MAX(event_time) AS event_time + FROM sla_history_state + WHERE service_id IS NOT NULL AND NOT EXISTS(SELECT 1 FROM service WHERE id = service_id) + GROUP BY service_id, environment_id, host_id + UNION ALL + SELECT service_id, environment_id, host_id, MAX(downtime_end) AS event_time + FROM sla_history_downtime + WHERE service_id IS NOT NULL AND NOT EXISTS(SELECT 1 FROM service WHERE id = service_id) + GROUP BY service_id, environment_id, host_id + ) AS deleted_services + GROUP BY service_id, environment_id, host_id HAVING MAX(event_time) IS NOT NULL + ON DUPLICATE KEY UPDATE sla_lifecycle.id = sla_lifecycle.id; + INSERT INTO icingadb_schema (version, timestamp) VALUES (6, UNIX_TIMESTAMP() * 1000); diff --git a/schema/pgsql/schema.sql b/schema/pgsql/schema.sql index a68d41a1d..6def3e347 100644 --- a/schema/pgsql/schema.sql +++ b/schema/pgsql/schema.sql @@ -2171,6 +2171,27 @@ COMMENT ON COLUMN sla_history_downtime.downtime_id IS 'downtime.id (may referenc COMMENT ON COLUMN sla_history_downtime.downtime_start IS 'start time of the downtime'; COMMENT ON COLUMN sla_history_downtime.downtime_end IS 'end time of the downtime'; +CREATE TABLE sla_lifecycle ( + id bytea20 NOT NULL, + environment_id bytea20 NOT NULL, + host_id bytea20 NOT NULL, + service_id bytea20 DEFAULT NULL, + + -- These columns are nullable, but as we're using the delete_time to build the composed primary key, we have to set + -- this to `0` instead, since it's not allowed to use a nullable column as part of the primary key. + create_time biguint NOT NULL DEFAULT 0, + delete_time biguint NOT NULL DEFAULT 0, + + CONSTRAINT pk_sla_lifecycle PRIMARY KEY (id, delete_time) +); + +COMMENT ON COLUMN sla_lifecycle.id IS 'host.id if service_id is NULL otherwise service.id'; +COMMENT ON COLUMN sla_lifecycle.environment_id IS 'environment.id'; +COMMENT ON COLUMN sla_lifecycle.host_id IS 'host.id (may reference already deleted hosts)'; +COMMENT ON COLUMN sla_lifecycle.service_id IS 'service.id (may reference already deleted services)'; +COMMENT ON COLUMN sla_lifecycle.create_time IS 'unix timestamp the event occurred'; +COMMENT ON COLUMN sla_lifecycle.delete_time IS 'unix timestamp the delete event occurred'; + CREATE SEQUENCE icingadb_schema_id_seq; CREATE TABLE icingadb_schema ( diff --git a/schema/pgsql/upgrades/1.3.0.sql b/schema/pgsql/upgrades/1.3.0.sql index 80d75f5d3..5980b2885 100644 --- a/schema/pgsql/upgrades/1.3.0.sql +++ b/schema/pgsql/upgrades/1.3.0.sql @@ -15,5 +15,94 @@ ALTER TABLE checkcommand_envvar ALTER COLUMN envvar_key TYPE varchar(255); ALTER TABLE eventcommand_envvar ALTER COLUMN envvar_key TYPE varchar(255); ALTER TABLE notificationcommand_envvar ALTER COLUMN envvar_key TYPE varchar(255); +CREATE TABLE sla_lifecycle ( + id bytea20 NOT NULL, + environment_id bytea20 NOT NULL, + host_id bytea20 NOT NULL, + service_id bytea20 DEFAULT NULL, + + -- These columns are nullable, but as we're using the delete_time to build the composed primary key, we have to set + -- this to `0` instead, since it's not allowed to use a nullable column as part of the primary key. + create_time biguint NOT NULL DEFAULT 0, + delete_time biguint NOT NULL DEFAULT 0, + + CONSTRAINT pk_sla_lifecycle PRIMARY KEY (id, delete_time) +); + +COMMENT ON COLUMN sla_lifecycle.id IS 'host.id if service_id is NULL otherwise service.id'; +COMMENT ON COLUMN sla_lifecycle.environment_id IS 'environment.id'; +COMMENT ON COLUMN sla_lifecycle.host_id IS 'host.id (may reference already deleted hosts)'; +COMMENT ON COLUMN sla_lifecycle.service_id IS 'service.id (may reference already deleted services)'; +COMMENT ON COLUMN sla_lifecycle.create_time IS 'unix timestamp the event occurred'; +COMMENT ON COLUMN sla_lifecycle.delete_time IS 'unix timestamp the delete event occurred'; + +-- Insert a sla lifecycle create_time entry for all existing hosts with the LEAST timestamp found in either +-- the sla_history_state or sla_history_downtime table, otherwise fallback to the current Unix timestamp. +INSERT INTO sla_lifecycle (id, environment_id, host_id, create_time) + SELECT host.id, + host.environment_id, + host.id, + COALESCE(LEAST(MIN(event_time), MIN(downtime_start)), EXTRACT(EPOCH FROM now()) * 1000) AS create_time + FROM host + LEFT JOIN sla_history_state shs on host.id = shs.host_id AND shs.service_id IS NULL + LEFT JOIN sla_history_downtime shd on host.id = shd.host_id AND shd.service_id IS NULL + GROUP BY host.id, host.environment_id + ON CONFLICT ON CONSTRAINT pk_sla_lifecycle DO NOTHING; + +-- Insert a sla lifecycle deleted entry for all not existing hosts with the GREATEST timestamp +-- found in either the sla_history_state or sla_history_downtime table. +INSERT INTO sla_lifecycle (id, environment_id, host_id, delete_time) + SELECT host_id AS id, + environment_id, + host_id, + MAX(event_time) AS delete_time + FROM (SELECT host_id, environment_id, MAX(event_time) AS event_time + FROM sla_history_state + WHERE service_id IS NULL AND NOT EXISTS(SELECT 1 FROM host WHERE id = host_id) + GROUP BY host_id, environment_id + UNION ALL + SELECT host_id, environment_id, MAX(downtime_end) AS event_time + FROM sla_history_downtime + WHERE service_id IS NULL AND NOT EXISTS(SELECT 1 FROM host WHERE id = host_id) + GROUP BY host_id, environment_id + ) AS deleted_hosts + GROUP BY host_id, environment_id HAVING MAX(event_time) IS NOT NULL + ON CONFLICT ON CONSTRAINT pk_sla_lifecycle DO NOTHING; + +-- Insert a sla lifecycle create_time entry for all existing services with the LEAST timestamp found in either +-- the sla_history_state or sla_history_downtime table, otherwise fallback to the current Unix timestamp. +INSERT INTO sla_lifecycle (id, environment_id, host_id, service_id, create_time) + SELECT service.id, + service.environment_id, + service.host_id, + service.id, + COALESCE(LEAST(MIN(event_time), MIN(downtime_start)), EXTRACT(EPOCH FROM now()) * 1000) AS create_time + FROM service + LEFT JOIN sla_history_state shs on service.id = shs.service_id + LEFT JOIN sla_history_downtime shd on service.id = shd.service_id + GROUP BY service.id, service.host_id, service.environment_id + ON CONFLICT ON CONSTRAINT pk_sla_lifecycle DO NOTHING; + +-- Insert a sla lifecycle deleted entry for all not existing hosts with the GREATEST timestamp +-- found in either the sla_history_state or sla_history_downtime table. +INSERT INTO sla_lifecycle (id, environment_id, host_id, service_id, delete_time) + SELECT service_id AS id, + environment_id, + host_id, + service_id, + MAX(event_time) AS delete_time + FROM (SELECT service_id, environment_id, host_id, MAX(event_time) AS event_time + FROM sla_history_state + WHERE service_id IS NOT NULL AND NOT EXISTS(SELECT 1 FROM service WHERE id = service_id) + GROUP BY service_id, environment_id, host_id + UNION ALL + SELECT service_id, environment_id, host_id, MAX(downtime_end) AS event_time + FROM sla_history_downtime + WHERE service_id IS NOT NULL AND NOT EXISTS(SELECT 1 FROM service WHERE id = service_id) + GROUP BY service_id, environment_id, host_id + ) AS deleted_services + GROUP BY service_id, environment_id, host_id HAVING MAX(event_time) IS NOT NULL + ON CONFLICT ON CONSTRAINT pk_sla_lifecycle DO NOTHING; + INSERT INTO icingadb_schema (version, timestamp) VALUES (4, extract(epoch from now()) * 1000); From e5510b5917b7aec7092e7c2e9d3ae062004ee702 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 24 Oct 2024 17:05:43 +0200 Subject: [PATCH 3/7] Write checkable sla events for runtime updates --- pkg/icingadb/runtime_updates.go | 121 +++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/pkg/icingadb/runtime_updates.go b/pkg/icingadb/runtime_updates.go index 46d7bbe29..0a9bd1b99 100644 --- a/pkg/icingadb/runtime_updates.go +++ b/pkg/icingadb/runtime_updates.go @@ -10,6 +10,7 @@ import ( "github.com/icinga/icinga-go-library/redis" "github.com/icinga/icinga-go-library/strcase" "github.com/icinga/icinga-go-library/structify" + "github.com/icinga/icinga-go-library/types" "github.com/icinga/icingadb/pkg/common" "github.com/icinga/icingadb/pkg/contracts" v1 "github.com/icinga/icingadb/pkg/icingadb/v1" @@ -58,7 +59,7 @@ func (r *RuntimeUpdates) ClearStreams(ctx context.Context) (config, state redis. } // Sync synchronizes runtime update streams from s.redis to s.db and deletes the original data on success. -// Note that Sync must be only be called configuration synchronization has been completed. +// Note that Sync must only be called once configuration synchronization has been completed. // allowParallel allows synchronizing out of order (not FIFO). func (r *RuntimeUpdates) Sync( ctx context.Context, factoryFuncs []database.EntityFactoryFunc, streams redis.Streams, allowParallel bool, @@ -71,10 +72,22 @@ func (r *RuntimeUpdates) Sync( s := common.NewSyncSubject(factoryFunc) stat := getCounterForEntity(s.Entity()) + // Multiplexer channels used to distribute the Redis entities to several consumers. + upsertEntitiesMultiplexer := make(chan database.Entity, 1) + deleteIdsMultiplexer := make(chan any, 1) + updateMessages := make(chan redis.XMessage, r.redis.Options.XReadCount) upsertEntities := make(chan database.Entity, r.redis.Options.XReadCount) deleteIds := make(chan interface{}, r.redis.Options.XReadCount) + var insertSlaEntities chan database.Entity + var updateSlaEntities chan database.Entity + switch s.Entity().(type) { + case *v1.Host, *v1.Service: + insertSlaEntities = make(chan database.Entity, r.redis.Options.XReadCount) + updateSlaEntities = make(chan database.Entity, r.redis.Options.XReadCount) + } + var upsertedFifo chan database.Entity var deletedFifo chan interface{} var upsertCount int @@ -95,13 +108,47 @@ func (r *RuntimeUpdates) Sync( r.logger.Debugf("Syncing runtime updates of %s", s.Name()) g.Go(structifyStream( - ctx, updateMessages, upsertEntities, upsertedFifo, deleteIds, deletedFifo, + ctx, updateMessages, upsertEntitiesMultiplexer, upsertedFifo, deleteIdsMultiplexer, deletedFifo, structify.MakeMapStructifier( reflect.TypeOf(s.Entity()).Elem(), "json", contracts.SafeInit), )) + // This worker consumes the "upsert" event from Redis and redistributes the entities to the "upsertEntities" + // channel and for Host/Service entities also to the "insertSlaEntities" channel. + g.Go(func() error { + defer close(upsertEntities) + if insertSlaEntities != nil { + defer close(insertSlaEntities) + } + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case entity, ok := <-upsertEntitiesMultiplexer: + if !ok { + return nil + } + + select { + case upsertEntities <- entity: + case <-ctx.Done(): + return ctx.Err() + } + + if insertSlaEntities != nil { + select { + case insertSlaEntities <- entity: + case <-ctx.Done(): + return ctx.Err() + } + } + } + } + }) + g.Go(func() error { var counter com.Counter defer periodic.Start(ctx, r.logger.Interval(), func(_ periodic.Tick) { @@ -125,6 +172,59 @@ func (r *RuntimeUpdates) Sync( ) }) + // Consumes from the "insertSlaEntities" channel and bulk inserts into the "sla_lifecycle" table. + g.Go(func() error { + var counter com.Counter + defer periodic.Start(ctx, r.logger.Interval(), func(_ periodic.Tick) { + if count := counter.Reset(); count > 0 { + r.logger.Infof("Inserted %d %s sla lifecycles", count, s.Name()) + } + }).Stop() + + stmt, _ := r.db.BuildInsertIgnoreStmt(v1.NewSlaLifecycle()) + return r.db.NamedBulkExec( + ctx, stmt, upsertCount, r.db.GetSemaphoreForTable(slaLifecycleTable), + CreateSlaLifecyclesFromCheckables(ctx, s.Entity(), g, insertSlaEntities, false), + com.NeverSplit[database.Entity], database.OnSuccessIncrement[database.Entity](&counter)) + }) + + // This worker consumes the "delete" event from Redis and redistributes the IDs to the "deleteIds" + // channel and for Host/Service entities also to the "updateSlaEntities" channel. + g.Go(func() error { + defer close(deleteIds) + if updateSlaEntities != nil { + defer close(updateSlaEntities) + } + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case deleteId, ok := <-deleteIdsMultiplexer: + if !ok { + return nil + } + + select { + case deleteIds <- deleteId: + case <-ctx.Done(): + return ctx.Err() + } + + if updateSlaEntities != nil { + entity := factoryFunc() + entity.SetID(deleteId.(types.Binary)) + + select { + case updateSlaEntities <- entity: + case <-ctx.Done(): + return ctx.Err() + } + } + } + } + }) + g.Go(func() error { var counter com.Counter defer periodic.Start(ctx, r.logger.Interval(), func(_ periodic.Tick) { @@ -142,6 +242,23 @@ func (r *RuntimeUpdates) Sync( return r.db.BulkExec(ctx, r.db.BuildDeleteStmt(s.Entity()), deleteCount, sem, deleteIds, onSuccess...) }) + + // Consumes from the "updateSlaEntities" channel and updates the "delete_time" of each + // SLA lifecycle entry with "delete_time = 0" to now. + g.Go(func() error { + var counter com.Counter + defer periodic.Start(ctx, r.logger.Interval(), func(_ periodic.Tick) { + if count := counter.Reset(); count > 0 { + r.logger.Infof("Updated %d %s sla lifecycles", count, s.Name()) + } + }).Stop() + + stmt := fmt.Sprintf(`UPDATE %s SET delete_time = :delete_time WHERE "id" = :id AND "delete_time" = 0`, slaLifecycleTable) + return r.db.NamedBulkExec( + ctx, stmt, deleteCount, r.db.GetSemaphoreForTable(slaLifecycleTable), + CreateSlaLifecyclesFromCheckables(ctx, s.Entity(), g, updateSlaEntities, true), + com.NeverSplit[database.Entity], database.OnSuccessIncrement[database.Entity](&counter)) + }) } // customvar and customvar_flat sync. From 0b234157dc3ae71b3b034fcc8d62b58726b6f2c6 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 24 Oct 2024 17:05:57 +0200 Subject: [PATCH 4/7] Add integration tests for checkable `SlaLifecycle` --- tests/go.mod | 2 +- tests/go.sum | 4 +- tests/object_sync_test.go | 131 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 8 deletions(-) diff --git a/tests/go.mod b/tests/go.mod index 981b4236c..f0000f5a7 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -6,13 +6,13 @@ require ( github.com/go-sql-driver/mysql v1.8.1 github.com/goccy/go-yaml v1.12.0 github.com/google/uuid v1.6.0 + github.com/icinga/icinga-go-library v0.3.0 github.com/icinga/icinga-testing v0.0.0-20240322142451-494ccd6d03e8 github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 github.com/redis/go-redis/v9 v9.7.0 github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20221012112151-59b0eab1532e golang.org/x/sync v0.8.0 ) diff --git a/tests/go.sum b/tests/go.sum index 54a112ed1..aac658004 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -66,6 +66,8 @@ 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/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/icinga/icinga-go-library v0.3.0 h1:BeoomAiQC5RTRWCNqNkgbdTGxQ7ZFfkruR4HCSn5e0k= +github.com/icinga/icinga-go-library v0.3.0/go.mod h1:YN7XJN3W0FodD+j4kirO89zk2tgvanXWt1RMV8UgOLo= github.com/icinga/icinga-testing v0.0.0-20240322142451-494ccd6d03e8 h1:PI+39IY1BjN24JC3B6Jy0rhwm3hqC4SnQFxbZjXOaHk= github.com/icinga/icinga-testing v0.0.0-20240322142451-494ccd6d03e8/go.mod h1:xjNiwePgnSVKJWPG/iFG7pNOibU/OWp01Zdl08o+EeI= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= @@ -171,8 +173,6 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= -golang.org/x/exp v0.0.0-20221012112151-59b0eab1532e h1:/SJUJZl3kz7J5GzAx5lgaKvqKGd4OfzshwDMr6YJCC4= -golang.org/x/exp v0.0.0-20221012112151-59b0eab1532e/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= diff --git a/tests/object_sync_test.go b/tests/object_sync_test.go index 23d2c96a0..30f95fcbf 100644 --- a/tests/object_sync_test.go +++ b/tests/object_sync_test.go @@ -6,6 +6,7 @@ import ( "database/sql" _ "embed" "fmt" + "github.com/icinga/icinga-go-library/types" "github.com/icinga/icinga-testing/services" "github.com/icinga/icinga-testing/utils" "github.com/icinga/icinga-testing/utils/eventually" @@ -16,9 +17,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - "golang.org/x/exp/slices" "io" "reflect" + "slices" "sort" "strings" "testing" @@ -112,7 +113,6 @@ func TestObjectSync(t *testing.T) { t.Parallel() for _, host := range data.Hosts { - host := host t.Run("Verify-"+host.VariantInfoString(), func(t *testing.T) { t.Parallel() @@ -144,7 +144,6 @@ func TestObjectSync(t *testing.T) { t.Parallel() for _, service := range data.Services { - service := service t.Run("Verify-"+service.VariantInfoString(), func(t *testing.T) { t.Parallel() @@ -171,6 +170,40 @@ func TestObjectSync(t *testing.T) { } }) + t.Run("SlaLifeCycle", func(t *testing.T) { + t.Parallel() + + slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())} + + t.Run("Hosts", func(t *testing.T) { + t.Parallel() + + for hostId, host := range data.Hosts { + t.Run("Verify-Host-"+fmt.Sprint(hostId), func(t *testing.T) { + t.Parallel() + + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifeCycleRow(t, db, slinfo, host.Name, "") + }, 20*time.Second, 1*time.Second) + }) + } + }) + + t.Run("Services", func(t *testing.T) { + t.Parallel() + + for serviceId, service := range data.Services { + t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) { + t.Parallel() + + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifeCycleRow(t, db, slinfo, *service.HostName, service.Name) + }, 20*time.Second, 1*time.Second) + }) + } + }) + }) + t.Run("HostGroup", func(t *testing.T) { t.Parallel() // TODO(jb): add tests @@ -324,8 +357,6 @@ func TestObjectSync(t *testing.T) { t.Parallel() for _, service := range makeTestSyncServices(t) { - service := service - t.Run("CreateAndDelete-"+service.VariantInfoString(), func(t *testing.T) { t.Parallel() @@ -418,6 +449,34 @@ func TestObjectSync(t *testing.T) { }) }) + t.Run("SlaLifeCycle", func(t *testing.T) { + t.Parallel() + + for serviceId, service := range makeTestSyncServices(t) { + //service.Name += fmt.Sprint(serviceId) + + t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) { + t.Parallel() + + client.CreateObject(t, "services", *service.HostName+"!"+service.Name, map[string]interface{}{ + "attrs": makeIcinga2ApiAttributes(service, false), + }) + + slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())} + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifeCycleRow(t, db, slinfo, *service.HostName, service.Name) + }, 20*time.Second, 1*time.Second) + + client.DeleteObject(t, "services", *service.HostName+"!"+service.Name, false) + + slinfo.DeleteTime = types.UnixMilli(time.Now()) + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifeCycleRow(t, db, slinfo, "", "") + }, 20*time.Second, 1*time.Second) + }) + } + }) + t.Run("User", func(t *testing.T) { t.Parallel() @@ -1188,6 +1247,68 @@ func verifyIcingaDbRow(t require.TestingT, db *sqlx.DB, obj interface{}) { require.False(t, rows.Next(), "SQL query should return only one row: %s", query) } +func verifySlaLifeCycleRow(t require.TestingT, db *sqlx.DB, slinfo *SlaLifecycle, host string, service string) { + query := `SELECT "create_time", "delete_time", "sla_lifecycle"."host_id", "sla_lifecycle"."service_id" FROM "sla_lifecycle"` + var args []interface{} + if !slinfo.HostID.Valid() { + query += ` INNER JOIN "host" ON "host"."id"="sla_lifecycle"."host_id"` + where := ` WHERE "host"."name"=?` + + args = append(args, host) + if service == "" { + where += ` AND "service_id" IS NULL` + } else { + query += ` INNER JOIN "service" ON "service"."id"="sla_lifecycle"."service_id"` + where += ` AND "service"."name"=?` + args = append(args, service) + } + + query += where + ` AND "delete_time" = 0` + } else { + query += ` WHERE "host_id"=?` + args = []interface{}{slinfo.HostID} + if !slinfo.ServiceID.Valid() { + query += ` AND "service_id" IS NULL` + } else { + query += ` AND "service_id"=?` + args = append(args, slinfo.ServiceID) + } + } + + var resultSet []SlaLifecycle + err := db.Select(&resultSet, db.Rebind(query), args...) + require.NoError(t, err, "querying sla lifecycle should not fail: Query: %q", query) + + require.Len(t, resultSet, 1, "there should be one sla lifecycle entry") + + result := resultSet[0] + zerotimestamp := time.Unix(0, 0) + + require.NotEqual(t, zerotimestamp, result.CreateTime.Time()) + assert.WithinDuration(t, slinfo.CreateTime.Time(), result.CreateTime.Time(), time.Minute) + + if slinfo.DeleteTime.Time().IsZero() { + // We can't join on the host/service tables, as the sla lifecycle entries may reference entries that have + // already been deleted. So cache the host/service id to use as a filter when asserting the sla lifecycles + // delete event. + slinfo.HostID = result.HostID + slinfo.ServiceID = result.ServiceID + + require.Equal(t, zerotimestamp, result.DeleteTime.Time()) + } else { + require.NotEqual(t, zerotimestamp, result.DeleteTime.Time()) + require.Less(t, result.CreateTime.Time(), result.DeleteTime.Time()) + assert.WithinDuration(t, slinfo.DeleteTime.Time(), result.DeleteTime.Time(), time.Minute) + } +} + +type SlaLifecycle struct { + CreateTime types.UnixMilli `db:"create_time"` + DeleteTime types.UnixMilli `db:"delete_time"` + HostID types.Binary `db:"host_id"` + ServiceID types.Binary `db:"service_id"` +} + // newString allocates a new *string and initializes it. This helper function exists as // there seems to be no way to achieve this within a single statement. func newString(s string) *string { From c5abf9391b2e17b3b0b72b54198d5d01c6b26cf2 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 24 Oct 2024 17:06:17 +0200 Subject: [PATCH 5/7] Test host runtime updates & document some helper functions --- tests/object_sync_test.go | 185 ++++++++++++++++++++++++++------------ 1 file changed, 129 insertions(+), 56 deletions(-) diff --git a/tests/object_sync_test.go b/tests/object_sync_test.go index 30f95fcbf..024c683b5 100644 --- a/tests/object_sync_test.go +++ b/tests/object_sync_test.go @@ -173,7 +173,7 @@ func TestObjectSync(t *testing.T) { t.Run("SlaLifeCycle", func(t *testing.T) { t.Parallel() - slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())} + createTime := types.UnixMilli(time.Now()) t.Run("Hosts", func(t *testing.T) { t.Parallel() @@ -182,8 +182,14 @@ func TestObjectSync(t *testing.T) { t.Run("Verify-Host-"+fmt.Sprint(hostId), func(t *testing.T) { t.Parallel() + slinfo := &SlaLifecycle{CreateTime: createTime} + eventually.Assert(t, func(t require.TestingT) { - verifySlaLifeCycleRow(t, db, slinfo, host.Name, "") + // We can't join on the host table, as the sla lifecycle entries may reference hosts that have + // already been deleted. So fetch the host id from DB before performing the actual test. + require.NoError(t, fetchCheckableId(db, slinfo, host.Name, "")) + + verifySlaLifecycleRow(t, db, slinfo, false) }, 20*time.Second, 1*time.Second) }) } @@ -196,8 +202,14 @@ func TestObjectSync(t *testing.T) { t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) { t.Parallel() + slinfo := &SlaLifecycle{CreateTime: createTime} + eventually.Assert(t, func(t require.TestingT) { - verifySlaLifeCycleRow(t, db, slinfo, *service.HostName, service.Name) + // We can't join on the service table, as the sla lifecycle entries may reference services that + // have already been deleted. So fetch the service id from DB before performing the actual test. + require.NoError(t, fetchCheckableId(db, slinfo, *service.HostName, service.Name)) + + verifySlaLifecycleRow(t, db, slinfo, false) }, 20*time.Second, 1*time.Second) }) } @@ -452,29 +464,71 @@ func TestObjectSync(t *testing.T) { t.Run("SlaLifeCycle", func(t *testing.T) { t.Parallel() - for serviceId, service := range makeTestSyncServices(t) { - //service.Name += fmt.Sprint(serviceId) + assertCheckableFunc := func(checkable any, objType string, objName string, host string, service string) { + client.CreateObject(t, objType, objName, map[string]any{ + "attrs": makeIcinga2ApiAttributes(checkable, false), + }) - t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) { - t.Parallel() + slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())} + eventually.Assert(t, func(t require.TestingT) { + // We can't join on the host/service tables, as the sla lifecycle entries may reference checkables + // that have already been deleted. So fetch the host/service id from DB before performing the actual test. + require.NoError(t, fetchCheckableId(db, slinfo, host, service)) - client.CreateObject(t, "services", *service.HostName+"!"+service.Name, map[string]interface{}{ - "attrs": makeIcinga2ApiAttributes(service, false), - }) + verifySlaLifecycleRow(t, db, slinfo, false) + }, 20*time.Second, 1*time.Second) - slinfo := &SlaLifecycle{CreateTime: types.UnixMilli(time.Now())} - eventually.Assert(t, func(t require.TestingT) { - verifySlaLifeCycleRow(t, db, slinfo, *service.HostName, service.Name) - }, 20*time.Second, 1*time.Second) + client.DeleteObject(t, objType, objName, false) - client.DeleteObject(t, "services", *service.HostName+"!"+service.Name, false) + slinfo.DeleteTime = types.UnixMilli(time.Now()) + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifecycleRow(t, db, slinfo, false) + }, 20*time.Second, 1*time.Second) - slinfo.DeleteTime = types.UnixMilli(time.Now()) - eventually.Assert(t, func(t require.TestingT) { - verifySlaLifeCycleRow(t, db, slinfo, "", "") - }, 20*time.Second, 1*time.Second) + client.CreateObject(t, objType, objName, map[string]interface{}{ + "attrs": makeIcinga2ApiAttributes(checkable, false), }) + + // We are recreating this checkable, so we only have to change the timestamps as the + // checkable id will remain the same. + slinfo.CreateTime = types.UnixMilli(time.Now()) + slinfo.DeleteTime = types.UnixMilli(time.Time{}) + + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifecycleRow(t, db, slinfo, true) + }, 20*time.Second, 1*time.Second) + + client.DeleteObject(t, objType, objName, false) + + slinfo.DeleteTime = types.UnixMilli(time.Now()) + eventually.Assert(t, func(t require.TestingT) { + verifySlaLifecycleRow(t, db, slinfo, true) + }, 20*time.Second, 1*time.Second) } + + t.Run("Host", func(t *testing.T) { + t.Parallel() + + for hostId, host := range makeTestSyncHosts(t) { + t.Run("Verify-Host-"+fmt.Sprint(hostId), func(t *testing.T) { + t.Parallel() + + assertCheckableFunc(host, "hosts", host.Name, host.Name, "") + }) + } + }) + + t.Run("Service", func(t *testing.T) { + t.Parallel() + + for serviceId, service := range makeTestSyncServices(t) { + t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) { + t.Parallel() + + assertCheckableFunc(service, "services", *service.HostName+"!"+service.Name, *service.HostName, service.Name) + }) + } + }) }) t.Run("User", func(t *testing.T) { @@ -1247,61 +1301,80 @@ func verifyIcingaDbRow(t require.TestingT, db *sqlx.DB, obj interface{}) { require.False(t, rows.Next(), "SQL query should return only one row: %s", query) } -func verifySlaLifeCycleRow(t require.TestingT, db *sqlx.DB, slinfo *SlaLifecycle, host string, service string) { - query := `SELECT "create_time", "delete_time", "sla_lifecycle"."host_id", "sla_lifecycle"."service_id" FROM "sla_lifecycle"` +// verifySlaLifecycleRow verifies the sla lifecycle entries matching the given host/service id. It checks the creation +// and deletion time of the specified checkable. When the provided checkable was recreated, it also additionally requires +// two sla lifecycle entries to exist that match the checkables id. +func verifySlaLifecycleRow(t require.TestingT, db *sqlx.DB, slinfo *SlaLifecycle, isRecreated bool) { + query := `SELECT "create_time", "delete_time" FROM "sla_lifecycle" WHERE "host_id" = ?` var args []interface{} - if !slinfo.HostID.Valid() { - query += ` INNER JOIN "host" ON "host"."id"="sla_lifecycle"."host_id"` - where := ` WHERE "host"."name"=?` - - args = append(args, host) - if service == "" { - where += ` AND "service_id" IS NULL` - } else { - query += ` INNER JOIN "service" ON "service"."id"="sla_lifecycle"."service_id"` - where += ` AND "service"."name"=?` - args = append(args, service) - } - - query += where + ` AND "delete_time" = 0` + args = []interface{}{slinfo.HostID} + if !slinfo.ServiceID.Valid() { + query += ` AND "service_id" IS NULL` } else { - query += ` WHERE "host_id"=?` - args = []interface{}{slinfo.HostID} - if !slinfo.ServiceID.Valid() { - query += ` AND "service_id" IS NULL` - } else { - query += ` AND "service_id"=?` - args = append(args, slinfo.ServiceID) - } + query += ` AND "service_id" = ?` + args = append(args, slinfo.ServiceID) } + query += ` ORDER BY "create_time" ASC` var resultSet []SlaLifecycle err := db.Select(&resultSet, db.Rebind(query), args...) require.NoError(t, err, "querying sla lifecycle should not fail: Query: %q", query) - require.Len(t, resultSet, 1, "there should be one sla lifecycle entry") - - result := resultSet[0] zerotimestamp := time.Unix(0, 0) + var result SlaLifecycle - require.NotEqual(t, zerotimestamp, result.CreateTime.Time()) + if isRecreated { + require.Len(t, resultSet, 2, "there should be two sla lifecycle entry") + + result = resultSet[1] + recreated := resultSet[0] + assert.NotEqual(t, zerotimestamp, recreated.CreateTime.Time()) + assert.NotEqual(t, zerotimestamp, recreated.DeleteTime.Time()) + + assert.Less(t, recreated.CreateTime.Time(), slinfo.CreateTime.Time()) + assert.Less(t, recreated.DeleteTime.Time(), slinfo.CreateTime.Time()) + + if !slinfo.DeleteTime.Time().IsZero() { + assert.Less(t, recreated.CreateTime.Time(), slinfo.DeleteTime.Time()) + assert.Less(t, recreated.DeleteTime.Time(), slinfo.DeleteTime.Time()) + } + } else { + require.Len(t, resultSet, 1, "there should be one sla lifecycle entry") + + result = resultSet[0] + } + + assert.NotEqual(t, zerotimestamp, result.CreateTime.Time()) assert.WithinDuration(t, slinfo.CreateTime.Time(), result.CreateTime.Time(), time.Minute) if slinfo.DeleteTime.Time().IsZero() { - // We can't join on the host/service tables, as the sla lifecycle entries may reference entries that have - // already been deleted. So cache the host/service id to use as a filter when asserting the sla lifecycles - // delete event. - slinfo.HostID = result.HostID - slinfo.ServiceID = result.ServiceID - - require.Equal(t, zerotimestamp, result.DeleteTime.Time()) + assert.Equal(t, zerotimestamp, result.DeleteTime.Time()) } else { - require.NotEqual(t, zerotimestamp, result.DeleteTime.Time()) - require.Less(t, result.CreateTime.Time(), result.DeleteTime.Time()) + assert.NotEqual(t, zerotimestamp, result.DeleteTime.Time()) + assert.Less(t, result.CreateTime.Time(), result.DeleteTime.Time()) assert.WithinDuration(t, slinfo.DeleteTime.Time(), result.DeleteTime.Time(), time.Minute) } } +// fetchCheckableId retrieves host/service id from the database matching the given host/service +// name and scans to the provided slinfo. Returns an error on any database failure. +func fetchCheckableId(db *sqlx.DB, slinfo *SlaLifecycle, host string, service string) error { + query := `SELECT "sla_lifecycle"."host_id", "sla_lifecycle"."service_id" + FROM "sla_lifecycle" INNER JOIN "host" ON "host"."id"="sla_lifecycle"."host_id"` + + where := ` WHERE "host"."name" = ?` + args := []interface{}{host} + if service == "" { + where += ` AND "service_id" IS NULL` + } else { + query += ` INNER JOIN "service" ON "service"."id"="sla_lifecycle"."service_id"` + where += ` AND "service"."name" = ?` + args = append(args, service) + } + + return db.QueryRowx(db.Rebind(query+where), args...).StructScan(slinfo) +} + type SlaLifecycle struct { CreateTime types.UnixMilli `db:"create_time"` DeleteTime types.UnixMilli `db:"delete_time"` From e028c93c0f4b650f6333885463ed4aac1a32aac6 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 24 Oct 2024 17:07:11 +0200 Subject: [PATCH 6/7] Test creation & deletion of sla lifecycles via config sync --- tests/config_sync_delta_slalifecycle.conf | 11 +++ tests/object_sync_test.go | 87 +++++++++++++++++------ 2 files changed, 76 insertions(+), 22 deletions(-) create mode 100644 tests/config_sync_delta_slalifecycle.conf diff --git a/tests/config_sync_delta_slalifecycle.conf b/tests/config_sync_delta_slalifecycle.conf new file mode 100644 index 000000000..e0c1e5ef4 --- /dev/null +++ b/tests/config_sync_delta_slalifecycle.conf @@ -0,0 +1,11 @@ +for (var index in range(5)) { + var hostName = "sla-lifecycle-host-" + index + object Host hostName { + check_command = "hostalive" + } + + object Service "sla-lifecycle-service" use (hostName) { + host_name = hostName + check_command = "dummy" + } +} diff --git a/tests/object_sync_test.go b/tests/object_sync_test.go index 024c683b5..a6130b5f5 100644 --- a/tests/object_sync_test.go +++ b/tests/object_sync_test.go @@ -31,6 +31,9 @@ import ( var testSyncConfRaw string var testSyncConfTemplate = template.Must(template.New("testdata.conf").Parse(testSyncConfRaw)) +//go:embed config_sync_delta_slalifecycle.conf +var slaLifecycleConfigSync []byte + var usergroups = []string{ "testusergroup1", "testusergroup2", @@ -92,9 +95,9 @@ func TestObjectSync(t *testing.T) { require.NoError(t, err, "generate icinga2 notification config") } //logger.Sugar().Infof("config:\n\n%s\n\n", conf.String()) - i.WriteConfig("etc/icinga2/conf.d/testdata.conf", conf.Bytes()) + i.WriteConfig("etc/icinga2/conf.d/testdata.conf", slaLifecycleConfigSync) i.EnableIcingaDb(r) - i.Reload() + require.NoError(t, i.Reload(), "Icinga 2 reload") // Wait for Icinga 2 to signal a successful dump before starting // Icinga DB to ensure that we actually test the initial sync. @@ -105,10 +108,54 @@ func TestObjectSync(t *testing.T) { logger.Debug("starting icingadb") it.IcingaDbInstanceT(t, r, rdb) + // Wait some time to give Icinga DB a chance to finish syncing the 5 dummy hosts and services. + time.Sleep(2 * time.Second) + db, err := sqlx.Open(rdb.Driver(), rdb.DSN()) require.NoError(t, err, "connecting to SQL database shouldn't fail") t.Cleanup(func() { _ = db.Close() }) + dummyHostIdsMap := map[string]SlaLifecycle{} + dummyServiceIdsMap := map[string]SlaLifecycle{} + scanDummyObjFunc := func(typ string) { + var query string + if typ == "service" { + query = `SELECT service.name AS service_name, host.name as host_name, service.id AS service_id, host_id FROM service INNER JOIN host ON host.id=host_id` + } else { + query = `SELECT "name" AS host_name, id AS host_id FROM host` + } + + rows, err := db.Queryx(query) + assert.NoError(t, err, "select all dummy %s ids", typ) + defer rows.Close() + + for rows.Next() { + obj := &struct { + HostName string `db:"host_name"` + ServiceName string `db:"service_name"` + SlaLifecycle `db:",inline"` + }{ + SlaLifecycle: SlaLifecycle{CreateTime: types.UnixMilli(time.Now())}, + } + + require.NoError(t, rows.StructScan(obj), "scan dummy %s", typ) + + if typ == "host" { + dummyHostIdsMap[obj.HostName] = obj.SlaLifecycle + } else { + dummyServiceIdsMap[obj.HostName+"!"+obj.ServiceName] = obj.SlaLifecycle + } + } + } + + // Fetch the dummy host and service ids from the database before reloading Icinga 2 with the new config. + go scanDummyObjFunc("host") + go scanDummyObjFunc("service") + + // Write the regular conf bytes excluding the dummy bytes we wrote earlier and reload the Icinga 2 instance. + i.WriteConfig("etc/icinga2/conf.d/testdata.conf", conf.Bytes()) + require.NoError(t, i.Reload(), "Icinga 2 reload") + t.Run("Host", func(t *testing.T) { t.Parallel() @@ -173,23 +220,21 @@ func TestObjectSync(t *testing.T) { t.Run("SlaLifeCycle", func(t *testing.T) { t.Parallel() - createTime := types.UnixMilli(time.Now()) - + deleteTime := types.UnixMilli(time.Now()) t.Run("Hosts", func(t *testing.T) { t.Parallel() - for hostId, host := range data.Hosts { - t.Run("Verify-Host-"+fmt.Sprint(hostId), func(t *testing.T) { + for i := 0; i < 5; i++ { + host := &Host{Name: "sla-lifecycle-host-" + fmt.Sprint(i)} + + t.Run("Verify-Host-"+fmt.Sprint(i), func(t *testing.T) { t.Parallel() - slinfo := &SlaLifecycle{CreateTime: createTime} + slinfo := dummyHostIdsMap[host.Name] + slinfo.DeleteTime = deleteTime eventually.Assert(t, func(t require.TestingT) { - // We can't join on the host table, as the sla lifecycle entries may reference hosts that have - // already been deleted. So fetch the host id from DB before performing the actual test. - require.NoError(t, fetchCheckableId(db, slinfo, host.Name, "")) - - verifySlaLifecycleRow(t, db, slinfo, false) + verifySlaLifecycleRow(t, db, &slinfo, false) }, 20*time.Second, 1*time.Second) }) } @@ -198,18 +243,17 @@ func TestObjectSync(t *testing.T) { t.Run("Services", func(t *testing.T) { t.Parallel() - for serviceId, service := range data.Services { - t.Run("Verify-Service-"+fmt.Sprint(serviceId), func(t *testing.T) { + for i := 0; i < 5; i++ { + service := &Service{Name: "sla-lifecycle-service", HostName: newString("sla-lifecycle-host-" + fmt.Sprint(i))} + + t.Run("Verify-Service-"+fmt.Sprint(i), func(t *testing.T) { t.Parallel() - slinfo := &SlaLifecycle{CreateTime: createTime} + slinfo := dummyServiceIdsMap[*service.HostName+"!"+service.Name] + slinfo.DeleteTime = deleteTime eventually.Assert(t, func(t require.TestingT) { - // We can't join on the service table, as the sla lifecycle entries may reference services that - // have already been deleted. So fetch the service id from DB before performing the actual test. - require.NoError(t, fetchCheckableId(db, slinfo, *service.HostName, service.Name)) - - verifySlaLifecycleRow(t, db, slinfo, false) + verifySlaLifecycleRow(t, db, &slinfo, false) }, 20*time.Second, 1*time.Second) }) } @@ -1306,8 +1350,7 @@ func verifyIcingaDbRow(t require.TestingT, db *sqlx.DB, obj interface{}) { // two sla lifecycle entries to exist that match the checkables id. func verifySlaLifecycleRow(t require.TestingT, db *sqlx.DB, slinfo *SlaLifecycle, isRecreated bool) { query := `SELECT "create_time", "delete_time" FROM "sla_lifecycle" WHERE "host_id" = ?` - var args []interface{} - args = []interface{}{slinfo.HostID} + args := []interface{}{slinfo.HostID} if !slinfo.ServiceID.Valid() { query += ` AND "service_id" IS NULL` } else { From 7aa02ddc6c7247e2b6c7ac68f77781de44f62d35 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 24 Oct 2024 17:07:51 +0200 Subject: [PATCH 7/7] Add SLA reporting docs --- doc/10-Sla-Reporting.md | 232 ++++++++++++++++++++++++++++ doc/images/sla_history_downtime.png | Bin 0 -> 69988 bytes doc/images/sla_history_state.png | Bin 0 -> 43039 bytes doc/images/sla_lifecycle.png | Bin 0 -> 36257 bytes 4 files changed, 232 insertions(+) create mode 100644 doc/10-Sla-Reporting.md create mode 100644 doc/images/sla_history_downtime.png create mode 100644 doc/images/sla_history_state.png create mode 100644 doc/images/sla_lifecycle.png diff --git a/doc/10-Sla-Reporting.md b/doc/10-Sla-Reporting.md new file mode 100644 index 000000000..203256257 --- /dev/null +++ b/doc/10-Sla-Reporting.md @@ -0,0 +1,232 @@ +# SLA Reporting + +A Service Level Agreement (SLA) is a legally binding contract between a service provider and a customer. +Its purpose is to define the level of service that the supplier promises to deliver to the customer. + +Icinga DB is designed to automatically identify and record the most relevant checkable events exclusively in a separate +table. By default, these events are retained forever unless you have set the retention +[`sla-days` option](03-Configuration.md#retention). It is important to note that Icinga DB records the raw events in +the database without any interpretation. In order to generate and visualise SLA reports of specific hosts and services +based on the accumulated events over time, [Icinga Reporting](https://icinga.com/docs/icinga-reporting/latest/doc/02-Installation/) +is the optimal complement, facilitating comprehensive SLA report generation within a specific timeframe. + +## Technical Description + +!!! info + + This documentation provides a detailed technical explanation of how Icinga DB fulfils all the + necessary requirements for the generation of an accurate service level agreement (SLA). + +Icinga DB provides a built-in support for automatically storing the relevant events of your hosts and services without +a manual action. Generally, these events are every **hard** state change a particular checkable encounters and all the +downtimes scheduled for that checkable throughout its entire lifetime. It is important to note that the aforementioned +events are not analogous to those utilised by [Icinga DB Web](https://icinga.com/docs/icinga-db-web/latest/) for +visualising host and service states. + +!!! info + + [Acknowledgements](https://icinga.com/docs/icinga-2/latest/doc/08-advanced-topics/#acknowledgements) are special + events that mainly control the Icinga 2 notification logic behaviour, and acknowledging a host problem will not + have an impact on the SLA result for that host. + +In case of a hard state change of a monitored host or service, Icinga DB records the precise temporal occurrence of +that state change in milliseconds within the `sla_history_state` table. The following image serves as a visual +illustration of the relational and representational aspects of state change events. + +![SLA history state](images/sla_history_state.png) + +In contrast, two timestamps are retained for downtimes, one indicating the commencement of the downtime as +`downtime_start` and the other denoting its end time, designated as `downtime_end` within the `sla_history_downtime` +table. For the sake of completeness, the following image provides also a visual representation of the +`sla_history_downtime` table and its relations. + +![SLA history downtime](images/sla_history_downtime.png) + +In certain circumstances, namely when a checkable is created and subsequently never deleted, this approach has been +empirically [demonstrated](#computing-sla-ok-percent) to be sufficient. Nevertheless, in the case of a host being +deleted and then recreated a couple of days later, the generation of SLA reports in +[Icinga Reporting](https://icinga.com/docs/icinga-reporting/latest/doc/02-Installation/) for that host at +the end of the week may yield disparate results, depending on the host state prior to its deletion. + +In order to generate SLA reports with the greatest possible accuracy, we have decided to supplement the existing data +with information regarding the **creation** and **deletion** of hosts and services in a new `sla_lifecycle` table, +introduced in Icinga DB **1.3.0**. This new table has a composite primary key consisting of two columns: `id` and +`delete_time`. In this way, the `delete_time` is used to indicate whether a specific checkable has been deleted, +with a `0` value denoting non-deleted object. In a perfect world, we would use `NULL` instead of `0` but due to the +[primary key `constraints`](https://dev.mysql.com/doc/refman/8.4/en/create-table.html#create-table-indexes-keys), +this is not possible. The `id` column represents either the service or host ID for which that particular sla lifecycle +is being generated. + +![SLA lifecycle](images/sla_lifecycle.png) + +The upgrade script for `1.3.0` generates a `create_time` SLA lifecycle entry for all existing hosts and services. +However, since that script has no knowledge of the creation time of these existing objects, the timestamp for them is +produced in the following manner: As previously outlined, Icinga DB has the capability to store timestamps for both +hard state changes and downtimes since its first stable release. This enables the upgrade script to identify the least +event timestamp of a given checkable from the `sla_history_state` and `sla_history_downtime` tables. In cases where no +timestamps can be obtained from the aforementioned tables, it simply fallbacks to `now`, i.e. in such situations, +the creation time of the checkable in question is set to the current timestamp. + +### Events Processing + +It is noteworthy that Icinga DB does not record checkable **soft** state changes, in the regular `service_state` +and `host_state` tables. However, for the `state_history`, for instance, all state changes are retrieved from Redis® +and persisted to the database, irrespective of whether it is in High Availability (HA) or single-instance mode. +Each time Icinga DB processes a state change, it checks whether it is a hard state change and generates the +corresponding SLA state event in the `sla_history_state` table. Similarly, Icinga DB generates a corresponding SLA +history downtime (`sla_history_downtime`) each time it receives a downtime-triggered or ended/cancelled event from +Icinga 2. Notably, if Icinga DB is operating in HA mode, this process takes place in parallel, i.e. both instances +concurrently write their respective histories to the database, consequently, the aforementioned tables have also to +track the endpoint ids in their `endpoint_id` column. + +Though, it is not necessary to be concerned about the potential duplicate entries in the database, as long as the events +from both Icinga DB instances have the same timestamp, there will be no duplicates. For instance, downtimes have unique +and deterministic IDs, allowing the second instance to detect if that very same downtime has already been recorded by +the other instance. + +The checkable events of the types **created** and **deleted**, on the other hand, are special and represent the life +cycle of the chekables. These two events are always written by a single Icinga DB instance at a time (if in HA mode) to +the `sla_lifecycle` table, denoting the creation and deletion of a checkable in Icinga 2. Unfortunately, Icinga 2 lacks +the capability to accurately determine the deletion time of an object. It should also be noted that Icinga DB is also +incapable of identifying the precise timestamp of an object's deletion. Instead, it simply records the time at which +the deletion event for that particular checkable occurred and populates the `sla_lifecycle` table accordingly. +Consequently, if a checkable is deleted while Icinga DB is stopped or not in an operational state, the events that +Icinga DB would otherwise record once it is restarted will not reflect the actual deletion or creation time. + +#### Initial Config Sync + +Each time when either the Icinga DB or Icinga 2 service is reloaded, Icinga DB computes something called a config +`delta`. The config delta determines which objects need to be deleted from the database, to be updated, or are new and +need to be inserted. After successfully computing and dumping the config, Icinga DB then performs a simple SQL +`INSERT INTO sla_lifecycle` statements for all checkables that don't already have **created** SLA event with +`delete_time` set to `0` and sets their `create_time` to `now`. Additionally, it also updates the `delete_time` column +of each existing SLA lifecycle entries whose checkable IDs cannot be found in the `host/service` tables. + +#### Runtime Updates + +When a host or service is created or deleted at runtime, either using +[Icinga Director](https://icinga.com/docs/icinga-director/latest/doc/01-Introduction/) or the plain `/v1/objects` API +endpoint, Icinga DB automatically generates an SLA lifecycle entry denoting the checkable creation or deletion time. +For all runtime *created* checkables, the SLA lifecycle entries are inserted using a slightly sophisticated SQL `INSERT` +statement with ignore on error mechanism, i.e. if it encounters a `duplicate key` error, it simply suppresses the error +and discards the query. In contrast, for runtime *deleted* checkables, it assumes that there is an SLA lifecycle +**created** event for these checkables, and uses a simple `UPDATE` statement setting their deletion time to now. +Consequently, should there be no corresponding **created** event for these checkables, the update statement becomes a +no-op, as the [initial config dump](#initial-config-sync) should have created the necessary entries for all existing +objects. + +### Computing SLA OK percent + +The following is a simplified explanation of the current (Icinga DB `1.3.0`) methodology behind the `get_sla_ok_percent` +SQL procedure, used to calculate the SLA OK percent. It is a fundamental characteristic of functional specifications +for Icinga Reporting to only generate reports covering a specific timeframe. Accordingly, the `get_sla_ok_percent` +SQL procedure necessitates the input of the start and end timeframes within which the SLA is to be calculated. + +First, it is necessary to identify the latest [`hard_state`](#hard-state-vs-previous-hard-state) of the service or host +that occurred at or prior to the timeline start date, and marking it as the initial one. In case the first query fails +to determine a `hard_state` entry, it proceeds to search for a [`previous_hard_state`](#hard-state-vs-previous-hard-state) +entry in the `sla_history_state` table that have been recorded after the start of the timeline. If this approach also +fails to retrieve the desired outcome, the regular non-historical `host_state` or `service_state` table is then +examined for the current state. Should this also produce no results, then it uses `OK` as its initial state. + +Next, we need to get the total time of the specified timeframe, expressed in milliseconds, for which we're going to +compute the SLA OK percent (`total_time = timeline_end - timeline_start`). + +Afterward, it traverses the entire state and downtime events within the provided timeframe, performing a series of +simple arithmetic operations. The complete algorithmic process is illustrated in the following pseudocode. + +``` +total_time := timeline_end - timeline_start + +// Mark the timeline start date as our last event time for now. +last_event_time := timeline_start + +// The problem time of a given host or service is initially set to zero. +problem_time := 0 + +// The previous_hard_state is determined dynamically as described above, however, +// for the purposes of this analysis, we'll just set it to 'OK'. +previous_hard_state := OK + +// Loop through all the state and downtime events within the provided timeframe ordered by their timestamp. +for event in (sla_history_state, sla_history_downtime) do + if (event.previous_hard_state is PENDING) then + // A PENDING state event indicates that the host or service in question has not yet had a check result that + // clearly identifies its state. Consequently, such events become irrelevant for the purposes of calculating + // the SLA and we must exclude the duration of that PENDING state from the total time. + total_time = total_time - (event.event_time - last_event_time) + else if (previous_hard_state is greater than OK/UP + AND previous_hard_state is not PENDING + AND checkable is not in DOWNTIME) then + // If the previous_hard_state is set to a non-OK state and the host or service in question was not in downtime, + // we consider that time slot to be problematic and add the duration to the problem time. + problem_time = problem_time + (event.event_time - last_event_time) + endif + + // Set the "last_event_time" to the timestamp of the event being currently processed. + last_event_time = event.event_time + + if (event.type is "state change event") then + // If the event being currently processed is a state change event, we mark its + // latest hard state as the previous one for the next iteration. + previous_hard_state = event.hard_state + endif +endloop +``` + +At this point, we now have computed the problem time of a particular host or service for a given time frame. The final +step is to determine the percentage of the remaining total time. In other words, we want to find out how much of the +total time is taken up by the problem time, so that we can obtain our final SLA OK percentage result. + +``` +sla_ok_percent := 100 * (total_time - problem_time) / total_time +``` + +The following example illustrates the practical implications of this concept. Suppose we have the following SLA events: +```json +{ + "state": [ + {"event_time": 1200, "hard_state": 2, "previous_hard_state": 0}, + {"event_time": 1500, "hard_state": 0, "previous_hard_state": 2} + ], + "downtime": [ + {"downtime_start": 1100, "downtime_end": 1300}, + {"downtime_start": 1400, "downtime_end": 1600} + ] +} +``` + +We would now like to calculate the SLA OK percent for the timeframe from `1000` to `2000`. + +``` +total_time := 2000 - 1000 +problem_time := 0 + +- 1000..1200 // in OK state (see the previous_hard_state of the first state event), so nothing to do. +- 1200..1300 // in Critical state, but was also set in downtime from (1100..1300), so here also nothing to do. +- 1300..1400 // still in Critical state and is not in downtime, so we count that time slot as a problem time. +problem_time = problem_time + 1400 - 1300 + +- 1400..1500 // still in critical state, but we have an active downtime during this period again, so nothing to do. +- 1500..2000 // in OK state + +// So, this indicates that our host was either not in a problem state or was set +// to a downtime for 90% of the period from 1000 to 2000. +sla_ok_percent := 100 * (total_time - problem_time) / total_time +``` + +## Appendix + +### Hard State vs. Previous Hard State + +The `hard_state` column denotes the most recent hard state of the host and service. +Conversely, the `previous_hard_state` column indicates the preceding hard state that was formerly stored in the +`hard_state` column prior to the host or service transitioning to a new hard state. Please refer to the tabular +representation below for a visual representation of this information. + +| previous_hard_state | hard_state | +|-------------------------------|------------| +| PENDING (no check result yet) | OK | +| OK | Warning | +| Warning | Critical | +| Critical | OK | diff --git a/doc/images/sla_history_downtime.png b/doc/images/sla_history_downtime.png new file mode 100644 index 0000000000000000000000000000000000000000..76e6929c48c93a2fd64c27f0af01c3906f167b39 GIT binary patch literal 69988 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 literal 0 HcmV?d00001 diff --git a/doc/images/sla_history_state.png b/doc/images/sla_history_state.png new file mode 100644 index 0000000000000000000000000000000000000000..460dcb5518efaeb401afb0861b7eb8c4d17deecf GIT binary patch literal 43039 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 literal 0 HcmV?d00001