alerta quando qualquer trabalho em uma categoria de trabalho falha

11

É possível configurar um alerta no SQL Server 2008 que enviará um email sempre que um trabalho em uma categoria específica falhar?

Gostaria de saber porque gostaria de configurar um email sempre que uma assinatura do SSRS falhar - e todas essas assinaturas são trabalhos na categoria Servidor de Relatório .

EDIT - acontece que, quando uma assinatura do SSRS falha, o trabalho em si não falha, portanto, minha pergunta não se aplica ao uso do monitoramento de assinatura do SSRS. No entanto, eu ainda gostaria de saber para outros trabalhos que executamos em nosso ambiente

JHFB
fonte
Um passo falha pelo menos? Minha resposta abaixo analisa os trabalhos na categoria 'Servidor de Relatório', mas se você quiser apenas todos os trabalhos, poderá remover toda a AND EXISTSparte do INSERT/SELECT. E provavelmente mude o nome ReportServerJob_FailQueuepara algo mais genérico. :-)
Aaron Bertrand
Infelizmente, nenhuma etapa falha - mas estou confiante de que posso criar outro mecanismo de monitoramento!
JHFB

Respostas:

10

Você pode criar um trabalho que verifique a tabela msdb.dbo.sysjobhistory a cada minuto (ou com a frequência que desejar). Você pode implementar uma tabela de filas para enviar apenas a mensagem para qualquer falha de instância única uma vez.

USE msdb;
GO

CREATE TABLE dbo.ReportServerJob_FailQueue
(
  job_id UNIQUEIDENTIFIER,
  run_date INT,
  run_time INT, -- horrible schema, just matching sysjobhistory
  sql_message_id INT,
  sent BIT NOT NULL DEFAULT 0,
  PRIMARY KEY (job_id, run_date, run_time)
);

Portanto, seu código, que você pode agendar em um trabalho, se torna:

INSERT dbo.ReportServerJob_FailQueue
  (job_id, run_date, run_time, sql_message_id)
SELECT job_id, run_date, run_time, sql_message_id
FROM msdb.dbo.sysjobhistory AS h
WHERE step_id = 0 
AND run_status = 0
AND EXISTS 
(
  SELECT 1 FROM msdb.dbo.sysjobs AS j
    INNER JOIN msdb.dbo.syscategories AS c
    ON j.category_id = c.category_id
    WHERE j.job_id = h.job_id
   AND c.name = 'Report Server'
)
AND NOT EXISTS 
(
  SELECT 1 FROM dbo.ReportServerJob_FailQueue
    WHERE job_id = h.job_id
    AND run_date = h.run_date
    AND run_time = h.run_time
);

Agora, suponho que você queira enviar um email individual para cada falha, portanto isso também pode fazer parte do trabalho (ou parte de um trabalho diferente, embora isso não seja necessariamente sensato):

DECLARE 
  @subject NVARCHAR(4000),
  @body NVARCHAR(4000),
  @name SYSNAME,
  @id UNIQUEIDENTIFIER,
  @date INT,
  @time INT,
  @msg INT;

DECLARE c CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR SELECT q.job_id, q.run_date, q.run_time, q.sql_message_id, j.name
  FROM dbo.ReportServerJob_FailQueue AS q
  INNER JOIN msdb.dbo.sysjobs AS j
  ON q.job_id = j.job_id
  WHERE q.sent = 0;

OPEN c;

FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;

WHILE @@FETCH_STATUS = 0
BEGIN

  SET @subject = 'Report Server job ' + @name + ' failed.';
  SET @body = 'Error number: ' + RTRIM(@msg);

  BEGIN TRY
    EXEC msdb.dbo.sp_send_dbmail 
      @profile_name = 'default',     -- you may need to change this
      @recipients   = '[email protected]', -- you will need to change this
      @subject      = @subject,
      @body         = @body;

    UPDATE dbo.ReportServerJob_FailQueue
      SET sent = 1 
      WHERE job_id = @id
      AND run_date = @date
      AND run_time = @time;
  END TRY
  BEGIN CATCH
    PRINT 'Will have to try that one again later.';
  END

  FETCH NEXT FROM c INTO @id, @date, @time, @msg, @name;
END

CLOSE c; DEALLOCATE c;

Existem outras opções também:

  • pull em sysjobhistory.message
  • observe as etapas individuais que falharam
  • envie apenas uma mensagem para qualquer trabalho uma vez em n minutos / horas, mesmo se houver várias falhas
  • envie um único email com uma lista de todos os trabalhos que falharam, em vez de um email para cada falha
  • convém incluir run_date e run_time na mensagem, pois o email pode não ser enviado ou recebido com rapidez suficiente para ser uma medida precisa de quando a tarefa realmente falhou (não a incluí aqui porque suas horríveis opções de tipo de dados tornar a formatação dessas coisas uma PITA real)
  • você provavelmente desejará limpar as linhas antigas depois de algum tempo; portanto, um comando de limpeza também pode ser desejado

Se o Database Mail ainda não estiver configurado, consulte este tutorial .

Você também pode usar ferramentas de terceiros (por exemplo, SQL Sentry Event Manager ) que simplificarão muito isso. Divulgação completa: Trabalho para o SQL Sentry.

Aaron Bertrand
fonte
0

Com base na sua edição, isso seria apenas uma extensão da resposta de Aaron, referente às falhas de assinatura do SSRS (não apenas ao trabalho do SQL Agent). Eu sugeriria apenas adicionar uma etapa ao trabalho de monitoramento de trabalho, ou você poderia fazer isso como um trabalho separado.

Para obter o status da assinatura, basta verificar a ReportServer.dbo.ExecutionLog3 visualização . A Statuscoluna mostrará tudo, exceto rsSuccessfalhas. Basta filtrar por RequestType = 'Subscription'. Você deseja incluir uma verificação de tempo, para não verificar todos os registros a cada vez. Se você executar o trabalho a cada 15 minutos, verifique TimeStartos últimos 15 minutos.


fonte