Hey!
Kurze Frage: Es gibt derzeit keine (bequeme) Möglichkeit je Device eine unterschiedliche Aufbewahrungszeit in DBlog zu definieren? Das einzige was ich gerade vor Augen habe wäre über DBREP timeOlderThan // allowDeletion 1 und die selektion über regex mit device? Man müsste da also mehrere dbrep Instanzen aufmachen, wenn man unterschiedliche Vorhaltezeiten braucht? Das wäre bei vielen Devices aber dann vor allem wegen der selektion über das attr "device" sehr unübersichtlich. Ich hab bei mir beispielsweise 934 Devices, bei denen Werte in der DB gespeichert werden.
Ich hätte gerne, dass man die Vorhaltezeit als userattr in jedem Device einzeln angeben kann, so dass diese dann bei gesetztem Wert automatisch nach Ablauf dieses Zeitraums gelöscht würden. Bevor ich mir jetzt hier aber was zusammenbaue frage ich lieber nochmal nach, ob ich das nicht ggf. einfach nur übersehen habe.
Zur Zeit gibt es eine solche Möglichkeit nicht "Out of the Box".
Vorstellbar wäre aber das Feld EVENT dafür zu benutzen. Dafür könnte man in dem DbLog Attr valueFn den Feldinhalt entsprechend setzen.
Prinzipvorgehen, kein Codebeispiel!:
{ if (defined $AufbewZeit->{Device}) {
$EVENT = $UnixZeit + $AufbewZeit->{Device};
}
else {
$EVENT = $UnixZeit + 5184000 # default Aufbewahrung 60 Tage
}
}
Dabei ist $AufbewZeit{Device} ein Hash den man sich in einer 99_myUtils hinterlegen und zentral pflegen kann:
my $AufbewZeit= {
Dev1 => 1000,
Dev2 => 2000,
Dev3 => 3000,
Dev4 => 4000,
Dev5 => 5000,
};
Ich vergaß noch zusätzlich zu erwähnen, es ginge natürlich auch über ein userAttr (z.B. retentionPeriod).
Das userAttr muß man dann in jedem Device setzen, oder es zieht der Default:
{
$EVENT = $UnixZeit + AttrVal ($name, 'retentionPeriod', 5184000);
}
Mit DbRep lässt man sich später regelmäßig ein sqlCmd laufen welches alle Datensätze mit EVENT > aktueller Unixzeit löscht.
Das Verfahren wäre m.M. nach leicht umsetzbar, einziger Haken ist, dass das EVENT Feld momentan zwar mit Länge 0 ausgeblendet, aber nicht modifiziert beschrieben werden kann. Dazu müßte ich das Attr valueFn noch mehr öffnen.
Das ist sicher nur ein möglicher Weg. Aber wenn dir das gefallen sollte, würde ich demnächst (kommende Woche) DbLog anpassen können.
PS: Warum stellst du die Frage nicht in "Automatisierung"? Das wäre das richtige DbLog-Forum und das hier ist sicher keine Anfängerlösung.
LG,
Heiko
Dein Vorschlag über ein Attribut wie z.b. "retentionPeriod" gefällt mir. Der erste Vorschlag hätte auch wieder den Nachteil, dass es recht unübersichtlich bei vielen Devices würde. Ich finde es viel besser managebar, wenn man dies je Device definieren kann/muss. Ich denke, dass das auch viel einfacher für weniger erfahrende User ist.
Schön wäre es wenn man das userattr auch im DbLog Device definieren kann, was dann der Defaultwert wäre. Wenn der allerdings dann nicht gesetzt ist und auch im jeweiligen Device selbst nichts hinterlegt ist, wäre es gut, wenn nichts passiert - also alles wie gehabt bliebe bzw. nichts gelöscht würde.
Du hast auch recht wegen dem Forum. Ich verschiebe das gleich mal
Ich überlege und teste mal was. Das wird aber vermutlich erst kommende Woche weil ich noch ein wenig relaxe.
Aber ich melde mich hier wieder und stelle dir eine Version zum Test bereit damit das Ergebnis auch dem Anspruch genügt.
BTW ... du kannst dir natürlich auch ein userAttr (z.B. retentionPeriodDef) im DbLog anlegen, welches den Default dann enhält. Die Funktion in userFn wäre dann nur ein wenig anders, z.B.:
{
my $def = AttrVal ($name, 'retentionPeriodDef', 5184000);
$EVENT = $UnixZeit + AttrVal ($name, 'retentionPeriod', $def);
}
Ich bräuchte in dem Fall nur das Attr userFn mehr öffnen und dann kannst du die Lösung sofort umsetzen.
Ein eingebautes Attr in DbLog wäre nicht so gut, weil die Verwendung des EVENT für diesen Zweck eine sehr individuelle Lösung ist. Ansonsten müsste man die Tabellenstruktur um ein Feld erweitern damit es zum Standard wird. Das zieht dann wieder weitere Dinge nach sich usw. und das möchte ich ungern tun.
Das hat mich doch mehr gefesselt als ich wollte. ;)
In meinem contrib (Fußtext) liegt eine V 5.9.4 zum Testen.
Ziehe dir diese Version und FHEM restarten.
Dann ergänze dir im global Device userattr mit "retentionPeriod" damit es in allen Devices vorhanden ist.
Im DbLog Device setzt du den Default:
attr ... retentionPeriod 2592000
Und in jedem relevanten Device den Wert deiner Wahl.
Im DbLog Device setzt du nun noch:
attr ... valueFn {
my $def = AttrVal ($NAME, 'retentionPeriod', 99999999999);
$EVENT = int (time) + AttrVal ($DEVICE, 'retentionPeriod', $def);
}
Ergänzend kannst das Feld EVENT mit colEvent = 50 begrenzen.
Das war es schon. Es wird zunächst der Default aus $NAME, dem DbLog Device, gelesen. Wenn es den nicht gibt gilt 99999999999, de facto unbegrenzt.
Dann wird in jedem zu schreibenden Datensatz EVENT mit dem Attributwert retentionPeriod des $DEVICE (Quellendevice) ersetzt oder der zuvor ermittelte Default verwendet.
Damit das ganze problemlos später mit der DbRep Löschung klappt, müsstest du vorher noch alle EVENT in den bisher vorhandenen Datensätzen in der DB mit einem Default Wert updaten mit einem passende SQL oder Tool.
Probier mal ein bisschen. Alles weitere dann später.
EDIT: int (time) statt time() ist besser denke ich.
Grüße,
Heiko
top! das ist aber auch ein wirklich nützliches feature (finde ich). gerade die große instanzen betreiben werden dir - wie ich - dankbar sein ;D
ich probiere das morgen einmal aus und berichte dann
Moin,
damit die Löschvorgänge später performant ablaufen, müsste man sich noch einen Index anlegen.
Geht mit DbRep sqlCmd:
CREATE INDEX Retention_Idx ON `history` (EVENT);
Ein at-Device zum regelmäßigen Löschen mit einem DbRep-Device könnte so aussehen:
define At.fhemtest1.RetentionDel at *23:15:00 {
my $t = int (time);
fhem "set <DbRep-Device> sqlCmd delete from history where EVENT<'$t'";
}
attr At.fhemtest1.RetentionDel disable 0
attr At.fhemtest1.RetentionDel room DbLog
Habe es getestet. Dauert bei mir ca. 2 Minuten um 8Mio Datensätze zu löschen.
Ich hab das jetzt mal ausprobiert. Es funktioniert leider nicht bei mir.
Die 93_DbLog.pm habe ich mir aus deinem contrib gezogen und die FHEM Verzeichnis existierende damit ersetzt. Ich habe dann im global device als userattr rententionPeriod hinzugefügt. Ich habe dann bei einem Device was minütlich geschrieben wird die retentionperiod auf 2592000 / 30 Tage gesetzt. Allerdings wird in der history Tabelle das Feld EVENT nicht beschrieben :(
Kleine Anmerkung: Es wäre stimmiger wenn du retentionPeriod vielleicht DbLogRententionPeriod nennen würdest. Also in der gleichen Syntax wie DbLogExclude / DbLogInclude / DbLogValueFn etc. Hab ich bei mir jedenfalls direkt so benannt.
hat sich glaub ich erledigt. hatte noch colEvent 0 im DbLog Device definiert.. ::)
von unterwegs...
das userattr kannst du ja nennen wie du magst. deswegen findest du retentionPeriod auch nicht im code von dblog. die logik liegt im attr valueFn.
läuft jetzt ja :-) danke soweit schonmal
Ich würde die Version in Kürze einchecken oder gibt es deinerseits noch Hinweise/Bemerkungen zu der Lösung?
Also die Lösung selbst funktioniert bei mir. Man kann natürlich drüber diskutieren, ob man die logik aus dem valueFn nicht im DbLog Modul in einer eigenen Funktion integriert und dafür ein neues Attribut zum an/ausschalten definiert, damit man den Umweg über valueFn nicht gehen muss. Das ist aber allenfalls nice to have. Funktionieren tuts so ja auch
Ist auf jeden Fall ein richtig gutes feature, dass man nun endlich je device unterschiedlich lange Vorhaltezeiten übersichtlich definieren kann. Das hilft mir jedenfalls enorm die Größe der DB zu kontrollieren!
bei der Gelegenheit: Die Spalten in der history table sind alle varchar mit Ausnahme des timestamps. Da bei mir in der Event Spalte nunmehr nur noch Integer Werte gespeichert werden, könnte ich das doch entsprechend ändern? Wäre kleiner und schneller beim selektieren, wenn ich daraus ein "int" machen könnte. Oder erwartet das DbLog Modul an irgendeiner Stelle, dass es varchar sein muss? Doch nur, wenn man $EVENT nicht überschreibt und colspan > 0 gesetzt hat? Sonst wird dort immer VALUE+UNIT reingeschrieben, was ja ohnehin redundant ist?
ZitatMan kann natürlich drüber diskutieren, ob man die logik aus dem valueFn nicht im DbLog Modul in einer eigenen Funktion integriert und dafür ein neues Attribut zum an/ausschalten definiert, damit man den Umweg über valueFn nicht gehen muss.
Hatte ich auch darüber nachgedacht, aber (vorerst) verworfen. EVENT braucht im Prinzip niemand, aber es gibt vllt. schon einge User die sich etwas eigenes mit dem Feld haben einfallen lassen und wenn im Standard, bräuchte man dann auch einen Index dafür usw. usf.
ZitatDa bei mir in der Event Spalte nunmehr nur noch Integer Werte gespeichert werden, könnte ich das doch entsprechend ändern?
Oder erwartet das DbLog Modul an irgendeiner Stelle, dass es varchar sein muss?
Kannst du nach deinem Gusto anpassen. DbLog macht mit EVENT nichts außer die Spalte beschreiben.
Ich kenne auch kein Modul welches EVENT auswertet (heißt natürlich nicht, dass es tatsächlich keines gibt!). Eigentlich ist EVENT m.M. nach überflüssig, aber aus Gründen der historischen Kompatibilität ist und bleibt die Spalte erhalten. Dadurch hat man zumindest den Vorteil ein Feld für individuelle Lösungen zu haben.
Ich checke die V heute Abend ein und ist dann morgen im Update.
LG
Ich habe diese Lösung für Nachnutzer im DbRep-Wiki (https://wiki.fhem.de/wiki/DbRep_-_Reporting_und_Management_von_DbLog-Datenbankinhalten#Eine_Device_spezifische_Aufbewahrungszeit_(Retention_Time)_in_der_Datenbank_realisieren) beschrieben.
Kannst ja mal drüberschauen.