Hintergrund

LOGINventory bereinigt den Changelog (_ChangeLog-Tabelle) standardmäßig automatisch. Der eingebaute Cleanup-Task läuft täglich um 01:00 Uhr und löscht alle Changelog-Einträge, die älter als der konfigurierte Schwellenwert sind (Standard: 90 Tage).

Dabei gibt es keine Möglichkeit, einzelne Entitäten von der Bereinigung auszunehmen. Entweder wird der gesamte Changelog bereinigt oder gar nicht.



Lösung

Dieses Paket ersetzt den eingebauten Changelog-Cleanup durch eine kundenspezifische Stored Procedure, die eine Ausschlusstabelle unterstützt. Damit können gezielt einzelne Entitäten oder ganze Entitätstypen von der Bereinigung ausgenommen werden.

Komponenten

KomponenteBeschreibung
_ChangeLogCleanupExclusionsTabelle für Ausschlussregeln
usp_CleanupChangeLogStored Procedure für die Bereinigung
SQL Server Agent JobTäglich automatisierte Ausführung



Einrichtung (Schritt für Schritt)

Schritt 1: LOGINventory Changelog-Bereinigung deaktivieren

In der LOGINventory Management Console (LMC):

  1. Öffnen: Einstellungen > LOGINventory > Datenpflege
  2. Changelog bereinigen deaktivieren (Haken entfernen)
  3. Speichern
Hinweis: Die separate Option Benutzer-Changelog bereinigen (DoEraseUserHistory) bleibt davon unberührt und sollte aktiviert bleiben. Diese bereinigt ausschließlich UserAccount-Einträge und ist aus Datenschutzgründen separat geregelt.

Alternativ direkt in der Datenbank:

UPDATE dbo._Settings SET Value = 'False' WHERE Name = 'DoEraseChangeLogEntries';


Schritt 2: SQL-Script ausführen

Das Script Cleanup_ChangeLog_WithExclusions.sql im SQL Server Management Studio öffnen und ausführen. Es erstellt:

  • Die Tabelle _ChangeLogCleanupExclusions
  • Die Stored Procedure usp_CleanupChangeLog
Den Datenbanknamen in der USE-Anweisung ggf. anpassen (Standard: LOGINventory).

Schritt 3: Ausschlüsse konfigurieren

Einträge in _ChangeLogCleanupExclusions einfügen, um Entitäten auszuschließen. Felder die NULL sind, wirken als Wildcard (= alle Werte).


Schritt 4: Automatisierung einrichten


Option A: SQL Server Agent (Standard/Enterprise Edition)

Den auskommentierten Block am Ende des SQL-Scripts einkommentieren und ausführen. Der Job läuft täglich um 01:30 Uhr (nach dem LOGINventory-eigenen Maintenance-Fenster).


Option B: Windows Aufgabenplanung (Express Edition)

Da SQL Server Express keinen Agent hat, kann stattdessen die Windows Aufgabenplanung mit sqlcmd verwendet werden:

sqlcmd -S .\LOGINventory -d LOGINventory -Q "EXEC dbo.usp_CleanupChangeLog @RetentionDays = 90"

Als geplante Aufgabe täglich um 01:30 ausführen.


Ausschluss-Beispiele

Benutzerdefinierte Gerätefelder (Device.Custom) ausschließen

Alle Changelog-Einträge für AssetCustom-Entitäten dauerhaft aufbewahren:

INSERT INTO dbo._ChangeLogCleanupExclusions (EntityType, Comment)
VALUES ('AssetCustom', 'Benutzerdefinierte Gerätefelder - Changelog aufbewahren');

Ein bestimmtes Gerät ausschließen

Nur das Gerät mit EntityId 42 schützen:

INSERT INTO dbo._ChangeLogCleanupExclusions (EntityType, EntityId, Comment)
VALUES ('Device', 42, 'Server XY - Changelog aufbewahren');

Alle Untereinträge eines Masters ausschließen

Alle Changelog-Einträge die einem bestimmten Master-Objekt zugeordnet sind:

INSERT INTO dbo._ChangeLogCleanupExclusions (MasterType, MasterId, Comment)
VALUES ('Device', 100, 'Alle Changelog-Einträge von Device 100 und dessen Unterentitäten');

Mehrere Entitätstypen ausschließen

INSERT INTO dbo._ChangeLogCleanupExclusions (EntityType, Comment) VALUES
('AssetCustom',     'Benutzerdefinierte Gerätefelder aufbewahren'),
('Device',          'Geräte-Changelog aufbewahren'),
('SoftwareProduct', 'Software-Changelog aufbewahren');
Hinweis: UserAccount-Einträge müssen hier nicht ausgeschlossen werden. Diese werden von der SP grundsätzlich ignoriert und weiterhin durch den eingebauten LOGINventory-Cleanup (DoEraseUserHistory) separat aus Datenschutzgründen bereinigt.


EntityId und MasterId ermitteln

Die IDs für die Ausschlussliste können über den Changelog selbst ermittelt werden:

-- Alle Entitätstypen im Changelog anzeigen (mit Anzahl)
SELECT EntityType, COUNT(*) AS Anzahl
FROM dbo._ChangeLog
GROUP BY EntityType
ORDER BY Anzahl DESC;

-- Bestimmtes Gerät anhand des Labels suchen
SELECT DISTINCT EntityType, EntityId, EntityLabel
FROM dbo._ChangeLog
WHERE EntityLabel LIKE '%servername%';

-- Alle Master-Typen anzeigen
SELECT MasterType, COUNT(*) AS Anzahl
FROM dbo._ChangeLog
WHERE MasterType IS NOT NULL
GROUP BY MasterType
ORDER BY Anzahl DESC;


Testen (Dry Run)

Vor der ersten produktiven Ausführung kann die Prozedur im Testmodus ausgeführt werden:

-- Dry Run: zeigt was gelöscht werden würde, löscht aber nichts
EXEC dbo.usp_CleanupChangeLog @RetentionDays = 90, @DryRun = 1;

Die Ausgabe zeigt:

  • Anzahl der Einträge älter als der Stichtag
  • Davon ausgeschlossene Einträge
  • Verbleibende Einträge die gelöscht würden


Ausschluss entfernen

-- Einzelnen Ausschluss entfernen
DELETE FROM dbo._ChangeLogCleanupExclusions WHERE Id = 1;

-- Alle Ausschlüsse anzeigen
SELECT * FROM dbo._ChangeLogCleanupExclusions;


Technische Details

Matching-Logik

Ein Changelog-Eintrag ist ausgeschlossen, wenn mindestens eine Zeile in der Ausschlusstabelle auf ihn zutrifft. Dabei gilt:

  • NULL-Felder in der Ausschlusstabelle matchen auf alle Werte (Wildcard)
  • Gesetzte Felder müssen exakt übereinstimmen
  • Mehrere gesetzte Felder in einer Zeile werden mit AND verknüpft

Beispiel: EntityType = 'AssetCustom', EntityId = NULL schließt alle AssetCustom-Einträge aus.


Betroffene Tabellen

TabelleAktion
_ChangeLogDELETE per Stored Procedure
_ChangeLogDetailsAutomatisch per CASCADE DELETE
_ChangeLogCleanupExclusionsKonfigurationstabelle (wird nur gelesen)


Performance

Die Stored Procedure verwendet NOT EXISTS mit der Ausschlusstabelle. Bei einer kleinen Anzahl von Ausschlussregeln (typisch: < 50 Zeilen) hat dies keinen nennenswerten Einfluss auf die Performance. Bei sehr großen Changelog-Tabellen (> 1 Mio. Einträge) empfiehlt sich ein Index:

CREATE NONCLUSTERED INDEX IX_ChangeLog_Cleanup
ON dbo._ChangeLog ([Timestamp])
INCLUDE (EntityType, EntityId, MasterType, MasterId);