2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-25 09:55:38 +00:00

93_DbLog: contrib 5.6.2

git-svn-id: https://svn.fhem.de/fhem/trunk@27105 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2023-01-22 20:00:52 +00:00
parent db66e5bc54
commit 5306857e06

View File

@ -1,5 +1,5 @@
############################################################################################################################################
# $Id: 93_DbLog.pm 26923 2023-01-10 10:28:14Z DS_Starter $
# $Id: 93_DbLog.pm 27082 2023-01-18 22:08:25Z DS_Starter $
#
# 93_DbLog.pm
# written by Dr. Boris Neubert 2007-12-30
@ -8,7 +8,7 @@
# modified and maintained by Tobias Faust since 2012-06-26 until 2016
# e-mail: tobias dot faust at online dot de
#
# redesigned and maintained 2016-2023 by DS_Starter with credits by: JoeAllb, DeeSpe
# redesigned and maintained 2016-2023 by DS_Starter
# e-mail: heiko dot maaz at t-online dot de
#
# reduceLog() created by Claudiu Schuster (rapster) adapted by DS_Starter
@ -38,14 +38,17 @@ no if $] >= 5.017011, warnings => 'experimental::smartmatch';
# Version History intern by DS_Starter:
my %DbLog_vNotesIntern = (
"5.5.12" => "10.01.2023 changed routine _DbLog_SBP_onRun_LogBulk ",
"5.6.2" => "22.01.2023 check Syntax of DbLogValueFn attribute with Log output ",
"5.6.1" => "16.01.2023 rewrite sub _DbLog_SBP_connectDB, rewrite sub DbLog_ExecSQL, _DbLog_SBP_onRun_deleteOldDays ",
"5.6.0" => "11.01.2023 rename attribute 'bulkInsert' to 'insertMode' ",
"5.5.12" => "10.01.2023 changed routine _DbLog_SBP_onRun_LogSequential, edit CommandRef ",
"5.5.11" => "09.01.2023 more code rework / structured subroutines ",
"5.5.10" => "07.01.2023 more code rework (_DbLog_SBP_checkDiscDelpars) and others, use dbh quote in _DbLog_SBP_onRun_LogBulk ".
"5.5.10" => "07.01.2023 more code rework (_DbLog_SBP_checkDiscDelpars) and others, use dbh quote in _DbLog_SBP_onRun_LogSequential ".
"configCheck changed to use only one db connect + measuring the connection time, universal DBHU ",
"5.5.9" => "28.12.2022 optimize \$hash->{HELPER}{TH}, \$hash->{HELPER}{TC}, mode in Define ".
"Forum: https://forum.fhem.de/index.php/topic,130588.msg1254073.html#msg1254073 ",
"5.5.8" => "27.12.2022 two-line output of long state messages, define LONGRUN_PID threshold ",
"5.5.7" => "20.12.2022 cutted _DbLog_SBP_onRun_Log into _DbLog_SBP_onRun_LogArray and _DbLog_SBP_onRun_LogBulk ".
"5.5.7" => "20.12.2022 cutted _DbLog_SBP_onRun_Log into _DbLog_SBP_onRun_LogArray and _DbLog_SBP_onRun_LogSequential ".
"__DbLog_SBP_onRun_LogCurrent, __DbLog_SBP_fieldArrays, some bugfixes, add drivers to configCheck, edit comref ",
"5.5.6" => "12.12.2022 Serialize with Storable instead of JSON, more code rework ",
"5.5.5" => "11.12.2022 Array Log -> may be better error processing ",
@ -147,7 +150,6 @@ sub DbLog_Initialize {
$hash->{ShutdownFn} = "DbLog_Shutdown";
$hash->{AttrList} = "addStateEvent:0,1 ".
"asyncMode:1,0 ".
"bulkInsert:1,0 ".
"commitMode:basic_ta:on,basic_ta:off,ac:on_ta:on,ac:on_ta:off,ac:off_ta:on ".
"cacheEvents:2,1,0 ".
"cacheLimit ".
@ -158,14 +160,13 @@ sub DbLog_Initialize {
"convertTimezone:UTC,none ".
"DbLogSelectionMode:Exclude,Include,Exclude/Include ".
"DbLogType:Current,History,Current/History,SampleFill/History ".
"SQLiteJournalMode:WAL,off ".
"SQLiteCacheSize ".
"dbSchema ".
"defaultMinInterval:textField-long ".
"disable:1,0 ".
"excludeDevs ".
"expimpdir ".
"exportCacheAppend:1,0 ".
"insertMode:1,0 ".
"noSupportPK:1,0 ".
"noNotifyDev:1,0 ".
"showproctime:1,0 ".
@ -174,6 +175,8 @@ sub DbLog_Initialize {
"syncEvents:1,0 ".
"syncInterval ".
"showNotifyTime:1,0 ".
"SQLiteJournalMode:WAL,off ".
"SQLiteCacheSize ".
"traceFlag:SQL,CON,ENC,DBD,TXN,ALL ".
"traceLevel:0,1,2,3,4,5,6,7 ".
"timeout ".
@ -190,6 +193,9 @@ sub DbLog_Initialize {
$hash->{SVG_sampleDataFn} = "DbLog_sampleDataFn";
$hash->{prioSave} = 1; # Prio-Flag für save Reihenfolge, Forum: https://forum.fhem.de/index.php/topic,130588.msg1249277.html#msg1249277
$hash->{AttrRenameMap} = { "bulkInsert" => "insertMode",
};
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; # für Meta.pm (https://forum.fhem.de/index.php/topic,97589.0.html)
return;
@ -404,22 +410,8 @@ sub DbLog_Attr {
return qq{"$aName" is not valid for database model "$hash->{MODEL}"};
}
if( $aName eq 'valueFn' ) {
my %specials= (
"%TIMESTAMP" => $name,
"%LASTTIMESTAMP" => $name,
"%DEVICE" => $name,
"%DEVICETYPE" => $name,
"%EVENT" => $name,
"%READING" => $name,
"%VALUE" => $name,
"%LASTVALUE" => $name,
"%UNIT" => $name,
"%IGNORE" => $name,
"%CN" => $name
);
my $err = perlSyntaxCheck($aVal, %specials);
if($aName =~ /[Vv]alueFn/) {
my ($err, $func) = DbLog_checkSyntaxValueFn ($name, $aVal);
return $err if($err);
}
@ -1236,19 +1228,11 @@ sub DbLog_Log {
my $clim = AttrVal ($name, 'cacheLimit', $dblog_cachedef);
my $ce = AttrVal ($name, 'cacheEvents', 0);
if( $DbLogValueFn =~ m/^\s*(\{.*\})\s*$/s ) { # Funktion aus Device spezifischer DbLogValueFn validieren
$DbLogValueFn = $1;
}
else {
$DbLogValueFn = '';
}
($err, $DbLogValueFn) = DbLog_checkSyntaxValueFn ($name, $DbLogValueFn, $dev_name); # Funktion aus Device spezifischer DbLogValueFn validieren
$DbLogValueFn = '' if($err);
if( $value_fn =~ m/^\s*(\{.*\})\s*$/s ) { # Funktion aus Attr valueFn validieren
$value_fn = $1;
}
else {
$value_fn = '';
}
($err, $value_fn) = DbLog_checkSyntaxValueFn ($name, $value_fn); # Funktion aus Attr valueFn validieren
$value_fn = '' if($err);
eval { # one Transaction
for (my $i = 0; $i < $max; $i++) {
@ -2206,10 +2190,10 @@ sub DbLog_SBP_onRun {
## Event Logging
#########################################################
if ($operation =~ /log_/xs) {
my $bi = $memc->{bi}; # Bulk-Insert 0|1
my $im = $memc->{im}; # Insert-Mode 0|1
if ($bi) {
_DbLog_SBP_onRun_LogBulk ( { subprocess => $subprocess,
if ($im) {
_DbLog_SBP_onRun_LogSequential ( { subprocess => $subprocess,
name => $name,
memc => $memc,
store => $store,
@ -2469,6 +2453,10 @@ return $doNext;
# PrintError - handle attribute tells DBI to call the Perl warn( ) function
# (which typically results in errors being printed to the screen
# when encountered)
#
# For maximum reliability and for robustness against database corruption,
# SQLite should always be run with its default synchronous setting of FULL.
# https://sqlite.org/howtocorrupt.html
###################################################################################
sub _DbLog_SBP_connectDB {
my $paref = shift;
@ -2533,27 +2521,56 @@ sub _DbLog_SBP_connectDB {
if($utf8) {
if($model eq "MYSQL") {
$dbh->{mysql_enable_utf8} = 1;
$dbh->do('set names "UTF8"');
($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, 'set names "UTF8"');
return ($err, q{}) if($err);
}
if($model eq "SQLITE") {
$dbh->do('PRAGMA encoding="UTF-8"');
($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, 'PRAGMA encoding="UTF-8"');
return ($err, q{}) if($err);
}
}
if ($model eq 'SQLITE') {
$dbh->do("PRAGMA temp_store=MEMORY");
$dbh->do("PRAGMA synchronous=FULL"); # For maximum reliability and for robustness against database corruption,
# SQLite should always be run with its default synchronous setting of FULL.
# https://sqlite.org/howtocorrupt.html
my @dos = ("PRAGMA temp_store=MEMORY",
"PRAGMA synchronous=FULL",
"PRAGMA journal_mode=$sltjm",
"PRAGMA cache_size=$sltcs"
);
$dbh->do("PRAGMA journal_mode=$sltjm");
$dbh->do("PRAGMA cache_size=$sltcs");
for my $do (@dos) {
($err, undef) = _DbLog_SBP_dbhDo ($name, $dbh, $do);
return ($err, q{}) if($err);
}
}
return ($err, $dbh);
}
####################################################################################################
# einfaches Sdbh->do, return ERROR-String wenn Fehler bzw. die Anzahl der betroffenen Zeilen
####################################################################################################
sub _DbLog_SBP_dbhDo {
my $name = shift;
my $dbh = shift;
my $sql = shift;
my $info = shift // "simple do statement: $sql";
my $err = q{};
my $rv = q{};
Log3 ($name, 4, "DbLog $name - $info");
eval{ $rv = $dbh->do($sql);
1;
}
or do { $err = $@;
Log3 ($name, 2, "DbLog $name - ERROR - $@");
};
return ($err, $rv);
}
############################################################################
# Datenbank Ping
# ohne alarm (timeout) bleibt ping hängen wenn DB nicht
@ -2592,11 +2609,37 @@ sub _DbLog_SBP_pingDB {
return $bool;
}
############################################################################
# DBH set
# PrintError = 1, RaiseError = 0
############################################################################
sub _DbLog_SBP_dbhPrintError {
my $dbh = shift;
$dbh->{PrintError} = 1;
$dbh->{RaiseError} = 0;
return;
}
############################################################################
# DBH set
# PrintError = 0, RaiseError = 1
############################################################################
sub _DbLog_SBP_dbhRaiseError {
my $dbh = shift;
$dbh->{PrintError} = 0;
$dbh->{RaiseError} = 1;
return;
}
#################################################################
# SubProcess - Log-Routine
# Bulk-Insert
#################################################################
sub _DbLog_SBP_onRun_LogBulk {
sub _DbLog_SBP_onRun_LogSequential {
my $paref = shift;
my $subprocess = $paref->{subprocess};
@ -2715,9 +2758,8 @@ sub _DbLog_SBP_onRun_LogBulk {
$error = __DbLog_SBP_beginTransaction ($name, $dbh, $useta);
if(!$useta) { # generate errstr wenn keine TA
$dbh->{PrintError} = 1;
$dbh->{RaiseError} = 0;
if(!$useta) { # keine Transaktion: generate errstr, keine Ausnahme
_DbLog_SBP_dbhPrintError ($dbh);
}
eval { for my $ds (@ins) {
@ -2728,7 +2770,6 @@ sub _DbLog_SBP_onRun_LogBulk {
Log3 ($name, 2, "DbLog $name - ERROR in >$operation< - ".$sth_ih->errstr);
}
else {
#$rv = 0 if($rv eq "0E0");
$ins_hist += $rv;
}
}
@ -2747,6 +2788,7 @@ sub _DbLog_SBP_onRun_LogBulk {
Log3 ($name, 2, "DbLog $name - Transaction is switched off. Transferred data is lost.");
}
_DbLog_SBP_dbhRaiseError ($dbh);
__DbLog_SBP_rollbackOnly ($name, $dbh, $history);
$ret = {
@ -2759,14 +2801,11 @@ sub _DbLog_SBP_onRun_LogBulk {
__DbLog_SBP_sendToParent ($subprocess, $ret);
$dbh->{PrintError} = 0;
$dbh->{RaiseError} = 1;
return;
};
$dbh->{PrintError} = 0;
$dbh->{RaiseError} = 1;
_DbLog_SBP_dbhRaiseError ($dbh);
__DbLog_SBP_commitOnly ($name, $dbh, $history);
if($ins_hist == $ceti) {
Log3 ($name, 4, "DbLog $name - $ins_hist of $ceti events inserted into table $history".($usepkh ? " using PK on columns $pkh" : ""));
@ -2779,8 +2818,6 @@ sub _DbLog_SBP_onRun_LogBulk {
Log3 ($name, 2, "DbLog $name - WARNING - only ".$ins_hist." of $ceti events inserted into table $history");
}
}
__DbLog_SBP_commitOnly ($name, $dbh, $history);
}
if ($operation eq 'importCachefile') {
@ -2954,11 +2991,14 @@ sub _DbLog_SBP_onRun_LogArray {
$error = __DbLog_SBP_beginTransaction ($name, $dbh, $useta);
eval {
($tuples, $rows) = $sth_ih->execute_array( { ArrayTupleStatus => \@tuple_status } );
};
if(!$useta) { # keine Transaktion: generate errstr, keine Ausnahme
_DbLog_SBP_dbhPrintError ($dbh);
}
if ($@) {
eval { ($tuples, $rows) = $sth_ih->execute_array( { ArrayTupleStatus => \@tuple_status } );
1;
}
or do {
$error = $@;
$nins_hist = $ceti;
@ -2966,18 +3006,31 @@ sub _DbLog_SBP_onRun_LogArray {
if($useta) {
$rowlback = $cdata; # nicht gespeicherte Datensätze nur zurück geben wenn Transaktion ein
__DbLog_SBP_rollbackOnly ($name, $dbh, $history);
Log3 ($name, 4, "DbLog $name - Transaction is switched on. Transferred data is returned to the cache.");
}
else {
__DbLog_SBP_commitOnly ($name, $dbh, $history);
Log3 ($name, 4, "DbLog $name - Transaction is switched off. Some or all of the transferred data will be lost. Note the following information.");
}
}
else {
_DbLog_SBP_dbhRaiseError ($dbh);
__DbLog_SBP_rollbackOnly ($name, $dbh, $history);
$ret = {
name => $name,
msg => $error,
ot => 0,
oper => $operation,
rowlback => $rowlback
};
__DbLog_SBP_sendToParent ($subprocess, $ret);
return;
};
_DbLog_SBP_dbhRaiseError ($dbh);
__DbLog_SBP_commitOnly ($name, $dbh, $history);
}
no warnings 'uninitialized';
@ -2987,7 +3040,7 @@ sub _DbLog_SBP_onRun_LogArray {
next if($status); # $status ist "1" wenn insert ok
Log3 ($name, 4, "DbLog $name - Insert into $history rejected".($usepkh ? " (possible PK violation) " : " ")."- TS: $timestamp[$tuple], Device: $device[$tuple], Reading: $reading[$tuple]");
Log3 ($name, 4, "DbLog $name - Insert into $history rejected".($usepkh ? " (possible PK violation) " : " ")."->\nTS: $timestamp[$tuple], Device: $device[$tuple], Reading: $reading[$tuple]");
$event[$tuple] =~ s/\|/_ESC_/gxs; # escape Pipe "|"
$reading[$tuple] =~ s/\|/_ESC_/gxs;
@ -3273,7 +3326,7 @@ sub __DbLog_SBP_logLogmodes {
my $name = $paref->{name};
my $useta = $paref->{useta};
my $dbh = $store->{dbh};
my $bi = $memc->{bi}; # Bulk-Insert 0|1
my $im = $memc->{im}; # Insert-Mode 0|1
my $DbLogType = $memc->{DbLogType}; # Log-Ziele
my $operation = $memc->{operation} // 'unknown'; # aktuell angeforderte Operation (log, etc.)
@ -3283,7 +3336,7 @@ sub __DbLog_SBP_logLogmodes {
Log3 ($name, 4, "DbLog $name - Operation: $operation");
Log3 ($name, 5, "DbLog $name - DbLogType: $DbLogType");
Log3 ($name, 4, "DbLog $name - AutoCommit: $ac, Transaction: $tm");
Log3 ($name, 4, "DbLog $name - Insert mode: ".($bi ? "Bulk" : "Array"));
Log3 ($name, 4, "DbLog $name - Insert mode: ".($im ? "Sequential" : "Array"));
return;
}
@ -3374,26 +3427,22 @@ sub _DbLog_SBP_onRun_deleteOldDays {
my $st = [gettimeofday]; # SQL-Startzeit
if(defined ($cmd)) {
eval { $numdel = $dbh->do($cmd);
1;
}
or do { $error = $@;
Log3 ($name, 2, "DbLog $name - Error table $history - $error");
(my $err, $numdel) = _DbLog_SBP_dbhDo ($name, $dbh, $cmd);
if ($err) {
$dbh->disconnect();
delete $store->{dbh};
$ret = {
name => $name,
msg => $error,
msg => $err,
ot => 0,
oper => $operation
};
__DbLog_SBP_sendToParent ($subprocess, $ret);
return;
};
}
$numdel = 0 if($numdel == 0E0);
$error = __DbLog_SBP_commitOnly ($name, $dbh, $history);
@ -3491,7 +3540,7 @@ return;
# $memc->{arguments} -> $infile
# $memc->{operation} -> 'importCachefile'
# $memc->{DbLogType} -> 'history'
# $memc->{bi} -> 0
# $memc->{im} -> 0
#
#################################################################
sub _DbLog_SBP_onRun_importCachefile {
@ -3546,7 +3595,7 @@ sub _DbLog_SBP_onRun_importCachefile {
Log3 ($name, 3, "DbLog $name - $msg");
$memc->{DbLogType} = 'history'; # nur history-Insert !
$memc->{bi} = 0; # Array-Insert !
$memc->{im} = 0; # Array-Insert !
($error, $nins_hist, $rowlback) = _DbLog_SBP_onRun_LogArray ( { subprocess => $subprocess,
name => $name,
@ -4186,32 +4235,6 @@ sub __DbLog_SBP_disconnectOnly {
return $err;
}
#################################################################
# erstellt SQL für Insert Daten in die HISTORY! Tabelle
#################################################################
sub __DbLog_SBP_sqlInsHistory {
my $table = shift;
my $model = shift;
my $usepkh = shift;
my $sql;
if ($usepkh && $model eq 'MYSQL') {
$sql = "INSERT IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
}
elsif ($usepkh && $model eq 'SQLITE') {
$sql = "INSERT OR IGNORE INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
}
elsif ($usepkh && $model eq 'POSTGRESQL') {
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
}
else { # ohne PK
$sql = "INSERT INTO $table (TIMESTAMP, DEVICE, TYPE, EVENT, READING, VALUE, UNIT) VALUES ";
}
return $sql;
}
#################################################################
# erstellt Statement Handle für Insert Daten in die
# angegebene Tabelle
@ -4453,7 +4476,7 @@ sub DbLog_SBP_sendLogData {
$memc->{nsupk} = AttrVal ($name, 'noSupportPK', 0);
$memc->{tl} = AttrVal ($name, 'traceLevel', 0);
$memc->{tf} = AttrVal ($name, 'traceFlag', 'SQL');
$memc->{bi} = AttrVal ($name, 'bulkInsert', 0);
$memc->{im} = AttrVal ($name, 'insertMode', 0);
$memc->{verbose} = AttrVal ($name, 'verbose', 3);
$memc->{operation} = $oper;
@ -4492,7 +4515,7 @@ sub DbLog_SBP_sendCommand {
$memc->{nsupk} = AttrVal ($name, 'noSupportPK', 0);
$memc->{tl} = AttrVal ($name, 'traceLevel', 0);
$memc->{tf} = AttrVal ($name, 'traceFlag', 'SQL');
$memc->{bi} = AttrVal ($name, 'bulkInsert', 0);
$memc->{im} = AttrVal ($name, 'insertMode', 0);
$memc->{verbose} = AttrVal ($name, 'verbose', 3);
$memc->{operation} = $oper;
$memc->{arguments} = $arg;
@ -5012,7 +5035,8 @@ sub DbLog_ExecSQL {
Log3 ($name, 4, "DbLog $name - Backdoor executing: $sql");
my $sth = DbLog_ExecSQL1($hash, $dbh, $sql);
($err, my $sth) = _DbLog_SBP_dbhDo ($name, $dbh, $sql);
$sth = 0 if($err);
__DbLog_SBP_commitOnly ($name, $dbh);
__DbLog_SBP_disconnectOnly ($name, $dbh);
@ -5020,24 +5044,6 @@ sub DbLog_ExecSQL {
return $sth;
}
sub DbLog_ExecSQL1 {
my $hash = shift;
my $dbh = shift;
my $sql = shift;
my $name = $hash->{NAME};
my $sth;
eval { $sth = $dbh->do($sql); };
if($@) {
Log3 ($name, 2, "DbLog $name - ERROR: $@");
return 0;
}
return $sth;
}
################################################################
#
# GET Funktion
@ -5944,25 +5950,25 @@ sub DbLog_configcheck {
### Check Betriebsmodus
#######################################################################
my $mode = $hash->{MODE};
my $bi = AttrVal($name, 'bulkInsert', 0);
my $im = AttrVal($name, 'insertMode', 0);
my $sfx = AttrVal("global", 'language', 'EN');
$sfx = $sfx eq "EN" ? "" : "_$sfx";
$check .= "<u><b>Result of insert mode check</u></b><br><br>";
if (!$bi) {
$bi = "Array";
$check .= "Insert mode of DbLog-device $name is: $bi <br>";
$check .= "Rating: ".$ok."<br>";
$rec = "Setting attribute \"bulkInsert\" to \"1\" may result a higher write performance in most cases. ";
$rec .= "Feel free to try this mode.";
}
else {
$bi = "Bulk";
$check .= "Insert mode of DbLog-device $name is: $bi <br>";
if (!$im) {
$im = "Array";
$check .= "Insert mode of DbLog-device $name is: $im <br>";
$check .= "Rating: ".$ok."<br>";
$rec = "settings o.k.";
}
else {
$im = "Sequential";
$check .= "Insert mode of DbLog-device $name is: $im <br>";
$check .= "Rating: ".$ok."<br>";
$rec = qq(Setting attribute "insertMode" to "0" (or delete it) may result a higher write performance in most cases. );
$rec .= "Feel free to try this mode.";
}
$check .= "<b>Recommendation:</b> $rec <br><br>";
### Check Plot Erstellungsmodus
@ -7054,6 +7060,44 @@ sub DbLog_checkUsePK {
return ($upkh,$upkc,$pkh,$pkc);
}
################################################################
# Syntaxcheck von Attr valueFn und DbLogValueFn
# Rückgabe von Error oder der gesäuberten Funktion
################################################################
sub DbLog_checkSyntaxValueFn {
my $name = shift;
my $func = shift;
my $devname = shift // q{};
my $err = q{};
if ($func !~ m/^\s*(\{.*\})\s*$/s) {
return "Error while syntax checking. The function has to be enclosed by curly brackets.";
}
my %specials= (
"%TIMESTAMP" => $name,
"%LASTTIMESTAMP" => $name,
"%DEVICE" => $name,
"%DEVICETYPE" => $name,
"%EVENT" => $name,
"%READING" => $name,
"%VALUE" => $name,
"%LASTVALUE" => $name,
"%UNIT" => $name,
"%IGNORE" => $name,
"%CN" => $name
);
$err = perlSyntaxCheck ($func, %specials);
Log3 ($name, 1, "DbLog $name - Syntaxcheck <$devname> attribute DbLogValueFn: \n".$err) if($err && $devname);
$func =~ s/^\s*(\{.*\})\s*$/$1/s;
return ($err, $func);
}
################################################################
# Routine für FHEMWEB Detailanzeige
################################################################
@ -7551,13 +7595,13 @@ sub DbLog_setVersionInfo {
if($modules{$type}{META}{x_prereqs_src} && !$hash->{HELPER}{MODMETAABSENT}) { # META-Daten sind vorhanden
$modules{$type}{META}{version} = "v".$v; # Version aus META.json überschreiben, Anzeige mit {Dumper $modules{DbLog}{META}}
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbLog.pm 26923 2022-12-29 10:28:14Z DS_Starter $ im Kopf komplett! vorhanden )
if($modules{$type}{META}{x_version}) { # {x_version} ( nur gesetzt wenn $Id: 93_DbLog.pm 27082 2023-01-18 22:08:25Z DS_Starter $ im Kopf komplett! vorhanden )
$modules{$type}{META}{x_version} =~ s/1\.1\.1/$v/xsg;
}
else {
$modules{$type}{META}{x_version} = $v;
}
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbLog.pm 26923 2022-12-29 10:28:14Z DS_Starter $ im Kopf komplett! vorhanden )
return $@ unless (FHEM::Meta::SetInternals($hash)); # FVERSION wird gesetzt ( nur gesetzt wenn $Id: 93_DbLog.pm 27082 2023-01-18 22:08:25Z DS_Starter $ im Kopf komplett! vorhanden )
if(__PACKAGE__ eq "FHEM::$type" || __PACKAGE__ eq $type) {
# es wird mit Packages gearbeitet -> Perl übliche Modulversion setzen
# mit {<Modul>->VERSION()} im FHEMWEB kann Modulversion abgefragt werden
@ -8357,8 +8401,7 @@ return;
<tr><td> </td><td>In principle, the data is immediately available in the database. </td></tr>
<tr><td> </td><td>Very little to no data is lost when FHEM crashes. </td></tr>
<tr><td> </td><td><b>Disadvantages:</b> </td></tr>
<tr><td> </td><td>The data is only short cached and will be lost if the database is unavailable or malfunctions. </td></tr>
<tr><td> </td><td>Alternative storage in the file system is not supported. </td></tr>
<tr><td> </td><td>An alternative storage in the file system (in case of database problems) is not supported. </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> 1 - </td><td><b>Asynchroner Log-Modus.</b> The data to be logged is first cached in a memory cache and written to the database </td></tr>
<tr><td> </td><td>depending on a <a href="#DbLog-attr-syncInterval">time interval</a> or <a href="#DbLog-attr-cacheLimit">fill level</a> of the cache. </td></tr>
@ -8376,25 +8419,6 @@ return;
</ul>
<br>
<ul>
<a id="DbLog-attr-bulkInsert"></a>
<li><b>bulkInsert</b>
<ul>
<code>attr &lt;device&gt; bulkInsert [1|0] </code><br><br>
Toggles the insert mode between "Array" and "Bulk". <br>
The bulk mode leads to a considerable performance increase when inserting a large number of data records into the
history table, especially in asynchronous mode.
To get the full performance increase, in this case the attribute "DbLogType" should <b>not</b> contain the
current table. <br>
In contrast, the "Array" mode has the advantage over "Bulk" that faulty data records are extracted and reported in the
log file. <br>
(default: 0=Array)
</ul>
</ul>
</li>
<br>
<ul>
<a id="DbLog-attr-commitMode"></a>
<li><b>commitMode</b>
@ -8872,6 +8896,30 @@ attr SMA_Energymeter DbLogValueFn
</ul>
<br>
<ul>
<a id="DbLog-attr-insertMode"></a>
<li><b>insertMode</b>
<ul>
<code>attr &lt;device&gt; insertMode [1|0] </code><br><br>
Toggles the insert mode of the database interface. <br><br>
<ul>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> 0 - </td><td>The data is passed as an array to the database interface. </td></tr>
<tr><td> </td><td>It is in most cases the most performant way to insert a lot of data into the database at once. </td></tr>
<tr><td> 1 - </td><td>The records are passed sequentially to the database interface and inserted into the DB. </td></tr>
</table>
</ul>
<br>
(default: 0)
</ul>
</ul>
</li>
<br>
<ul>
<a id="DbLog-attr-noNotifyDev"></a>
<li><b>noNotifyDev</b>
@ -10018,8 +10066,7 @@ attr SMA_Energymeter DbLogValueFn
<tr><td> </td><td>Die Daten stehen im Prinzip sofort in der Datenbank zur Verfügung. </td></tr>
<tr><td> </td><td>Bei einem Absturz von FHEM gehen sehr wenige bis keine Daten verloren. </td></tr>
<tr><td> </td><td><b>Nachteile:</b> </td></tr>
<tr><td> </td><td>Die Daten werden nur kurz zwischengespeichert und gehen verloren wenn die Datenbank nicht verfügbar ist </td></tr>
<tr><td> </td><td>oder fehlerhaft arbeitet. Eine alternative Speicherung im Filesystem wird nicht unterstützt. </td></tr>
<tr><td> </td><td>Eine alternative Speicherung im Filesystem (bei Datenbankproblemen) wird nicht unterstützt. </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> </td><td> </td></tr>
<tr><td> 1 - </td><td><b>Asynchroner Log-Modus.</b> Die zu loggenden Daten werden zunächst in einem Memory Cache zwischengespeichert </td></tr>
@ -10038,24 +10085,6 @@ attr SMA_Energymeter DbLogValueFn
</ul>
<br>
<ul>
<a id="DbLog-attr-bulkInsert"></a>
<li><b>bulkInsert</b>
<ul>
<code>attr &lt;device&gt; bulkInsert [1|0] </code><br><br>
Schaltet den Insert-Modus zwischen "Array" und "Bulk" um. <br>
Der Bulk Modus führt beim Insert von sehr vielen Datensätzen in die history-Tabelle zu einer erheblichen
Performancesteigerung vor allem im asynchronen Mode. Um die volle Performancesteigerung zu erhalten, sollte in
diesem Fall das Attribut "DbLogType" <b>nicht</b> die current-Tabelle enthalten. <br>
Demgegenüber hat der Modus "Array" gegenüber "Bulk" den Vorteil, dass fehlerhafte Datensätze extrahiert und im
Logfile reported werden. <br>
(default: 0=Array)
</ul>
</ul>
</li>
<br>
<ul>
<a id="DbLog-attr-cacheEvents"></a>
<li><b>cacheEvents</b>
@ -10553,6 +10582,30 @@ attr SMA_Energymeter DbLogValueFn
</ul>
<br>
<ul>
<a id="DbLog-attr-insertMode"></a>
<li><b>insertMode</b>
<ul>
<code>attr &lt;device&gt; insertMode [1|0] </code><br><br>
Schaltet den Insert-Modus der Datenbankschnittstelle um. <br><br>
<ul>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> 0 - </td><td>Die Daten werden als Array der Datenbankschnittstelle übergeben. </td></tr>
<tr><td> </td><td>Es ist in den meisten Fällen der performanteste Weg viele Daten auf einmal in die Datenbank einzufügen. </td></tr>
<tr><td> 1 - </td><td>Die Datensätze werden sequentiell der Datenbankschnittstelle übergeben und in die DB eingefügt. </td></tr>
</table>
</ul>
<br>
(default: 0)
</ul>
</ul>
</li>
<br>
<ul>
<a id="DbLog-attr-noNotifyDev"></a>
<li><b>noNotifyDev</b>