Files
sql-scripts/TPDT-268 - ACP in task sequence/dba_packages/DeployJobsStatusMonitoring.sql
2024-03-07 16:52:14 +01:00

930 lines
30 KiB
Transact-SQL

/*=============================================================================
Création d'un package pour la gestion du monitoring des status des Jobs SQL
-> Création des tables
-> Création des FK et index
-> Deploy de la SP d'initialisation du status des jobs : mon.Initialize_Jobs_Status
-> Deploy de la SP de mise à jour du status des jobs : mon.Maj_Jobs_Status
-> Deploy de la fonction du calcul de prochain schedule : GetNextScheduleForJob
Création : 13.07.2023 / FLA
Modifications :
17.08.2023 / FLA : Changement de methode d'update, changement du calcul du prochain schedule, add SP to check status
21.09.2023 / FLA : Improve performance for function GetNextScheduleForJob and for SP Maj_Jobs_Status
=============================================================================*/
/***********************************************************************/
/* STRUCTURE */
/* */
/***********************************************************************/
USE HCITools;
IF NOT EXISTS ( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[mon].[Job_monitoring_config]')
AND type IN ( N'U' ))
BEGIN
CREATE TABLE [mon].[Job_monitoring_config](
[Job_monitoring_config_ID] [INT] IDENTITY(1,1) NOT NULL,
[JMC_name] [VARCHAR](255) NOT NULL,
[JMC_need_history] [BIT] NOT NULL,
[JMC_caller] [VARCHAR](255) NULL,
[JMC_ignore] [BIT] NOT NULL,
CONSTRAINT [PK_Job_monitoring_config] PRIMARY KEY CLUSTERED
(
[Job_monitoring_config_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMC_need_history]') AND type = 'D')
BEGIN
ALTER TABLE [mon].[Job_monitoring_config] ADD CONSTRAINT DF_JMC_need_history DEFAULT (1) FOR [JMC_need_history]
END
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMC_ignore]') AND type = 'D')
BEGIN
ALTER TABLE [mon].[Job_monitoring_config] ADD CONSTRAINT DF_JMC_ignore DEFAULT (0) FOR [JMC_ignore]
END
GO
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_config', 'Column', 'JMC_need_history'))
BEGIN
EXEC sp_addextendedproperty 'MS_Description', '0: same row updated in table Job_monitoring_history, 1:one row for each execution of job', 'Schema', [mon], 'table', [Job_monitoring_config], 'column', [JMC_need_history]
END
GO
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_config', 'Column', 'JMC_caller'))
BEGIN
EXEC sp_addextendedproperty 'MS_Description', 'Name of job If job called by another one', 'Schema', [mon], 'table', [Job_monitoring_config], 'column', [JMC_caller]
END
GO
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_config', 'Column', 'JMC_ignore'))
BEGIN
EXEC sp_addextendedproperty 'MS_Description', '0: To monitor, 1:To don''t monitor', 'Schema', [mon], 'table', [Job_monitoring_config], 'column', [JMC_ignore]
END
GO
IF NOT EXISTS ( SELECT 1
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TABLE_NAME = N'Job_monitoring_config')
BEGIN
ALTER TABLE [mon].[Job_monitoring_config]
ADD CONSTRAINT [PK_Job_monitoring_config]
PRIMARY KEY CLUSTERED ([Job_monitoring_config_ID] ASC);
END;
IF NOT EXISTS ( SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'[mon].[Job_monitoring_config]')
AND name = N'NCIX_Job_monitoring_config_COL_JMC_name')
BEGIN
CREATE NONCLUSTERED INDEX [NCIX_Job_monitoring_config_COL_JMC_name]
ON [mon].[Job_monitoring_config] ([JMC_name] ASC)
INCLUDE (JMC_need_history, JMC_caller, JMC_ignore);
END;
IF NOT EXISTS ( SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'[mon].[Job_monitoring_history]')
AND type IN ( N'U' ))
BEGIN
CREATE TABLE [mon].[Job_monitoring_history](
[Job_monitoring_history_ID] [INT] IDENTITY(1,1) NOT NULL,
[JMH_job_monitoring_config_ID] [INT] NOT NULL,
[JMH_next_schedule] [DATETIME] NULL,
[JMH_monitoring_status] [TINYINT] NOT NULL,
[JMH_job_status] [TINYINT] NULL,
[JMH_error_message] [NVARCHAR](4000) NULL,
[JMH_update_status] [DATETIME] NOT NULL,
[JMH_monitoring_date] [DATETIME] NULL,
CONSTRAINT [PK_Job_monitoring_history] PRIMARY KEY CLUSTERED
(
[Job_monitoring_history_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMH_monitoring_status]') AND type = 'D')
BEGIN
ALTER TABLE [mon].[Job_monitoring_history] ADD CONSTRAINT DF_JMH_monitoring_status DEFAULT ((0)) FOR [JMH_monitoring_status]
END
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[DF_JMH_update_status]') AND type = 'D')
BEGIN
ALTER TABLE [mon].[Job_monitoring_history] ADD CONSTRAINT DF_JMH_update_status DEFAULT (GETDATE()) FOR [JMH_update_status]
END
GO
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_history', 'Column', 'JMH_monitoring_status'))
BEGIN
EXEC sp_addextendedproperty 'MS_Description', '0: No error, 1:Error not checked, 2:Error checked', 'Schema', [mon], 'table', [Job_monitoring_history], 'column', [JMH_monitoring_status]
END
GO
IF NOT EXISTS (SELECT * FROM ::fn_listextendedproperty ('MS_Description', 'Schema', 'mon', 'Table', 'Job_monitoring_history', 'Column', 'JMH_job_status'))
BEGIN
EXEC sp_addextendedproperty 'MS_Description', '0 = Failed
1 = Succeeded
2 = No execution', 'Schema', [mon], 'table', [Job_monitoring_history], 'column', [JMH_job_status]
END
GO
IF NOT EXISTS ( SELECT 1
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
AND TABLE_NAME = N'Job_monitoring_history')
BEGIN
ALTER TABLE [mon].[Job_monitoring_history]
ADD CONSTRAINT [PK_Job_monitoring_history]
PRIMARY KEY CLUSTERED ([Job_monitoring_history_ID] ASC);
END;
IF NOT EXISTS ( SELECT 1
FROM sys.foreign_keys
WHERE object_id = OBJECT_ID(N'mon.FK_Job_monitoring_config_COL_Job_monitoring_config_ID')
AND parent_object_id = OBJECT_ID(N'[mon].[Job_monitoring_history]'))
BEGIN
ALTER TABLE [mon].[Job_monitoring_history]
ADD CONSTRAINT [FK_Job_monitoring_config_COL_Job_monitoring_config_ID]
FOREIGN KEY ([JMH_Job_monitoring_config_ID])
REFERENCES [mon].[Job_monitoring_config] ([Job_monitoring_config_ID]) ON DELETE NO ACTION ON UPDATE NO ACTION;
END;
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[Initialize_Jobs_Status]') AND type IN (N'P', N'PC'))
DROP PROCEDURE [mon].[Initialize_Jobs_Status]
GO
CREATE PROCEDURE [mon].[Initialize_Jobs_Status]
@in_debug TINYINT = 0,
@in_JobName NVARCHAR(1000) = NULL
AS
/*=============================================================================
Explication du traitement realise par la SP
-------------------------------------------
Cette SP sert a initialiser le status des jobs
Contexte d'utilisation
----------------------
Appelée à la main en passant le nom du job à initialiser si besoin sinon all jobs
Parametres
----------
@in_debug : non utilisé
@in_JobName : nom du job (si null All jobs)
Creation : 13.07.23 / FLA
Modifications :
=============================================================================*/
SET NOCOUNT ON;
/*------------------- Declaration des variables --------------------*/
DECLARE @JobName VARCHAR(255),
@LastStatus TINYINT,
@LastMessage NVARCHAR(4000),
@NextRun DATETIME,
@ID INT;
/*------------ Affectation des parametres aux variables ------------*/
/*-------------------------- Traitement ---------------------------*/
BEGIN TRY
DECLARE c_Jobs CURSOR FAST_FORWARD READ_ONLY FOR
SELECT SJ.name,
SJH.LastStatus,
SJH.Lastmessage,
SJA.NextRun
FROM msdb.dbo.sysjobs SJ
OUTER APPLY ( SELECT TOP 1 NextRun = JA.next_scheduled_run_date
FROM msdb.dbo.sysjobactivity JA
WHERE JA.job_id = SJ.job_id
ORDER BY session_id DESC) AS SJA
OUTER APPLY ( SELECT TOP 1 LastStatus = MIN(run_status),
Lastmessage = CASE
WHEN JH.sql_severity > 0 THEN message
ELSE NULL END
FROM msdb.dbo.sysjobhistory JH
WHERE JH.job_id = SJ.job_id
AND JH.run_date = ( SELECT MAX(T.run_date)
FROM msdb.dbo.sysjobhistory T
WHERE T.job_id = JH.job_id)
AND JH.run_time >= ( SELECT MAX(T.run_time)
FROM msdb.dbo.sysjobhistory T
WHERE T.job_id = JH.job_id
AND JH.run_date = T.run_date
AND T.step_id = 0)
GROUP BY CASE
WHEN JH.sql_severity > 0 THEN message
ELSE NULL END
ORDER BY MIN(run_status)) AS SJH
WHERE SJ.enabled = 1
AND (( SJ.name LIKE 'DR[0-9]%'
OR SJ.name LIKE 'D[0-9]%'
OR SJ.name LIKE 'M[0-9]%'
OR SJ.name LIKE 'W[0-9]%'
OR SJ.name LIKE '[_]%') AND @in_JobName IS NULL)
AND SJ.name NOT LIKE '%Log reader%'
OR (SJ.name = @in_JobName AND @in_JobName IS NOT NULL)
ORDER BY SJ.name;
OPEN c_Jobs;
FETCH NEXT FROM c_Jobs
INTO @JobName,
@LastStatus,
@LastMessage,
@NextRun;
WHILE @@FETCH_STATUS = 0
BEGIN
IF NOT EXISTS ( SELECT 1
FROM mon.Job_monitoring_config
WHERE JMC_name = @JobName)
BEGIN
INSERT INTO mon.Job_monitoring_config (JMC_name,
JMC_need_history)
VALUES (@JobName, CASE
WHEN @JobName LIKE '[_][0-9]%' THEN 0
WHEN @JobName LIKE 'DR[0-9]%' THEN 0
ELSE 1 END);
SELECT @ID = SCOPE_IDENTITY();
INSERT INTO mon.Job_monitoring_history (JMH_job_monitoring_config_ID,
JMH_next_schedule,
JMH_monitoring_status,
JMH_job_status,
JMH_error_message)
VALUES (@ID, @NextRun, CASE WHEN ISNULL(@LastStatus,1) = 1 THEN 0 ELSE 1 END, @LastStatus, @LastMessage);
END;
FETCH NEXT FROM c_Jobs
INTO @JobName,
@LastStatus,
@LastMessage,
@NextRun;
UPDATE JMC
SET JMC.JMC_Caller = SJ.name
FROM msdb.dbo.sysjobs SJ
INNER JOIN msdb.dbo.sysjobsteps SJS
ON SJ.job_id = SJS.job_id
INNER JOIN mon.Job_monitoring_config JMC
ON JMC.JMC_name = REPLACE(REPLACE(SUBSTRING(SJS.step_name, 11, 80), '[', ''), ']', '')
WHERE SJS.command LIKE '%aps_Launch_Job_SQL_Agent%'
OR SJS.command LIKE '%aps_CheckProd_Job%';
END;
CLOSE c_Jobs;
DEALLOCATE c_Jobs;
END TRY
BEGIN CATCH
/* Traitement des erreurs (sans RaiseError) */
EXEC dbo.get_Error_Info @in_RaiseError = 0;
END CATCH;
/*------------------ Retour au programme appelant -----------------*/
RETURN (@@error);
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GetNextScheduleForJob]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[GetNextScheduleForJob]
GO
CREATE FUNCTION [dbo].[GetNextScheduleForJob]
(
@JobName SYSNAME,
@startDate DATETIME,
@endDate DATETIME
)
RETURNS @t TABLE (
scheduleID INT NOT NULL,
jobName SYSNAME NOT NULL,
jobDescription NVARCHAR(512) NOT NULL,
scheduleName SYSNAME NOT NULL,
categoryName SYSNAME NOT NULL,
startDate DATETIME NOT NULL,
jobEnabled INT NOT NULL,
scheduleEnabled INT NOT NULL)
AS
BEGIN
-- Create a tally table. If you already have one of your own please use that instead.
DECLARE @tallyNumbers TABLE
(
num SMALLINT PRIMARY KEY CLUSTERED
)
DECLARE @index SMALLINT
SET @index = 1
WHILE @index <= 8640
BEGIN
INSERT @tallyNumbers
(
num
)
VALUES (
@index
)
SET @index = @index + 1
END
-- Create a staging table for jobschedules
DECLARE @jobSchedules TABLE
(
rowID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
jobName SYSNAME NOT NULL,
jobDescription NVARCHAR(512) NOT NULL,
scheduleName SYSNAME NOT NULL,
scheduleID INT NOT NULL,
categoryName SYSNAME NOT NULL,
freq_type INT NOT NULL,
freq_interval INT NOT NULL,
freq_subday_type INT NOT NULL,
freq_subday_interval INT NOT NULL,
freq_relative_interval INT NOT NULL,
freq_recurrence_factor INT NOT NULL,
startDate DATETIME NOT NULL,
startTime DATETIME NOT NULL,
endDate DATETIME NOT NULL,
endTime DATETIME NOT NULL,
jobEnabled INT NOT NULL,
scheduleEnabled INT NOT NULL
)
-- Populate the staging table for JobSchedules with SQL Server 2005 and SQL Server 2008
INSERT @JobSchedules
(
jobName,
jobDescription,
scheduleName,
scheduleID,
categoryName,
freq_type,
freq_interval,
freq_subday_type,
freq_subday_interval,
freq_relative_interval,
freq_recurrence_factor,
startDate,
startTime,
endDate,
endTime,
jobEnabled,
scheduleEnabled
)
SELECT sj.name,
COALESCE(sj.description, ''),
ss.name,
ss.schedule_id,
sc.name,
ss.freq_type,
ss.freq_interval,
ss.freq_subday_type,
ss.freq_subday_interval,
ss.freq_relative_interval,
ss.freq_recurrence_factor,
COALESCE(STR(ss.active_start_date, 8), CONVERT(CHAR(8), GETDATE(), 112)) startDate,
STUFF(STUFF(REPLACE(STR(ss.active_start_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':') startTime,
STR(ss.active_end_date, 8) endDate,
STUFF(STUFF(REPLACE(STR(ss.active_end_time, 6), ' ', '0'), 3, 0, ':'), 6, 0, ':') endTime,
sj.enabled,
ss.enabled
FROM msdb..sysschedules AS ss WITH (NOLOCK)
INNER JOIN msdb..sysjobschedules AS sjs WITH (NOLOCK) ON sjs.schedule_id = ss.schedule_id
INNER JOIN msdb..sysjobs AS sj WITH (NOLOCK) ON sj.job_id = sjs.job_id
INNER JOIN msdb..syscategories AS sc WITH (NOLOCK) ON sc.category_id = sj.category_id
WHERE ss.freq_type IN (1, 4, 8, 16, 32)
AND sj.name = @JobName
-- Deal with first, second, third, fourth and last occurence
DECLARE @tempStart DATETIME,
@tempEnd DATETIME
SELECT @tempStart = DATEADD(MONTH, DATEDIFF(MONTH, '19000101', @startDate), '19000101'),
@TempEnd = DATEADD(MONTH, DATEDIFF(MONTH, '18991231', @endDate), '18991231')
DECLARE @dayInformation TABLE
(
infoDate DATETIME PRIMARY KEY CLUSTERED,
weekdayName VARCHAR(9) NOT NULL,
statusCode INT NOT NULL,
lastDay TINYINT DEFAULT 0
)
WHILE @tempStart <= @tempEnd
BEGIN
INSERT @dayInformation
(
infoDate,
weekdayName,
statusCode
)
SELECT @tempStart,
DATENAME(WEEKDAY, @tempStart),
CASE
WHEN DATEPART(DAY, @tempStart) BETWEEN 1 AND 7 THEN 1
WHEN DATEPART(DAY, @tempStart) BETWEEN 8 AND 14 THEN 2
WHEN DATEPART(DAY, @tempStart) BETWEEN 15 AND 21 THEN 4
WHEN DATEPART(DAY, @tempStart) BETWEEN 22 AND 28 THEN 8
ELSE 0
END
SET @tempStart = DATEADD(DAY, 1, @tempStart)
END
UPDATE di
SET di.statusCode = di.statusCode + 16
FROM @dayInformation AS di
INNER JOIN (
SELECT DATEDIFF(MONTH, '19000101', infoDate) AS theMonth,
DATEPART(DAY, MAX(infoDate)) - 6 AS theDay
FROM @dayInformation
GROUP BY DATEDIFF(MONTH, '19000101', infoDate)
) AS x ON x.theMonth = DATEDIFF(MONTH, '19000101', di.infoDate)
WHERE DATEPART(DAY, di.infoDate) >= x.theDay
UPDATE di
SET di.lastDay = 16
FROM @dayInformation AS di
INNER JOIN (
SELECT DATEDIFF(MONTH, '19000101', infoDate) AS theMonth,
MAX(infoDate) AS theDay
FROM @dayInformation
GROUP BY DATEDIFF(MONTH, '19000101', infoDate)
) AS x ON x.theMonth = DATEDIFF(MONTH, '19000101', di.infoDate)
WHERE di.infoDate = x.theDay
UPDATE @dayInformation
SET lastDay = DATEPART(DAY, infoDate)
WHERE DATEPART(DAY, infoDate) BETWEEN 1 AND 4
-- Stage all individual schedule times
DECLARE @scheduleTimes TABLE
(
rowID INT NOT NULL,
startDate DATETIME NOT NULL,
endDate DATETIME NOT NULL,
waitSeconds INT DEFAULT 0
)
-- Insert one time only schedules
INSERT @scheduleTimes
(
rowID,
startDate,
endDate
)
SELECT rowID,
startDate+startTime,
startDate+startTime
FROM @jobSchedules
WHERE freq_type = 1
AND startDate+startTime BETWEEN @StartDate AND @EndDate
-- Insert daily schedules
INSERT @scheduleTimes
(
rowID,
startDate,
endDate,
waitSeconds
)
SELECT js.rowID,
di.infoDate+js.startTime,
di.infoDate+js.endTime,
CASE js.freq_subday_type
WHEN 1 THEN 0
WHEN 2 THEN js.freq_subday_interval
WHEN 4 THEN 60 * js.freq_subday_interval
WHEN 8 THEN 3600 * js.freq_subday_interval
END
FROM @jobSchedules AS js
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
AND di.infoDate <= js.endDate
WHERE js.freq_type = 4
AND DATEDIFF(DAY, js.startDate, di.infoDate) % js.freq_interval = 0
-- Insert weekly schedules
INSERT @scheduleTimes
(
rowID,
startDate,
endDate,
waitSeconds
)
SELECT js.rowID,
di.infoDate+js.startTime,
di.infoDate+js.endTime,
CASE js.freq_subday_type
WHEN 1 THEN 0
WHEN 2 THEN js.freq_subday_interval
WHEN 4 THEN 60 * js.freq_subday_interval
WHEN 8 THEN 3600 * js.freq_subday_interval
END
FROM @jobSchedules AS js
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
AND di.infoDate <= js.endDate
WHERE js.freq_type = 8
AND 1 = CASE
WHEN js.freq_interval & 1 = 1 AND di.weekdayName = 'Sunday' THEN 1
WHEN js.freq_interval & 2 = 2 AND di.weekdayName = 'Monday' THEN 1
WHEN js.freq_interval & 4 = 4 AND di.weekdayName = 'Tuesday' THEN 1
WHEN js.freq_interval & 8 = 8 AND di.weekdayName = 'Wednesday' THEN 1
WHEN js.freq_interval & 16 = 16 AND di.weekdayName = 'Thursday' THEN 1
WHEN js.freq_interval & 32 = 32 AND di.weekdayName = 'Friday' THEN 1
WHEN js.freq_interval & 64 = 64 AND di.weekdayName = 'Saturday' THEN 1
ELSE 0
END
AND (DATEDIFF(DAY, js.startDate, di.infoDate) / 7) % js.freq_recurrence_factor = 0
-- Insert monthly schedules
INSERT @scheduleTimes
(
rowID,
startDate,
endDate,
waitSeconds
)
SELECT js.rowID,
di.infoDate+js.startTime,
di.infoDate+js.endTime,
CASE js.freq_subday_type
WHEN 1 THEN 0
WHEN 2 THEN js.freq_subday_interval
WHEN 4 THEN 60 * js.freq_subday_interval
WHEN 8 THEN 3600 * js.freq_subday_interval
END
FROM @jobSchedules AS js
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
AND di.infoDate <= js.endDate
WHERE js.freq_type = 16
AND DATEPART(DAY, di.infoDate) = js.freq_interval
AND DATEDIFF(MONTH, js.startDate, di.infoDate) % js.freq_recurrence_factor = 0
-- Insert monthly relative schedules
INSERT @scheduleTimes
(
rowID,
startDate,
endDate,
waitSeconds
)
SELECT js.rowID,
di.infoDate+js.startTime,
di.infoDate+js.endTime,
CASE js.freq_subday_type
WHEN 1 THEN 0
WHEN 2 THEN js.freq_subday_interval
WHEN 4 THEN 60 * js.freq_subday_interval
WHEN 8 THEN 3600 * js.freq_subday_interval
END
FROM @jobSchedules AS js
INNER JOIN @dayInformation AS di ON di.infoDate >= js.startDate
AND di.infoDate <= js.endDate
WHERE js.freq_type = 32
AND 1 = CASE
WHEN js.freq_interval = 1 AND di.weekdayName = 'Sunday' THEN 1
WHEN js.freq_interval = 2 AND di.weekdayName = 'Monday' THEN 1
WHEN js.freq_interval = 3 AND di.weekdayName = 'Tuesday' THEN 1
WHEN js.freq_interval = 4 AND di.weekdayName = 'Wednesday' THEN 1
WHEN js.freq_interval = 5 AND di.weekdayName = 'Thursday' THEN 1
WHEN js.freq_interval = 6 AND di.weekdayName = 'Friday' THEN 1
WHEN js.freq_interval = 7 AND di.weekdayName = 'Saturday' THEN 1
WHEN js.freq_interval = 8 AND js.freq_relative_interval = di.lastDay THEN 1
WHEN js.freq_interval = 9 AND di.weekdayName NOT IN ('Sunday', 'Saturday') THEN 1
WHEN js.freq_interval = 10 AND di.weekdayName IN ('Sunday', 'Saturday') THEN 1
ELSE 0
END
AND di.statusCode & js.freq_relative_interval = js.freq_relative_interval
AND DATEDIFF(MONTH, js.startDate, di.infoDate) % js.freq_recurrence_factor = 0
-- Get the daily recurring schedule times
INSERT @scheduleTimes
(
rowID,
startDate,
endDate,
waitSeconds
)
SELECT st.rowID,
DATEADD(SECOND, tn.num * st.waitSeconds, st.startDate),
st.endDate,
st.waitSeconds
FROM @scheduleTimes AS st
CROSS JOIN @tallyNumbers AS tn
WHERE tn.num * st.waitSeconds <= DATEDIFF(SECOND, st.startDate, st.endDate)
AND st.waitSeconds > 0
-- Present the result
INSERT @t (scheduleID,
jobName,
jobDescription,
scheduleName,
categoryName,
startDate,
jobEnabled,
scheduleEnabled)
SELECT js.scheduleID,
js.jobName,
js.jobDescription,
js.scheduleName,
js.categoryName,
st.startDate,
js.jobEnabled,
js.scheduleEnabled
FROM @scheduleTimes AS st
INNER JOIN @jobSchedules AS js ON js.rowID = st.rowID
WHERE js.jobEnabled = 1
AND js.scheduleEnabled = 1
AND st.startDate >= @startDate
AND st.startDate <= @endDate
RETURN
END
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[Maj_Jobs_Status]') AND type IN (N'P', N'PC'))
DROP PROCEDURE [mon].[Maj_Jobs_Status]
GO
CREATE PROCEDURE [mon].[Maj_Jobs_Status]
@in_debug TINYINT = 0,
@in_JobName NVARCHAR(1000) = NULL,
@in_JobID UNIQUEIDENTIFIER = NULL
AS
/*=============================================================================
Explication du traitement realise par la SP
-------------------------------------------
Cette SP sert a mettre à jour le status des jobs
Contexte d'utilisation
----------------------
Appelée depuis le step Empty Step et Send mail KO des jobs
Parametres
----------
@in_debug : non utilisé
@in_JobName : nom du job (si null All jobs)
Creation : 03.08.23 / FLA
Modifications :
22.08.23 : Get directly the job_id in job instead of put job name in parameter
21.09.23 : Call the new version of function [GetNextScheduleForJob]
=============================================================================*/
SET NOCOUNT ON;
/*------------------- Declaration des variables --------------------*/
DECLARE @LastMessage NVARCHAR(4000) = NULL,
@JMC_ID INT = 0,
@JMH_ID INT = NULL,
@NeedHistory BIT = 1,
@NextRun DATETIME
/*------------ Affectation des parametres aux variables ------------*/
/*-------------------------- Traitement ---------------------------*/
BEGIN TRY
IF @in_JobID IS NOT NULL
SELECT @in_JobName = name FROM msdb.dbo.sysjobs WHERE job_id = @in_JobID
SELECT @LastMessage = jh.message
FROM msdb.dbo.sysjobhistory jh
INNER JOIN msdb.dbo.sysjobactivity ja
ON ja.job_id = jh.job_id
INNER JOIN msdb.dbo.sysjobs j
ON j.job_id = ja.job_id
WHERE j.name = @in_JobName
AND run_status = 0 --and ja.stop_execution_date is null--
AND ja.session_id = (SELECT TOP 1 session_id
FROM msdb.dbo.syssessions
ORDER BY agent_start_date DESC)
AND start_execution_date IS NOT NULL
--AND stop_execution_date is null
AND msdb.dbo.agent_datetime(run_date, run_time) >= start_execution_date;
/* Gestion des Query Timeout Error */
IF EXISTS (SELECT 1
FROM msdb..sysjobhistory jh
INNER JOIN msdb..sysjobactivity ja
ON ja.job_id = jh.job_id
INNER JOIN msdb..sysjobs j
ON j.job_id = ja.job_id
WHERE j.name = @in_JobName
AND run_status = 1 --and ja.stop_execution_date is null--
AND ja.session_id = (SELECT TOP 1 session_id
FROM msdb.dbo.syssessions
ORDER BY agent_start_date DESC)
AND start_execution_date IS NOT NULL
AND jh.sql_message_id = 7412
AND msdb.dbo.agent_datetime(run_date, run_time) >= start_execution_date)
BEGIN
SELECT @LastMessage = jh.message
FROM msdb..sysjobhistory jh
INNER JOIN msdb..sysjobactivity ja
ON ja.job_id = jh.job_id
INNER JOIN msdb..sysjobs j
ON j.job_id = ja.job_id
WHERE j.name = @in_JobName
AND run_status = 1 --and ja.stop_execution_date is null--
AND ja.session_id = (SELECT TOP 1 session_id
FROM msdb.dbo.syssessions
ORDER BY agent_start_date DESC)
AND start_execution_date IS NOT NULL
AND jh.sql_message_id = 7412
AND msdb.dbo.agent_datetime(run_date, run_time) >= start_execution_date;
END;
SELECT @JMC_ID = JMC.Job_monitoring_config_ID,
@NeedHistory = JMC.JMC_need_history,
@JMH_ID = JMH.Job_monitoring_history_ID
FROM [mon].[Job_monitoring_config] JMC
LEFT OUTER JOIN [mon].[Job_monitoring_history] JMH
ON JMC.Job_monitoring_config_ID = JMH.JMH_job_monitoring_config_ID
WHERE JMC_name = @in_JobName
AND JMC_ignore = 0
IF @JMC_ID <> 0
BEGIN
SELECT @NextRun = Job.startDate FROM
(SELECT TOP 1 startDate
FROM [dbo].[GetNextScheduleForJob](@in_JobName,GETDATE(), GETDATE() + 1)
ORDER BY startDate) AS Job
IF @NeedHistory = 0
BEGIN
UPDATE [mon].[Job_monitoring_history] SET [JMH_next_schedule] = @NextRun,
[JMH_monitoring_status] = CASE WHEN @LastMessage IS NOT NULL THEN 1 ELSE 0 END,
[JMH_job_status] = CASE WHEN @LastMessage IS NOT NULL THEN 0 ELSE 1 END,
[JMH_error_message] = @LastMessage,
[JMH_update_status] = GETDATE()
WHERE JMH_job_monitoring_config_ID = @JMH_ID
END
ELSE
BEGIN
INSERT INTO [mon].[Job_monitoring_history] ([JMH_job_monitoring_config_ID],
[JMH_next_schedule],
[JMH_monitoring_status],
[JMH_job_status],
[JMH_error_message],
[JMH_update_status])
VALUES (@JMC_ID,
@NextRun,
CASE WHEN @LastMessage IS NOT NULL THEN 1 ELSE 0 END,
CASE WHEN @LastMessage IS NOT NULL THEN 0 ELSE 1 END,
@LastMessage,
DEFAULT
)
END
END
END TRY
BEGIN CATCH
/* Traitement des erreurs (sans RaiseError) */
EXEC dbo.get_Error_Info @in_RaiseError = 0;
END CATCH;
/*------------------ Retour au programme appelant -----------------*/
RETURN (@@error);
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[mon].[Get_Jobs_Status]') AND type in (N'P', N'PC'))
DROP PROCEDURE [mon].[Get_Jobs_Status]
GO
CREATE PROCEDURE [mon].[Get_Jobs_Status]
@in_debug TINYINT = 0,
@in_JobName NVARCHAR(1000) = NULL
AS
/*=============================================================================
Explication du traitement realise par la SP
-------------------------------------------
Cette SP sert à retourner le status des jobs
Contexte d'utilisation
----------------------
Appelée depuis le MDV ou à la main
Parametres
----------
@in_debug : non utilisé
@in_JobName : nom du job (si null All jobs)
Creation : 17.08.23 / FLA
Modifications :
=============================================================================*/
SET NOCOUNT ON;
/*------------------- Declaration des variables --------------------*/
/*------------ Affectation des parametres aux variables ------------*/
/*-------------------------- Traitement ---------------------------*/
BEGIN TRY
SELECT JMC.JMC_name AS JobName,
JMH.JMH_error_message AS Error,
CASE
WHEN ( JMH.JMH_job_status = 0
AND JMH_monitoring_status = 1) THEN 'ERROR'
WHEN (CASE WHEN ISNULL(JMH.JMH_next_schedule,T1.JMH_next_schedule) < ISNULL(T1.JMH_next_schedule,JMH.JMH_next_schedule) THEN ISNULL(JMH.JMH_next_schedule,T1.JMH_next_schedule) ELSE ISNULL(T1.JMH_next_schedule,JMH.JMH_next_schedule) END < GETDATE()) THEN 'NOT EXECUTED'
ELSE '' END AS Status
FROM mon.Job_monitoring_config JMC
INNER JOIN mon.Job_monitoring_history JMH
ON JMC.Job_monitoring_config_ID = JMH.JMH_job_monitoring_config_ID
AND JMC.JMC_ignore = 0
AND JMH.JMH_update_status = (SELECT MAX(JMH2.JMH_update_status)
FROM mon.Job_monitoring_history JMH2
WHERE JMH2.JMH_job_monitoring_config_ID = JMC.Job_monitoring_config_ID)
OUTER APPLY (SELECT JMH3.JMH_next_schedule FROM mon.Job_monitoring_config JMC3
INNER JOIN mon.Job_monitoring_history JMH3
ON JMC3.Job_monitoring_config_ID = JMH3.JMH_job_monitoring_config_ID
AND JMH3.JMH_update_status = (SELECT MAX(JMH4.JMH_update_status)
FROM mon.Job_monitoring_history JMH4
WHERE JMH4.JMH_job_monitoring_config_ID = JMC3.Job_monitoring_config_ID)
WHERE JMC3.JMC_name = JMC.JMC_caller) AS T1
WHERE JMC.JMC_name = COALESCE(@in_JobName, JMC.JMC_name)
ORDER BY JMC.JMC_name
END TRY
BEGIN CATCH
/* Traitement des erreurs (sans RaiseError) */
EXEC dbo.get_Error_Info @in_RaiseError = 0;
END CATCH;
/*------------------ Retour au programme appelant -----------------*/
RETURN (@@error);
GO
/***********************************************************************/
/* INITIALISATION */
/* */
/***********************************************************************/
EXEC [mon].[Initialize_Jobs_Status]
SELECT *
FROM mon.Job_monitoring_config JMC
INNER JOIN mon.Job_monitoring_history JMH
ON JMC.Job_monitoring_config_ID = JMH.JMH_Job_monitoring_config_ID
ORDER BY JMC.JMC_name
EXEC [mon].[Get_Jobs_Status]