Jasne i ciemne strony baz danych

… w szczególności MS SQL Server ;-)

SQL Server – Listowanie ostatnich N zdarzeń z dziennika zdarzeń (CLR)

Posted by C3PO w dniu 14 lipca 2010


Niedawno pisałem o tym, jak można czytać dzienniki zdarzeń systemu Windows za pomocą funkcji napisanej dla SQL Servera w CLR (patrz tutaj). Jednak podana funkcja ma podstawową wadę – czyta cały dziennik, a to oczywiście może trwaaaaaać :-)

Dlatego spróbowałem nieco zmienić kod C#, by dawało się określić, ile ostatnich wpisów ze wskazanego dziennika chcemy przeczytać. Powstało mi na razie coś takiego (pewnie za moment będzie ewoluować):

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Diagnostics;

public partial class UserDefinedFunctions
{
  [Microsoft.SqlServer.Server.SqlFunction(
      Name = "ufn_clr_GetEventLog",
      FillRowMethodName = "FillEventLogRow",
      TableDefinition = "EntryType nvarchar(50), " +
                        "TimeWritten datetime, " +
                        "Source nvarchar(4000), " +
                        "InstanceId bigint, " +
                        "Category nvarchar(255), " +
                        "Message nvarchar(max)"
  )]
  public static IEnumerable ReadLog(
    SqlString LogName,
    SqlString MachineName,
    SqlInt32 HowMany
  )
  {
    EventLog log = new EventLog(LogName.Value, MachineName.Value);
    int size =
      (log.Entries.Count - HowMany.Value) >= 0 ?
      HowMany.Value :
      log.Entries.Count;
    EventLogEntry[] entries = new EventLogEntry[size];
    int index =
      (log.Entries.Count - HowMany.Value) >= 0 ?
      (log.Entries.Count - HowMany.Value) :
      0;
    for (int i = index; i <= log.Entries.Count - 1; i++)
    {
      entries[i-index] = log.Entries[i];
    }
    return entries;
  } 

  public static void FillEventLogRow(
    Object Obj,
    out SqlString EntryType,
    out SqlDateTime TimeWritten,
    out SqlString Source,
    out SqlInt64 InstanceId,
    out SqlString Category,
    out SqlString Message
  )
  {
    EventLogEntry entry = (EventLogEntry)Obj;
    EntryType = entry.EntryType.ToString();
    TimeWritten = new SqlDateTime(entry.TimeWritten);
    Source = entry.Source;
    InstanceId = new SqlInt64(entry.InstanceId);
    Category = entry.Category;
    Message = entry.Message;
  }
};

Doszedł trzeci parametr funkcji – HowMany, który określa, ile ostatnich wpisów chcemy zwrócić. Reszta to prosta matematyka i liczenie indeksów tablic (mam nadzieję, że nic nie pokpiłem). Zapewne da się to napisać prościej, ale nie jestem programistą .NET, więc poradziłem sobie, jak umiałem :-) Spróbuję jeszcze wydumać, jak zwracać zdarzenia pomiędzy zadanymi datami lub od zadanej daty, ale to już będzie dla mnie nie lada wyzwanie ;-)

Bez projektu Database Project po skompilowaniu do pliku .dll i wczytaniu owego pliku jako assembly (polecenie CREATE ASSEMBLY z opcją PERMISSION_SET ustawioną na UNSAFE) do bazy danych funkcję tworzymy tak:

CREATE FUNCTION [dbo].[ufn_clr_GetEventLog](
  @LogName [nvarchar](4000),
  @MachineName [nvarchar](4000),
  @HowMany [int])
RETURNS  TABLE (
    [EntryType] [nvarchar](50) NULL,
    [TimeWritten] [datetime] NULL,
    [Source] [nvarchar](4000) NULL,
    [InstanceId] [bigint] NULL,
    [Category] [nvarchar](255) NULL,
    [Message] [nvarchar](max) NULL
)
AS
EXTERNAL NAME [DBAToolbox].[UserDefinedFunctions].[ReadLog];
GO

DBAToolbox to nazwa assembly podana w poleceniu CREATE ASSEMBLY.

Przykładowe wywołanie funkcji:

SELECT * FROM dbo.ufn_clr_GetEventLog('System','MojSerwer', 2000);

Przyjemnego przeglądania dzienników życzę :-)

[EDYCJA | 2010-07-21]
A jeżeli chesz posortować rekordy zwracane przez funkcję ufn_clr_GetEventLog malejąco po dacie (od najświeższych wpisów do najstarszych), zastąp linijkę:

entries[i - index] = log.Entries[i];

odpowiednikiem:

entries[size - 1 - i + index] = log.Entries[i];
Reklamy

komentarze 2 to “SQL Server – Listowanie ostatnich N zdarzeń z dziennika zdarzeń (CLR)”

  1. Michał said

    Dziekuję za szybką pomoc :)

  2. Michał said

    Super, działa jak należy!

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

 
%d blogerów lubi to: