/*
OCTPDBA-373

Proposition of structure for alerts in dbaTools, for reporting via Scom

27.10.2022, TSC
*/
USE sandbox

IF OBJECT_ID('dbo.alert_type') IS NOT NULL BEGIN;
    IF OBJECT_ID('fk_alert_log__ref__alert_type') IS NOT NULL BEGIN 
        ALTER TABLE dbo.alert_log DROP CONSTRAINT fk_alert_log__ref__alert_type;
	END 
    IF OBJECT_ID('fk_alert_overview__ref__alert_type') IS NOT NULL BEGIN 
        ALTER TABLE dbo.alert_overview DROP CONSTRAINT fk_alert_overview__ref__alert_type;
	END 
    DROP TABLE dbo.alert_type;
END;

/*
Define the types of alerts we handle.
Each alert type is identified by an unique code
We can define a window of time in between alerts will not be recorded, or have a master switch to enable / disable the alert
If an alert is enabled (alert_enabled = 1) but we are in a disabled time window (current_timestamp between alert_disabled_from and alert_disabled_to) then we do not record any new alerts
the field keep_for_days define how long we keep a record of this alert in the log, once an alert is older that this value, it will be cleaned up.
The severity of the alert is at the alert level and not tied to the definition of the alert itself.
*/
CREATE TABLE dbo.alert_type (
    alert_type_id INT NOT NULL IDENTITY
   ,alert_type VARCHAR(50) NOT NULL				--a code to identify the alert
   ,alert_enabled BIT NOT NULL					--global switch to disable / enable the alert outside a time window
        CONSTRAINT def_alert_enabled
            DEFAULT 1
   ,alert_disabled_from SMALLDATETIME NULL		--if a window is planned for deativating the alert, beginning of the window
   ,alert_disabled_to SMALLDATETIME NULL		--if a window is planned for deativating the alert, end of the window
   ,keep_for_days INT NOT NULL					--how long does the alert should stay in the log. After that age passes, alerts in the log will be deleted.
        DEFAULT 365							
  ,comp_alert_is_enabled AS CONVERT(BIT			--computed column to get the current state of the alert (enabled or disabled)
                                    ,alert_enabled * CASE
                                                         WHEN CURRENT_TIMESTAMP BETWEEN alert_disabled_from
                                                                                AND     alert_disabled_to THEN 0
                                                         ELSE 1
                                                     END
                             )

   ,CONSTRAINT pk_alert_type
        PRIMARY KEY (alert_type_id)
);

CREATE UNIQUE NONCLUSTERED INDEX NCUIX_alert_type__alert_type
ON dbo.alert_type (alert_type);

IF OBJECT_ID('dbo.alert_log') IS NOT NULL BEGIN;
    DROP TABLE dbo.alert_log;
END;

/*
This table will holds every alerts that have been recorded.
*/
CREATE TABLE dbo.alert_log (
    alert_log_id INT NOT NULL IDENTITY
   ,alert_type VARCHAR(50) NOT NULL				--point to alert_type, FK
   ,alert_creation_date SMALLDATETIME NOT NULL	--when was this alert created
        CONSTRAINT def_alert_creation_date
            DEFAULT CURRENT_TIMESTAMP
   ,alert_treated_date SMALLDATETIME NULL		--when was the alert treated, if it was
   ,alert_source VARCHAR(1000) NULL				--what is the source of the alert (job name, script, parsing system logs, audits, extended events ?)
   ,alert_resolution_comment VARCHAR(MAX) NULL	--to leave a comment on the resolution, if needed
   ,alert_severity INT NULL						-- 0 = info / 1 = warning / 2 = error
   ,CONSTRAINT pk_alert_log
        PRIMARY KEY (alert_log_id)
);

IF OBJECT_ID('fk_alert_log__ref__alert_type') IS NULL
    ALTER TABLE dbo.alert_log
    ADD CONSTRAINT fk_alert_log__ref__alert_type
        FOREIGN KEY (alert_type)
        REFERENCES dbo.alert_type (alert_type)
	;

IF OBJECT_ID('dbo.alert_overview')IS NOT NULL BEGIN;
	DROP TABLE dbo.alert_overview;
END;

/*
This overview table is recreated by a job every night.
It only contains 1 row per alert type, if the alert is enabled in alert_type.
A timestamp of the rebuild of this table is present, to ensure that the job did rebuild it daily.
The highest severity of all the alerts of that type is recorded, as well as the oldest non treated alert
A computed column gives the age of the oldest alert of that type in days
*/
CREATE TABLE dbo.alert_overview(
	alert_type VARCHAR(50) NOT NULL													--1 entry per alert type, this is an overview
	,overview_creation_date SMALLDATETIME NOT NULL									--when was this overview created
	,alert_oldest SMALLDATETIME NOT NULL											--The oldest alert entry not treated for this alert type
	,alert_severity INT NOT NULL													--the highest level of alert severity not treated for this alert type
	,comp_days_since_alert_exists AS DATEDIFF(DAY, alert_oldest, CURRENT_TIMESTAMP)	--Oldest not treated alert of that type is X days old
	,CONSTRAINT pk_alert_overview PRIMARY KEY(alert_type)
);

IF OBJECT_ID('fk_alert_overview__ref__alert_type') IS NULL
	ALTER TABLE dbo.alert_overview 
	ADD CONSTRAINT fk_alert_overview__ref__alert_type
		FOREIGN KEY(alert_type)
		REFERENCES dbo.alert_type(alert_type)
	;
