ostrzegaj, gdy którekolwiek zadanie z danej kategorii zawodzi

11

Czy w SQL Server 2008 można ustawić alert, który wyśle ​​wiadomość e-mail za każdym razem, gdy zadanie w określonej kategorii nie powiedzie się?

Zastanawiam się, ponieważ chciałbym skonfigurować e-mail za każdym razem, gdy subskrypcja SSRS się nie powiedzie - i wszystkie te subskrypcje są zadaniami z kategorii Serwer raportów .

EDYCJA - okazuje się, że gdy subskrypcja SSRS zawiedzie, samo zadanie nie zawiedzie, więc moje pytanie nie będzie dotyczyło monitorowania subskrypcji SSRS. Jednak nadal chciałbym wiedzieć o innych zadaniach, które wykonujemy w naszym środowisku

JHFB
źródło
Czy krok przynajmniej kończy się niepowodzeniem? Moja odpowiedź poniżej dotyczy zadań w kategorii „Serwer raportów”, ale jeśli chcesz tylko wszystkie zadania, możesz usunąć całą ich AND EXISTSczęść INSERT/SELECT. I prawdopodobnie zmień nazwę ReportServerJob_FailQueuena coś bardziej ogólnego. :-)
Aaron Bertrand
Niestety, żaden krok nie zawiedzie - ale jestem pewien, że mogę wymyślić inny mechanizm monitorowania!
JHFB

Odpowiedzi:

10

Możesz utworzyć zadanie sprawdzające tabelę msdb.dbo.sysjobhistory co minutę (lub jak często chcesz). Możesz zaimplementować tabelę kolejek, abyś mógł wysłać wiadomość tylko raz w przypadku awarii pojedynczej instancji.

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)
);

Zatem twój kod, który możesz zaplanować w zadaniu, staje się:

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
);

Teraz zakładam, że chcesz wysłać indywidualny e-mail dla każdej awarii, więc może to być również część zadania (lub część innego zadania, choć niekoniecznie jest to mądre):

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;

Istnieją również inne opcje:

  • ściągnij sysjobhistory.message
  • spójrz na poszczególne kroki, które się nie powiodły
  • wysyłaj wiadomość dla dowolnego zadania tylko raz na n minut / godzin, nawet jeśli wystąpi wiele awarii
  • wyślij pojedynczą wiadomość e-mail z listą wszystkich zadań, które zakończyły się niepowodzeniem, zamiast wiadomości e-mail dla każdej awarii
  • możesz dołączyć do wiadomości datę uruchomienia i czas działania, ponieważ wiadomość e-mail może nie zostać wysłana lub odebrana wystarczająco szybko, aby dokładnie określić, kiedy zadanie faktycznie się nie powiodło (nie uwzględniłem go tutaj, ponieważ ich straszne wybory typu danych uczyń formatowanie tego typu królewską PITA)
  • prawdopodobnie po pewnym czasie będziesz chciał wyczyścić stare wiersze, więc może być również pożądane polecenie czyszczenia

Jeśli poczta bazy danych nie jest jeszcze skonfigurowana, zapoznaj się z tym samouczkiem .

Możesz także użyć narzędzi innych firm (np. SQL Sentry Event Manager ), które znacznie uprości to. Pełne ujawnienie: Pracuję dla SQL Sentry.

Aaron Bertrand
źródło
0

W oparciu o Twoją edycję byłoby to tylko rozszerzenie odpowiedzi Aarona na same niepowodzenia subskrypcji SSRS (nie tylko zadanie SQL Agent). Proponuję po prostu dodać krok do zadania monitorowania pracy, albo możesz to zrobić jako osobne zadanie.

Aby uzyskać status subskrypcji, wystarczy sprawdzić ReportServer.dbo.ExecutionLog3 widok . StatusKolumna pokaże wszystko, ale rsSuccessna awarie. Po prostu odfiltruj RequestType = 'Subscription'. Będziesz chciał uwzględnić kontrolę czasu, aby nie sprawdzać wszystkich rekordów za każdym razem. Jeśli uruchamiasz zadanie co 15 minut, po prostu sprawdź TimeStartostatnie 15 minut.


źródło