Alarm, wenn ein Job in einer Jobkategorie fehlschlägt

11

Ist es möglich, in SQL Server 2008 eine Warnung einzurichten, die eine E-Mail sendet, wenn ein Auftrag in einer bestimmten Kategorie fehlschlägt?

Ich frage mich, weil ich eine E-Mail einrichten möchte, wenn ein SSRS-Abonnement fehlschlägt - und alle diese Abonnements sind Jobs in der Kategorie Berichtsserver .

BEARBEITEN - Es stellt sich heraus, dass der Job selbst nicht fehlschlägt, wenn ein SSRS-Abonnement fehlschlägt. Daher gilt meine Frage nicht für die Verwendung der SSRS-Abonnementüberwachung. Ich würde jedoch gerne wissen, welche anderen Jobs wir in unserer Umgebung ausführen

JHFB
quelle
Scheitert zumindest ein Schritt? Meine Antwort unten befasst sich mit Jobs in der Kategorie "Berichtsserver". Wenn Sie jedoch nur alle Jobs möchten, können Sie den gesamten AND EXISTSTeil des Jobs entfernen INSERT/SELECT. Und wahrscheinlich den Namen ReportServerJob_FailQueuein etwas allgemeineres ändern . :-)
Aaron Bertrand
Leider schlägt kein Schritt fehl - aber ich bin zuversichtlich, dass ich mir einen anderen Überwachungsmechanismus ausdenken kann!
JHFB

Antworten:

10

Sie können einen Job erstellen, der jede Minute (oder wie oft Sie möchten) die Tabelle msdb.dbo.sysjobhistory überprüft. Möglicherweise möchten Sie eine Warteschlangentabelle implementieren, damit Sie die Nachricht für einen einzelnen Instanzfehler immer nur einmal senden.

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

Ihr Code, den Sie in einem Job planen können, lautet dann:

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

Nun gehe ich davon aus, dass Sie für jeden Fehler eine individuelle E-Mail senden möchten, sodass dies auch Teil des Jobs sein kann (oder Teil eines anderen Jobs, obwohl dies nicht unbedingt sinnvoll ist):

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;

Es gibt auch einige andere Optionen:

  • Ziehen Sie sysjobhistory.message ein
  • Schauen Sie sich einzelne Schritte an, die fehlgeschlagen sind
  • Senden Sie eine Nachricht für einen Auftrag nur einmal in n Minuten / Stunden, selbst wenn mehrere Fehler vorliegen
  • Senden Sie eine einzelne E-Mail mit einer Liste aller fehlgeschlagenen Jobs anstelle einer E-Mail für jeden Fehler
  • Möglicherweise möchten Sie run_date und run_time in die Nachricht aufnehmen, da die E-Mail möglicherweise nicht schnell genug gesendet oder empfangen wird, um genau zu messen, wann der Auftrag tatsächlich fehlgeschlagen ist (ich habe sie hier nicht aufgenommen, weil sie schreckliche Datentypen ausgewählt haben Formatierung dieses Materials zu einer königlichen PITA machen)
  • Möglicherweise möchten Sie alte Zeilen nach einiger Zeit bereinigen, daher ist möglicherweise auch ein Bereinigungsbefehl erwünscht

Wenn Database Mail noch nicht eingerichtet ist, lesen Sie bitte dieses Tutorial .

Sie können auch Tools von Drittanbietern (z. B. SQL Sentry Event Manager ) verwenden, die dies erheblich vereinfachen. Vollständige Offenlegung: Ich arbeite für SQL Sentry.

Aaron Bertrand
quelle
0

Basierend auf Ihrer Bearbeitung wäre dies nur eine Erweiterung von Aarons Antwort in Bezug auf SSRS-Abonnementfehler selbst (nicht nur den SQL Agent-Job). Ich würde vorschlagen, nur einen Schritt zum Jobüberwachungsjob hinzuzufügen, oder Sie könnten dies als separaten Job insgesamt tun.

Um den Abonnementstatus zu erhalten, überprüfen Sie einfach die ReportServer.dbo.ExecutionLog3 Ansicht . In der StatusSpalte wird alles andere als rsSuccessbei Fehlern angezeigt. Filtern Sie einfach nach RequestType = 'Subscription'. Sie sollten eine Zeitprüfung einschließen, damit Sie nicht jedes Mal alle Datensätze überprüfen. Wenn Sie den Job alle 15 Minuten ausführen, überprüfen Sie ihn in TimeStartden letzten 15 Minuten.


quelle