Montag, 28. Februar 2011

SQL Server Agent Job Step Notification

SQL Server Agent bietet unter anderem E-Mail Benachrichtigungen für die Jobs an, die z.B. fehlschlagen. Aber für das ganze Job, nicht für die einzelnen Schritte. Wenn so eine E-Mail Benachrichtigung konfiguriert ist, kriegt man z.B. folgende Nachricht:
JOB RUN: 'name' was run on 14.10.2010 at 02:00:00
DURATION: 0 hours, 16 minutes, 4 seconds
STATUS: Failed
MESSAGES: The job failed. The Job was invoked by Schedule ** (name). The last step to run was step * (name).
Die Nachricht beinhaltet keine Info über den Fehler selber, obwohl ein Eintrag in die Tabelle msdb.dbo.sysjobhistory gemacht wird, wenn ein Jobstep fehlgeschlagen oder erfolgreich ausgeführt ist.
Es wäre günstiger, wenn man die detaillierte Info gekriegt hätte und sich die Anmeldung am System mit der Untersuchung des Fehlerprotokolls ersparen könnte, denn meistens kann die Fehlerursache aus der detaillierten Fehlermeldung ermittelt werden.
Als kleine Hilfe habe ich den folgenden Insert-Trigger der Tabelle msdb.dbo.sysjobhistory implementiert, der eine E-Mail an den beim Job eingetragenen Operator versendet, wenn die Benachrichtigungsbedingungen des Jobs erfüllt sind.
Wenn Sie den Trigger einsetzen möchten, tragen Sie einen gültigen Profilnamen der Database Mail im Trigger in der Variable @profile_name ein.
Alle konfigurierten Profile der Database Mail finden Sie in der Tabelle msdb.dbo.sysmail_profile.
use msdb
go
if exists (
select * from sys.triggers 
where object_id = object_id(N'[dbo].[TR_sysjobhistory_INS]'))
drop trigger [dbo].[TR_sysjobhistory_INS]
go

create trigger dbo.tr_sysjobhistory_ins
  on dbo.sysjobhistory
  after insert
as
begin
 set nocount on;

 declare @subject nvarchar(255)
 declare @body nvarchar(max)
 declare @message nvarchar(4000)
 declare @run_date varchar(10)
 declare @run_time int

 declare @profile_name sysname
 set @profile_name = 'hier profile_name eintragen'
 declare @recipients nvarchar(max)

 select
  @subject = (case h.run_status when 1 then 'Succeeded' else 'Failed' end)
  + ' [' + h.[server] + '].[' + j.[name] + '].[' + h.[step_name] + ']',
  @message = h.[message],
  @run_date = cast(convert(date,(cast(h.[run_date] as varchar(10))),120) as varchar(10)),
  @run_time = h.[run_time],
  @recipients = o.email_address
 from
  inserted h
  inner join msdb.dbo.sysjobs j
  on h.job_id = j.job_id
  left join msdb.dbo.sysoperators o
  on j.notify_email_operator_id = o.id
 where
  ((h.[run_status] = 0 and j.notify_level_email = 2)
  or (h.[run_status] = 1 and j.notify_level_email = 1))
  and j.notify_level_email > 0
  and h.step_id > 0

 if (@subject is not null)
 begin
  declare @crlf char(2)
  set @crlf = char(13) + char(10)
  declare @pos tinyint = (case when @run_time > 95959 then 3 else 2 end)
  set @body = 'RUN STEP: ' + cast(convert(date,@run_date, 120) as varchar(10)) + 
  ' ' + stuff(stuff((cast(@run_time as varchar(32))),@pos,0,':'),@pos+3,0,':')
  set @body = @body + @crlf
  set @body = @body + 'MESSAGE: ' + @message
  
  exec msdb.dbo.sp_send_dbmail
   @profile_name = @profile_name,
   @recipients = @recipients,
   @body = @body,
   @subject = @subject;
 end
end
go