Link to home
Start Free TrialLog in
Avatar of VIVEKANANDHAN_PERIASAMY
VIVEKANANDHAN_PERIASAMY

asked on

Need to restart the SQL job if it's running morethan 30 minutes

Hello,

I have a SQL job called "ALL - DelHistory" which occupationally gets hung or running morethan 30 minutes.In that case,it should stop the job,wait for 5 minutes and should start the job again.

I have created a another sql job to montior ALL-DelHistory job, but script below is not working.Please modify the script to achieve my goal.
USE [msdb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
 
 
 
ALTER PROCEDURE [dbo].[Monitoring_all_del_history_job] (
 
          @threshold_minute int = 30,       -- Default is set to 30 minutes
 
          @StopJob bit = 0,                  -- Default is not to stop the job 
 
          @ExcludeJOb XML =NULL -- '<ExcludeJob><JobName JOB="Export TMF PerfData"/></ExcludeJob>'
 
          )
 
 
 
AS
 
 
 
SET NOCOUNT ON
 
 
 
DECLARE @is_sysadmin     INT
 
DECLARE @job_owner       sysname
 
DECLARE @job_id         UNIQUEIDENTIFIER
 
DECLARE @JobName            VARCHAR(255)
 
DECLARE @JobStartTime    DateTime
 
DECLARE @Msg            VARCHAR(1000)
 
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
 
 
/** Insert the jobs to be excluded from job monitoring  */
 
INSERT @ExcludeJObTable (JobName)
 
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)
 
 
 
-- Step 1: Create intermediate work tables to store the running job data
 
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
 
                       last_run_date         INT              NOT NULL,
 
                       last_run_time         INT              NOT NULL,
 
                       next_run_date         INT              NOT NULL,
 
                       next_run_time         INT              NOT NULL,
 
                       next_run_schedule_id  INT              NOT NULL,
 
                       requested_to_run      INT              NOT NULL, -- BOOL
 
                       request_source        INT              NOT NULL,
 
                       request_source_id     sysname          NULL,
 
                       running               INT              NOT NULL, -- BOOL
 
                       current_step          INT              NOT NULL,
 
                       current_retry_attempt INT              NOT NULL,
 
                       job_state             INT              NOT NULL)
 
 
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
 
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
 
SELECT @job_owner = SUSER_SNAME() 
 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
 
BEGIN
 
    INSERT INTO #xp_results
 
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
 
END
 
ELSE
 
BEGIN
 
     INSERT INTO #xp_results
 
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
 
END
 
 
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
 
 
DECLARE joblist_cursor CURSOR FOR
 
SELECT j.name, a.job_id, a.start_execution_date
 
FROM #xp_results x
 
INNER JOIN msdb.dbo.sysjobactivity a
 
ON x.job_id = a.job_id
 
INNER join msdb.dbo.sysjobs j
 
ON a.job_id = j.job_id
 
     WHERE x.running = 1 
 
     AND j.name  ='ALL - DelHistory'                                          --Excluding the job Monitoring
 
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
 
     AND a.stop_execution_date is null                                 -- The job is not complete 
 
     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
 
 
OPEN joblist_cursor
 
 
 
FETCH NEXT FROM joblist_cursor
 
INTO @JobName, @job_id, @JobStartTime
 
 
 
WHILE @@FETCH_STATUS = 0
 
BEGIN
 
     -- Check again if the same job at the starting time is still active
 
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND start_execution_date = @JobStartTime)
 
    
 
 
 
     IF @StopJob = 1
 
     BEGIN
 
          PRINT 'Stopping job [' + @Jobname + ']'
 
          EXEC msdb..sp_stop_job @job_name=@JobName
 
          waitfor delay '00:05:00'
 
          PRINT 'Starting job [' + @Jobname + ']'
 
          EXEC msdb..sp_start_job @job_name=@JobName
 
     END
 
     FETCH NEXT FROM joblist_cursor
 
     INTO @JobName, @job_id, @JobStartTime
 
END
 
 
 
CLOSE joblist_cursor
 
DEALLOCATE joblist_cursor
 
DROP TABLE #xp_results

Open in new window

Avatar of David Todd
David Todd
Flag of New Zealand image

Hi,

Can you expand on what you mean when you say - Its Not Working?

That is, it does nothing, it kills said job, but doesn't restart it, ... what?

Regards
   David
Avatar of VIVEKANANDHAN_PERIASAMY
VIVEKANANDHAN_PERIASAMY

ASKER

No Sir,

Even if this job running for morethan 30 minutes, it's not stopping and restart the job.

I'm i missing anything in sp's.
Hi,
Please find my comment ID: 38069283 in https://www.experts-exchange.com/questions/27732791/Need-a-double-monitoring-for-SQL-job's.html?cid=1752

Here's the code:
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL, -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          @mail_profile VARCHAR(255)=NULL,
          @mail_recipients VARCHAR(512)='test@company.com'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)

Set @TableTail = '</table></body></html>';

Set @TableHead = '<html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
                  '</style>' +
                  '</head>' +
                  '<body>'
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)
 
-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			SET @TableTail = '</table></body></html>';
			SET @Table_Content = @TableHead+'<table cellpadding=0 cellspacing=0 border=0>' +
                  '<tr bgcolor=#FFEFD8><td align=center><b>Job Name</b></td>' + 
                  '<td align=center><b>Last Run Date</b></td>' + 
                  '<td align=center><b>Last Run Time</b></td>' + 
                  '<td align=center><b>Next Run Date</b></td>' + 
                  '<td align=center><b>Next Run Time</b></td>' +
                  '<td align=center><b>Next Run Time</b></td>' +
                  '<td align=center><b>Running</b></td>' +
                  '<td align=center><b>Current Step</b></td>' +
                  '<td align=center><b>Current Rettry Attempt</b></td>' +
                  '<td align=center><b>Job State</b></td></tr>'
			SELECT @Body = (SELECT ROW_NUMBER() OVER(ORDER BY job_id) % 2 AS [TRRow],
            job_id AS [TD],
            last_run_date AS [TD],
            last_run_time AS [TD],
            next_run_date AS [TD],
            next_run_time AS [TD],
            CASE running
				WHEN 0 THEN 'Stopped'
				WHEN 1 THEN 'Running'
			END AS [TD],
            current_step AS [TD],
            current_retry_attempt AS [TD],
            CASE job_state
				WHEN 0 THEN 'Not idle or suspended'
				WHEN 1 THEN 'Executing'
				WHEN 2 THEN 'Waiting For Thread'
				WHEN 3 THEN 'Between Retries'
				WHEN 4 THEN 'Idle'
				WHEN 5 THEN 'Suspended'
				WHEN 6 THEN 'Waiting For Step To Finish'
				WHEN 7 THEN 'Performing Completion Actions'
			END AS [TD]
			FROM #xp_results_new
            FOR XML RAW('tr'), ELEMENTS)
			
			SET @Body = Replace(@Body, '_x0020_', space(1))
			SET @Body = Replace(@Body, '_x003D_', '=')
			SET @Body = Replace(@Body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
			SET @Body = Replace(@Body, '<TRRow>0</TRRow>', '')

			SELECT @Body = @TableHead + @Body + @TableTail
			
			SET @mail_subject = '[!!!WARNING!!!] Job'+ISNULL(@JobName,'UNKNOWN')+' is running longer than 30 minutes'
			
			EXEC msdb.dbo.sp_send_dbmail 
			@recipients=@mail_recipients,
			@subject = @mail_subject,
			@body = @Body,
			@body_format = 'HTML' ;  
			
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END
			END
     END
 
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime
END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new

Open in new window

Thanks Sir, Can you please explain the code Sir. Willing to learn the code.Awesome work.

I have to test it.I have one more doubt.
Will script will take of sending the mail to the appropriate recipients
@mail_profile VARCHAR(255)=NULL,
  @mail_recipients VARCHAR(512)='test@company.com'

or should need to configure any operator or enable database mail?Because by default all are disabled in our environment.
Dear Vivekanandhan,
Please edit code to fulfill your requirements. I've added some values to show you how it should be configured. You can edit @mail_recipients VARCHAR(512)='test@company.com'
to your default recipients list. While you're executing procedure you suply this parameter with value, default one will be ignored. NULL value for mail profile name means that sp_send_dbmail procedure will use default mail profile for user executing code.

E.g.
EXECUTE [dbo].[SQL_Job_Monitor] @mail_profile='Name of your mail profile', @mail_recipients='List of recipients'

EXECUTE [dbo].[SQL_Job_Monitor] @mail_profile='Jobs_profile', @mail_recipients='Vivekanandhan.Periasamy@ee.com;Someone.Else@mailaddress.com'
so i should configure my database mail so that NULL value for mail profile will use my default mail profile.
And I will give my recipients.
Is there anything else I should manually alter in the script?
NULL is the default value for sp_send_dbmail procedure. In case you don't specify any profiles procedure will use profile marked as default for login executing procedure.
Don't hesitate to post problems with code, I'll try to fix them as soon as possible.
Sir give me 2 days. i need to get approval for enabling database mail.
Sure,

Take your time, I'm just Daniel btw ;)
Sir meanwhile can you please explain me the code you have written.i have less knowledge in xml query.
User generated imageI have just updated procedure code. The xml part is to create HTML code to form nice table for your email. You can easily extend it to send other useful info.
Updated code:
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL, -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          @mail_profile VARCHAR(255)=NULL,
          @mail_recipients VARCHAR(512)='test@company.com'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)

Set @TableTail = '</table></body></html>';

Set @TableHead = '<html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
                  '</style>' +
                  '</head>' +
                  '<body>'
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)
 
-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			SET @TableTail = '</table></body></html>';
			SET @Table_Content = @TableHead+'<table cellpadding=0 cellspacing=0 border=0>' +
                  '<tr bgcolor=#FFEFD8><td align=center><b>Job Name</b></td>' + 
                  '<td align=center><b>Is Running</b></td>' +
                  '<td align=center><b>Current Step</b></td>' +
                  '<td align=center><b>Current Rettry Attempt</b></td>' +
                  '<td align=center><b>Job State</b></td></tr>'
			SELECT @Body = (SELECT ROW_NUMBER() OVER(ORDER BY x.job_id) % 2 AS [TRRow],
            sj.name AS [TD],
            CASE running
				WHEN 0 THEN 'Stopped'
				WHEN 1 THEN 'Running'
			END AS [TD],
            current_step AS [TD],
            current_retry_attempt AS [TD],
            CASE job_state
				WHEN 0 THEN 'Not idle or suspended'
				WHEN 1 THEN 'Executing'
				WHEN 2 THEN 'Waiting For Thread'
				WHEN 3 THEN 'Between Retries'
				WHEN 4 THEN 'Idle'
				WHEN 5 THEN 'Suspended'
				WHEN 6 THEN 'Waiting For Step To Finish'
				WHEN 7 THEN 'Performing Completion Actions'
			END AS [TD]
			FROM #xp_results_new x
			JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
            FOR XML RAW('tr'), ELEMENTS)
			
			SET @Body = Replace(@Body, '_x0020_', space(1))
			SET @Body = Replace(@Body, '_x003D_', '=')
			SET @Body = Replace(@Body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#C6CFFF>')
			SET @Body = Replace(@Body, '<TRRow>0</TRRow>', '')

			SELECT @Body = @TableHead + @Table_Content + @Body + @TableTail
			
			SET @mail_subject = '[!!!WARNING!!!] Job '+QUOTENAME(ISNULL(@JobName,'UNKNOWN'))+' is running longer than 30 minutes'
			
			EXEC msdb.dbo.sp_send_dbmail 
			@recipients=@mail_recipients,
			@subject = @mail_subject,
			@body = @Body,
			@body_format = 'HTML' ;  
			
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END
			END
     END
 
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime
END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new

Open in new window


Sample table:
User generated image
Hello Sir,

I tried lot to get an approval but my senior management rejected the request to configure Database mail.

Is it possible to re-write the scipt,which will store the information in the table. So that it will be easy for me configure SSRS report and will help in showing it in a graph.

Information details needed are SQL jobname, SQL job running morethan 30 mins, error message in case of failure,Time the sql job stopped,time the sql job started again,Current status
I don't want to sens a mail, just it needs to perform the restart of the SQL Job.And i want store those logs into a table. Since I didn't get approval for enabling database mail,I need to look out for other options.
Check whether this suits you:
CREATE TABLE [msdb].[dbo].[jobs_stats] (
	entry_id INT IDENTITY(1,1) NOT NULL,
	job_id UNIQUEIDENTIFIER NOT NULL,
	job_name NVARCHAR(2000) NOT NULL,
	job_status CHAR(7) NOT NULL,
	current_step INT NOT NULL,
    current_retry_attempt INT NOT NULL,
	job_state NVARCHAR(40) NOT NULL,
	entry_date DATETIME NOT NULL,
	CONSTRAINT [PK_jobs_stats] PRIMARY KEY CLUSTERED
	(entry_id ASC)
	)
	
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL, -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          @mail_profile VARCHAR(255)=NULL,
          @mail_recipients VARCHAR(512)='test@company.com'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)

Set @TableTail = '</table></body></html>';

Set @TableHead = '<html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
                  '</style>' +
                  '</head>' +
                  '<body>'
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)

-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			IF EXISTS (SELECT 1 FROM #xp_results_new)
				BEGIN
					INSERT INTO [msdb].[dbo].[jobs_stats] (job_id, job_name, job_status, current_step, current_retry_attempt, job_state, entry_date)
					SELECT x.job_id,
					sj.name as job_name,
					CASE running
						WHEN 0 THEN 'Stopped'
						WHEN 1 THEN 'Running'
					END AS job_status,
					current_step ,
					current_retry_attempt ,
					CASE job_state
						WHEN 0 THEN 'Not idle or suspended'
						WHEN 1 THEN 'Executing'
						WHEN 2 THEN 'Waiting For Thread'
						WHEN 3 THEN 'Between Retries'
						WHEN 4 THEN 'Idle'
						WHEN 5 THEN 'Suspended'
						WHEN 6 THEN 'Waiting For Step To Finish'
						WHEN 7 THEN 'Performing Completion Actions'
					END AS job_state,
					GETDATE() AS entry_date
					FROM #xp_results_new x
					JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
				END
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END
			END
     END
 
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime
END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new
                                            

Open in new window

If it's less than 60 mins, will stop and restart?
IF @JobRunningTime<60
            BEGIN
                  PRINT 'Stopping job [' + @Jobname + ']'
                  EXEC msdb..sp_stop_job @job_name=@JobName
                  WAITFOR DELAY '00:00:05'
                  PRINT 'Starting job [' + @Jobname + ']'
                  EXEC msdb..sp_start_job @job_name=@JobName

Here it only stops, will it not start the job again???

BEGIN
                                    PRINT 'Stopping job [' + @Jobname + ']'
                                    EXEC msdb..sp_stop_job @job_name=@JobName
Hi,

BEGIN
                  PRINT 'Stopping job [' + @Jobname + ']'
                  EXEC msdb..sp_stop_job @job_name=@JobName --HERE JOB STOPS
                  WAITFOR DELAY '00:00:05' --WAIT 5 SECONDS
                  PRINT 'Starting job [' + @Jobname + ']'
                  EXEC msdb..sp_start_job @job_name=@JobName -- HERE JOB STARTS
If it's less than 60 mins, will stop and restart?
IF @JobRunningTime<60
            BEGIN
                  PRINT 'Stopping job [' + @Jobname + ']'
                  EXEC msdb..sp_stop_job @job_name=@JobName
                  WAITFOR DELAY '00:00:05'
                  PRINT 'Starting job [' + @Jobname + ']'
                  EXEC msdb..sp_start_job @job_name=@JobName
The above line i understood,



BEGIN
                                    PRINT 'Stopping job [' + @Jobname + ']'
                                    EXEC msdb..sp_stop_job @job_name=@JobName

Why we are having one more stop at the end of the sp?
It was retained from the original code. I thought you wanted to keep that part as it was originally. If you wish not to have it there, just remove or comment it out:
CREATE TABLE [msdb].[dbo].[jobs_stats] (
	entry_id INT IDENTITY(1,1) NOT NULL,
	job_id UNIQUEIDENTIFIER NOT NULL,
	job_name NVARCHAR(2000) NOT NULL,
	job_status CHAR(7) NOT NULL,
	current_step INT NOT NULL,
    current_retry_attempt INT NOT NULL,
	job_state NVARCHAR(40) NOT NULL,
	entry_date DATETIME NOT NULL,
	CONSTRAINT [PK_jobs_stats] PRIMARY KEY CLUSTERED
	(entry_id ASC)
	)
	
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL, -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          @mail_profile VARCHAR(255)=NULL,
          @mail_recipients VARCHAR(512)='test@company.com'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)

Set @TableTail = '</table></body></html>';

Set @TableHead = '<html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
                  '</style>' +
                  '</head>' +
                  '<body>'
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)

-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			IF EXISTS (SELECT 1 FROM #xp_results_new)
				BEGIN
					INSERT INTO [msdb].[dbo].[jobs_stats] (job_id, job_name, job_status, current_step, current_retry_attempt, job_state, entry_date)
					SELECT x.job_id,
					sj.name as job_name,
					CASE running
						WHEN 0 THEN 'Stopped'
						WHEN 1 THEN 'Running'
					END AS job_status,
					current_step ,
					current_retry_attempt ,
					CASE job_state
						WHEN 0 THEN 'Not idle or suspended'
						WHEN 1 THEN 'Executing'
						WHEN 2 THEN 'Waiting For Thread'
						WHEN 3 THEN 'Between Retries'
						WHEN 4 THEN 'Idle'
						WHEN 5 THEN 'Suspended'
						WHEN 6 THEN 'Waiting For Step To Finish'
						WHEN 7 THEN 'Performing Completion Actions'
					END AS job_state,
					GETDATE() AS entry_date
					FROM #xp_results_new x
					JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
				END
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				/*IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END*/
			END
     END
 
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime
END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new
                                            
                                            

Open in new window

Do we need these lines?If we don't use email services.

 @mail_profile VARCHAR(255)=NULL,
          @mail_recipients VARCHAR(512)='test@company.com'

Set @TableTail = '</table></body></html>';

Set @TableHead = '<html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
                  '</style>' +
                  '</head>' +
                  '<body>'
And I want to monitor only ALL - DelHistory SQL job.
No, you don't need them. Furthermore if you run this proc on SQL 2005 and higher you can shorten code a bit more.
/*CREATE TABLE [msdb].[dbo].[jobs_stats] (
	entry_id INT IDENTITY(1,1) NOT NULL,
	job_id UNIQUEIDENTIFIER NOT NULL,
	job_name NVARCHAR(2000) NOT NULL,
	job_status CHAR(7) NOT NULL,
	current_step INT NOT NULL,
    current_retry_attempt INT NOT NULL,
	job_state NVARCHAR(40) NOT NULL,
	entry_date DATETIME NOT NULL,
	CONSTRAINT [PK_jobs_stats] PRIMARY KEY CLUSTERED
	(entry_id ASC)
	)*/
	
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
		  @job_name VARCHAR(255) = 'ALL - DelHistory SQL'  -- Default is set to [ALL - DelHistory SQL]
          ) 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)

-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
SELECT @job_id = job_id FROM msdb..sysjobs WHERE name = @job_name

INSERT INTO #xp_results
EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
SELECT @JobName=j.name, @job_id=a.job_id,  @JobStartTime=a.start_execution_date, @JobRunningTime=DATEDIFF(MINUTE,a.start_execution_date,GETDATE())
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name = @job_name
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
 
IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_id AND stop_execution_date is NULL AND  
@JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			IF EXISTS (SELECT 1 FROM #xp_results_new)
				BEGIN
					INSERT INTO [msdb].[dbo].[jobs_stats] (job_id, job_name, job_status, current_step, current_retry_attempt, job_state, entry_date)
					SELECT x.job_id,
					sj.name as job_name,
					CASE running
						WHEN 0 THEN 'Stopped'
						WHEN 1 THEN 'Running'
					END AS job_status,
					current_step ,
					current_retry_attempt ,
					CASE job_state
						WHEN 0 THEN 'Not idle or suspended'
						WHEN 1 THEN 'Executing'
						WHEN 2 THEN 'Waiting For Thread'
						WHEN 3 THEN 'Between Retries'
						WHEN 4 THEN 'Idle'
						WHEN 5 THEN 'Suspended'
						WHEN 6 THEN 'Waiting For Step To Finish'
						WHEN 7 THEN 'Performing Completion Actions'
					END AS job_state,
					GETDATE() AS entry_date
					FROM #xp_results_new x
					JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
				END
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
			END
     END

DROP TABLE #xp_results
DROP TABLE #xp_results_new

Open in new window

Thanks Daniel for helping me all the way.

I created a sp, it complied successfully but when i ran the job it failed with the error

Procedure or functionSQL_Job_Monitor has too many arguments specified. [SQLSTATE 42000] (Error 8144).  NOTE: The step was retried the requested number of times (3) without succeeding.  The step failed.

I'm using SQL server 2008 R2. So i guess there won't any problem.
How do you execute proc? By using last code you can pass 2 parameters - @threshold_minute and  @job_name
I used below code and got an error. Can you point me where I'm wrong.
CREATE TABLE [msdb].[dbo].[jobs_stats] (
	entry_id INT IDENTITY(1,1) NOT NULL,
	job_id UNIQUEIDENTIFIER NOT NULL,
	job_name NVARCHAR(2000) NOT NULL,
	job_status CHAR(7) NOT NULL,
	current_step INT NOT NULL,
    current_retry_attempt INT NOT NULL,
	job_state NVARCHAR(40) NOT NULL,
	entry_date DATETIME NOT NULL,
	CONSTRAINT [PK_jobs_stats] PRIMARY KEY CLUSTERED
	(entry_id ASC)
	)
	
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL, -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          @mail_profile VARCHAR(255)=NULL,
          @mail_recipients VARCHAR(512)='test@company.com'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)

Set @TableTail = '</table></body></html>';

Set @TableHead = '<html><head>' +
                  '<style>' +
                  'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
                  '</style>' +
                  '</head>' +
                  '<body>'
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)

-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			IF EXISTS (SELECT 1 FROM #xp_results_new)
				BEGIN
					INSERT INTO [msdb].[dbo].[jobs_stats] (job_id, job_name, job_status, current_step, current_retry_attempt, job_state, entry_date)
					SELECT x.job_id,
					sj.name as job_name,
					CASE running
						WHEN 0 THEN 'Stopped'
						WHEN 1 THEN 'Running'
					END AS job_status,
					current_step ,
					current_retry_attempt ,
					CASE job_state
						WHEN 0 THEN 'Not idle or suspended'
						WHEN 1 THEN 'Executing'
						WHEN 2 THEN 'Waiting For Thread'
						WHEN 3 THEN 'Between Retries'
						WHEN 4 THEN 'Idle'
						WHEN 5 THEN 'Suspended'
						WHEN 6 THEN 'Waiting For Step To Finish'
						WHEN 7 THEN 'Performing Completion Actions'
					END AS job_state,
					GETDATE() AS entry_date
					FROM #xp_results_new x
					JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
				END
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				/*IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END*/
			END
     END
 
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime
END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new
                                            
                                            

Open in new window

You need to show me command you execute in that Job.
parameter to run the job:
Exec msdb.dbo.SQL_Job_Monitor 60, 0,'<ExcludeJob><JobName JOB="PerfData"/></ExcludeJob>'
Right, my fault. There was a bug in code (Fetch Next has too few variables :/).
I've modified code. There are few lines at the end which are commented. If you wish to have  in your check job history comment for each job which wasn't candidate for check, please uncomment those lines.

IF NOT EXISTS (SELECT 1 FROM msdb.sys.tables WHERE name = 'jobs_stats')
BEGIN
CREATE TABLE [msdb].[dbo].[jobs_stats] (
	entry_id INT IDENTITY(1,1) NOT NULL,
	job_id UNIQUEIDENTIFIER NOT NULL,
	job_name NVARCHAR(2000) NOT NULL,
	job_status CHAR(7) NOT NULL,
	current_step INT NOT NULL,
    current_retry_attempt INT NOT NULL,
	job_state NVARCHAR(40) NOT NULL,
	entry_date DATETIME NOT NULL,
	CONSTRAINT [PK_jobs_stats] PRIMARY KEY CLUSTERED
	(entry_id ASC)
	)
END
GO
ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 60,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime TINYINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)

-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			IF EXISTS (SELECT 1 FROM #xp_results_new)
				BEGIN
					INSERT INTO [msdb].[dbo].[jobs_stats] (job_id, job_name, job_status, current_step, current_retry_attempt, job_state, entry_date)
					SELECT x.job_id,
					sj.name as job_name,
					CASE running
						WHEN 0 THEN 'Stopped'
						WHEN 1 THEN 'Running'
					END AS job_status,
					current_step ,
					current_retry_attempt ,
					CASE job_state
						WHEN 0 THEN 'Not idle or suspended'
						WHEN 1 THEN 'Executing'
						WHEN 2 THEN 'Waiting For Thread'
						WHEN 3 THEN 'Between Retries'
						WHEN 4 THEN 'Idle'
						WHEN 5 THEN 'Suspended'
						WHEN 6 THEN 'Waiting For Step To Finish'
						WHEN 7 THEN 'Performing Completion Actions'
					END AS job_state,
					GETDATE() AS entry_date
					FROM #xp_results_new x
					JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
				END
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				/*IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END*/
			END
     END
	 /*
	 --If you wish to keep info that particular job is not candidate for check please remove comments in this part of code
	 ELSE
	 PRINT 'Job '+@JobName+' is not running longer that 30 seconds and wasn''t checked!'
	 */
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime, @JobRunningTime

END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new

Open in new window

for testing purpose,I have created the changed the parameter value.

@threshold_minute int = 1 and schedule it to run every 1 minute.
parameter to run the job:
Exec msdb.dbo.SQL_Job_Monitor 1, 0,'<ExcludeJob><JobName JOB="PerfData"/></ExcludeJob>

created another job which will execute for 5:00 minutes.But the monitoring job wasn't able to capture the job and didn't restart it.
Wait job executed sucessfully.
And there was no entry logged into jobs_stats table.Is that anything I'm missing.
Alter JOB
USE [msdb]
GO

/****** Object:  StoredProcedure [dbo].[SQL_Job_Monitor]    Script Date: 06/23/2012 21:49:40 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


ALTER PROCEDURE [dbo].[SQL_Job_Monitor] (
          @threshold_minute int = 1,       -- Default is set to 60 minutes
          @StopJob bit = 0,                  -- Default is not to stop the job 
          @ExcludeJOb XML =NULL -- '<ExcludeJob><JobName JOB="SQL SERVER JOB"/></ExcludeJob>'
          )
 
AS
 
SET NOCOUNT ON
 
DECLARE @is_sysadmin     INT
DECLARE @job_owner       SYSNAME
DECLARE @job_id         UNIQUEIDENTIFIER
DECLARE @JobName         VARCHAR(255)
DECLARE @JobStartTime    DateTime
DECLARE @JobRunningTime bigINT
DECLARE @Msg            VARCHAR(1000)
DECLARE @ExcludeJObTable TABLE (JobName VARCHAR(1000))
DECLARE @Body varchar(max)
DECLARE	@TableHead varchar(max)
DECLARE	@Table_Content varchar(max)
DECLARE @TableTail varchar(max)
DECLARE @mail_subject VARCHAR(255)
 
/** Insert the jobs to be excluded from job monitoring  */
INSERT @ExcludeJObTable (JobName)
SELECT xmllist.rows.value('@JOB','varchar(1000)') 
from @ExcludeJOb.nodes('/ExcludeJob/JobName') xmllist(rows)

-- Step 1: Create intermediate work tables to store the running job data
CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)

CREATE TABLE #xp_results_new (job_id                UNIQUEIDENTIFIER NOT NULL,
                       last_run_date         INT              NOT NULL,
                       last_run_time         INT              NOT NULL,
                       next_run_date         INT              NOT NULL,
                       next_run_time         INT              NOT NULL,
                       next_run_schedule_id  INT              NOT NULL,
                       requested_to_run      INT              NOT NULL, -- BOOL
                       request_source        INT              NOT NULL,
                       request_source_id     sysname          NULL,
                       running               INT              NOT NULL, -- BOOL
                       current_step          INT              NOT NULL,
                       current_retry_attempt INT              NOT NULL,
                       job_state             INT              NOT NULL)
 
-- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
SELECT @job_owner = SUSER_SNAME() 
IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
BEGIN
    INSERT INTO #xp_results
    EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
END
ELSE
BEGIN
     INSERT INTO #xp_results
     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
END
 
-- Step 3: Get the current job that exceeded the monitoring threshold
 
DECLARE joblist_cursor CURSOR FOR
SELECT j.name, a.job_id, a.start_execution_date, DATEDIFF(MINUTE,a.start_execution_date,GETDATE()) AS JobRunningTime
FROM #xp_results x
INNER JOIN msdb.dbo.sysjobactivity a
ON x.job_id = a.job_id
INNER join msdb.dbo.sysjobs j
ON a.job_id = j.job_id
     WHERE x.running = 1                                               -- The job is running
     AND j.name  not IN  (SELECT Jobname from @ExcludeJObTable)               --Excluding the job Monitoring
     AND a.session_id = (select max(session_id) from msdb.dbo.sysjobactivity where job_id = a.job_id)
     AND a.stop_execution_date is null                                 -- The job is not complete 
--     AND a.start_execution_date <= dateadd(minute, -@threshold_minute, getdate())     -- Measure the thresdhold
 
OPEN joblist_cursor
 
FETCH NEXT FROM joblist_cursor
INTO @JobName, @job_id, @JobStartTime, @JobRunningTime
 
WHILE @@FETCH_STATUS = 0
BEGIN
     -- Check again if the same job at the starting time is still active
     IF EXISTS (SELECT TOP 1 * FROM msdb.dbo.sysjobactivity WHERE job_id = @job_ID AND stop_execution_date is NULL AND  
     @JobRunningTime>30)
     BEGIN
		IF @JobRunningTime<60
		BEGIN
			PRINT 'Stopping job [' + @Jobname + ']'
			EXEC msdb..sp_stop_job @job_name=@JobName
			WAITFOR DELAY '00:00:05'
			PRINT 'Starting job [' + @Jobname + ']'
			EXEC msdb..sp_start_job @job_name=@JobName
			
			INSERT INTO #xp_results_new
			EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
			
			IF EXISTS (SELECT 1 FROM #xp_results_new)
				BEGIN
					INSERT INTO [msdb].[dbo].[jobs_stats] (job_id, job_name, job_status, current_step, current_retry_attempt, job_state, entry_date)
					SELECT x.job_id,
					sj.name as job_name,
					CASE running
						WHEN 0 THEN 'Stopped'
						WHEN 1 THEN 'Running'
					END AS job_status,
					current_step ,
					current_retry_attempt ,
					CASE job_state
						WHEN 0 THEN 'Not idle or suspended'
						WHEN 1 THEN 'Executing'
						WHEN 2 THEN 'Waiting For Thread'
						WHEN 3 THEN 'Between Retries'
						WHEN 4 THEN 'Idle'
						WHEN 5 THEN 'Suspended'
						WHEN 6 THEN 'Waiting For Step To Finish'
						WHEN 7 THEN 'Performing Completion Actions'
					END AS job_state,
					GETDATE() AS entry_date
					FROM #xp_results_new x
					JOIN msdb.dbo.sysjobs sj ON x.job_id=sj.job_id
				END
			TRUNCATE TABLE #xp_results_new;      
		END
			IF @JobRunningTime>=@threshold_minute
			BEGIN
				SELECT @Msg = 'The SQL Job - [' + @JobName + '] on ' + @@ServerName + ' has exceeded the job running threshold of ' + CONVERT(varchar(3), @threshold_minute) + ' minutes.'
				RAISERROR (@Msg, 16, 1) WITH LOG
				/*IF @StopJob = 1
					BEGIN
						PRINT 'Stopping job [' + @Jobname + ']'
						EXEC msdb..sp_stop_job @job_name=@JobName
					END*/
			END
     END
	
	 --If you wish to keep info that particular job is not candidate for check please remove comments in this part of code
	 ELSE
	 PRINT 'Job '+@JobName+' is not running longer that 30 seconds and wasn''t checked!'
	 
     FETCH NEXT FROM joblist_cursor
     INTO @JobName, @job_id, @JobStartTime, @JobRunningTime

END
 
CLOSE joblist_cursor
DEALLOCATE joblist_cursor
DROP TABLE #xp_results
DROP TABLE #xp_results_new
GO

Open in new window


Wait job sp's
USE [msdb]
GO
/****** Object:  StoredProcedure [dbo].[test]    Script Date: 06/23/2012 21:47:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[test] 
as 
begin 
waitfor delay '00:05:00'
end

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Daniel_PL
Daniel_PL
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Awesome Knowledge.Still there few things to be turned,i will try to post in different question