20 letzten Log darstellen

Begonnen von choetzu, 14 November 2017, 08:23:25

Vorheriges Thema - Nächstes Thema

choetzu

Guten Morgen,
Ich möchte gerne die letzten 20 Zeilen im Logfile visualisieren. Wie macht ihr das? Mit dem Widget Filelog schaff ich es nicht.
Lg C
Raspi3, EnOcean, Zwave, Homematic

sinus61

Damit geht das aber, allerdings nur nicht mit dem allgemeinem FHEM-Log.

choetzu

Ja, genau mit dem Fhem-Logfile wärs gewünscht.. das geht gemäss diesem Forumthema nicht mehr: https://forum.fhem.de/index.php/topic,63759.msg684798.html#msg684798

Gibts ne andere Lösung?
Raspi3, EnOcean, Zwave, Homematic

moeweflieg

Hallo choetzu,

habe mir kürzlich folgende Lösung auf FTUI für verschiedene Protokolle meiner Alarmanlage ("Alarmprotokoll","Betriebsprotokoll","Sensorprotokoll","FHEM") zusammengeschustert:
In die 99_myUtils.pm kommt die Sub MyFHEMlog, die Logfiles ausliest und die z.B. für die fhem-log "/opt/fhem/log/fhem.log" je nach Anwahl aus FTUI heraus die ersten, letzen, nächsten oder vorherigen 20 Zeilen ausliest und im Dummy-Device " SYS_LOG_FHEM_INH" als HTML-Text ablegt (Zeilen werden ween Darstellung auf Handy nach 58 Zeichen abgeschnitten).


define SYS_LOG_FHEM_INH dummy
attr SYS_LOG_FHEM_INH room System
define SYS_LOG_FHEM_LAST dummy
attr SYS_LOG_FHEM_LAST room System
define SYS_LOG_FHEM_FILT dummy
attr SYS_LOG_FHEM_FILT room System
attr SYS_LOG_FHEM_INH verbose 0
define SYS_LOG_FHEM_CMD dummy
attr SYS_LOG_FHEM_CMD room System
attr SYS_LOG_FHEM_CMD webCmd last:first:prev:next
define nSYS_LOG_FHEM_CMD notify SYS_LOG_FHEM_CMD { MyFHEMlog("FHEM","R","R") }
attr nSYS_LOG_FHEM_CMD room System
define atSYS_LOG_FHEM_INH at *23:59:59 { MyLogLimiter("FHEM");; }
attr atSYS_LOG_FHEM_INH room System



sub MyFHEMlog {
# Auszug aus dem FHEM-Log
my $log_type   = $_[0]; #"Alarmprotokoll","Betriebsprotokoll","Sensorprotokoll","FHEM"
my $log_mode   = $_[1]; #"first","prev","next","last"
my $log_filter = $_[2];       
my $log_line1  = -1;
my $log_line2  = -1;
my $log_last   = -1;
my $log_width  = 10;
my $log_file   = "";

if ($log_type eq "Alarmprotokoll") {
if ($log_mode eq "R") {
$log_mode  = ReadingsVal("SYS_LOG_ALAR_CMD","state","last");
}
if ($log_filter eq "R") {
$log_filter= ReadingsVal("SYS_LOG_ALAR_FILT","state","");
}
$log_last  = ReadingsVal("SYS_LOG_ALAR_LAST","state","-1");
$log_file  = "/opt/fhem/log/Alarmprotokoll.log";
$log_width = 5;
} elsif ($log_type eq "Betriebsprotokoll") {
if ($log_mode eq "R") {
$log_mode  = ReadingsVal("SYS_LOG_BETR_CMD","state","last");
}
if ($log_filter eq "R") {
$log_filter= ReadingsVal("SYS_LOG_BETR_FILT","state","");
}
$log_last  = ReadingsVal("SYS_LOG_BETR_LAST","state","-1");
$log_file  = "/opt/fhem/log/Betriebsprotokoll.log";
$log_width = 20;
} elsif ($log_type eq "Sensorprotokoll") {
if ($log_mode eq "R") {
$log_mode  = ReadingsVal("SYS_LOG_SENS_CMD","state","last");
}
if ($log_filter eq "R") {
$log_filter= ReadingsVal("SYS_LOG_SENS_FILT","state","");
}
$log_last  = ReadingsVal("SYS_LOG_SENS_LAST","state","-1");
$log_file  = "/opt/fhem/log/Sensorprotokoll.log";
$log_width = 20;
} else {
if ($log_mode eq "R") {
$log_mode  = ReadingsVal("SYS_LOG_FHEM_CMD","state","last");
}
if ($log_filter eq "R") {
$log_filter= ReadingsVal("SYS_LOG_FHEM_FILT","state","");
}
$log_last  = ReadingsVal("SYS_LOG_FHEM_LAST","state","-1");
#my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
#my $monat  = sprintf("%04d-%02d", $year+1900, $mon+1);
#$log_file  = "/opt/fhem/log/fhem-" . $monat . ".log";
$log_file  = "/opt/fhem/log/fhem.log";
$log_width = 20;
}
open(my $fh,"<$log_file") or die ("Couldn't open $log_file: $!");

#Log-Datei einlesen
my $in = -1;
my @Zeilen = ("");
while(<$fh>)
{
push(@Zeilen,$_);
$in = $in + 1;
}
close($fh);

#Log-Datei filtern
if ($log_filter ne "-") {
$in = -1;
my @newZeilen = ("");
foreach my $n (@Zeilen) {
if($n =~ /$log_filter/) {
$in = $in + 1;
push @newZeilen, $n;
}
}
@Zeilen = @newZeilen;
}

#Grenzen des Ergebnis-Log festlegen
if ($log_mode eq "last") {
$log_line2 = $in + 1;
} elsif ($log_mode eq "first") {
$log_line2 = $log_width;
} elsif ($log_mode eq "next") {
$log_line2 = $log_last + $log_width;
} elsif ($log_mode eq "prev") {
$log_line2 = $log_last - $log_width;
}
if ($log_line2 > $in + 1) { $log_line2 = $in + 1; }
$log_line1 = $log_line2 - $log_width + 1;
if ($log_line1 < 1  ) { $log_line1 = 1; $log_line2 = $log_width; }
$log_last = $log_line2;

#Ergebnis-Log zusammenstellen
my $logtxt ='<!DOCTYPE html><html><head><title>FHEM-Log</title></head><body><H6><div align="left">' . "\n";
$logtxt = $logtxt . '<FONT COLOR="#FFFF00">' . $log_file . ': ' . $log_line1 . '-' . $log_line2 . ' von ' . ($in + 1) . '</FONT><br/>' . "\n";
my $i = 0;
foreach my $n (@Zeilen) {
if ($i >= $log_line1 and $i <= $log_line2) {
$n =~ s/\n//;
$n =~ s/;/ /g;
#$n =~ s/:/ /g;
$n = substr $n, 0, 58;
#$lasttxt = $n;
if ($n =~ /larm /) {
$n = '<FONT COLOR="#FF0000">' . $n . '</FONT><br/>' . "\n";
} else {
$n = '<FONT COLOR="#FFFFFF">' . $n . '</FONT><br/>' . "\n";
}
$logtxt = $logtxt . $n;
}
$i = $i + 1;
}
$logtxt = $logtxt . "</div></H6></body></html>\n";

#$lasttxt = substr $lasttxt, 0, 30;
#if ($lasttxt eq "") { $lasttxt = "nothing" }
if ($log_type eq "Alarmprotokoll") {
fhem("set SYS_LOG_ALAR_LAST $log_last");
fhem("set SYS_LOG_ALAR_INH  $logtxt");
} elsif ($log_type eq "Betriebsprotokoll") {
fhem("set SYS_LOG_BETR_LAST $log_last");
fhem("set SYS_LOG_BETR_INH  $logtxt");
} elsif ($log_type eq "Sensorprotokoll") {
fhem("set SYS_LOG_SENS_LAST $log_last");
fhem("set SYS_LOG_SENS_INH  $logtxt");
}
else {
fhem("set SYS_LOG_FHEM_LAST $log_last");
fhem("set SYS_LOG_FHEM_INH  $logtxt");
}

return "0"
}


Die 20 Zeilen werden im FTUI wiefolgt angezeigt (siehe Code), über Buttons kann im Text gescrollt werden, über die erste Textbox ein Filter eingestellt werden und über die zweite Textbox eine Zeile direkt angewählt werden:


<li data-row="128" data-col="1" data-sizex="30" data-sizey="33">
<header>FHEM-Log</header>
<div class="round small"
style="position:absolute;z-index:1001;top:20px;left:10px"
data-type="link"
data-width="40"
data-height="25"
data-color="white"
data-icon="fa-fast-backward"
data-device="AA_COMMAND"
data-set="SYS_LOG_FHEM_CMD:"
data-value="first">
</div>
<div class="round small"
style="position:absolute;z-index:1001;top:355px;left:10px"
data-type="link"
data-width="30"
data-height="25"
data-color="white"
data-icon="fa-backward"
data-device="AA_COMMAND"
data-set="SYS_LOG_FHEM_CMD:"
data-value="prev">
</div>
<div class="medium hbox">
<div class="notransmit w2x"
style="position:absolute;z-index:1001;top:20px;left:70px"
data-width="10"
data-type="input"
data-device="SYS_LOG_FHEM_FILT"
data-get="STATE"
id="sendTask_4">
</div>
<div class="round"
style="position:absolute;z-index:1001;top:18px;left:140px"
data-type="link"
data-width="30"
data-height="25"
data-color="white"
data-background-color="green"
data-icon="fa-feed"
data-device="AA_COMMAND"
data-set="SYS_LOG_FHEM_FILT:"
data-value="#sendTask_4">
</div>
</div>
<div class="medium hbox">
<div class="notransmit w2x"
style="position:absolute;z-index:1001;top:20px;left:185px"
data-width="10"
data-type="input"
data-device="SYS_LOG_FHEM_LAST"
data-get="STATE"
id="sendTask_3a">
</div>
<div class="round"
style="position:absolute;z-index:1001;top:18px;left:255px"
data-type="link"
data-width="30"
data-height="25"
data-color="white"
data-background-color="green"
data-icon="fa-feed"
data-device="AA_COMMAND"
data-set="SYS_LOG_FHEM_LAST:"
data-value="#sendTask_4a">
</div>
</div>
<div class="round small"
style="position:absolute;z-index:1001;top:355px;left:310px"
data-type="link"
data-width="40"
data-height="25"
data-color="white"
data-icon="fa-forward"
data-device="AA_COMMAND"
data-set="SYS_LOG_FHEM_CMD:"
data-value="next">
</div>
<div class="round small"
style="position:absolute;z-index:1001;top:20px;left:310px"
data-type="link"
data-width="40"
data-height="25"
data-color="white"
data-icon="fa-fast-forward"
data-device="AA_COMMAND"
data-set="SYS_LOG_FHEM_CMD:"
data-value="last">
</div>
<div data-type="label"
data-device="SYS_LOG_FHEM_INH"
data-get="state"
class="large left"
style="position:absolute;z-index:1001;top:35px;left:10px">
</div>
</li>


Zur Verfeinerung kann man die Logfiles auch bei Überschreiten einer Zeilenanzahl begrenzen bzw. kürzen und die herausgeschnittenen Zeilen sicher;

sub MyLogLimiter {
# Auszug aus dem FHEM-Log
my $log_type    = $_[0]; #"Alarmprotokoll","Betriebsprotokoll","Sensorprotokoll","Sensorprotokoll","FHEM"
my $log_min     = 5000;
my $log_max     = 10000;
my $log_fileOrg = "";
my $log_fileLim = "";
my $log_fileBak = "";

if ($log_type eq "Alarmprotokoll") {
$log_fileOrg  = "/opt/fhem/log/Alarmprotokoll.log";
} elsif ($log_type eq "Betriebsprotokoll") {
$log_fileOrg  = "/opt/fhem/log/Betriebsprotokoll.log";
} elsif ($log_type eq "Sensorprotokoll") {
$log_fileOrg  = "/opt/fhem/log/Sensorprotokoll.log";
} else {
$log_fileOrg  = "/opt/fhem/log/fhem.log";
}
open(my $fh,"<$log_fileOrg") or die ("Couldn't open $log_fileOrg: $!");

#Log-Datei einlesen
my $in = -1;
my @Zeilen = ("");
while(<$fh>)
{
push(@Zeilen,$_);
$in = $in + 1;
}
close($fh);

#Log-File begrenzen
if ($in >= $log_max) {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
my $today  = sprintf("%04d-%02d-%02d", $year+1900, $mon+1, $mday);
#Sicherungskopie anlagen
$log_fileBak = $log_fileOrg . ".bak." . $today;
copy($log_fileOrg, $log_fileBak) or die "Copy failed: $!";
#Log aufteilen
$log_fileLim = $log_fileOrg . "." . $today;
open(my $fh1,">$log_fileLim") or die ("Couldn't open $log_fileLim: $!");
open(my $fh2,">$log_fileOrg") or die ("Couldn't open $log_fileOrg: $!");
my @Zeilen1 = ("");
my @Zeilen2 = ("");
my $i1 = 0;
foreach my $n1 (@Zeilen) {
if ($i1 <= $log_min) {
print $fh1 $n1;
} else {
print $fh2 $n1;
}
$i1 = $i1 + 1;
}
close($fh1);
close($fh2);
Log 1, "Log begrenzt: $log_fileLim";
}
return "0"
}


Das Dummy-Device leitet die Befehle der Buttons weiter an MyCommands (in 99_myUtils.pm) - wegen Befehlsprüfung leider etwas umständlich geraten -bitte selbbst bei Bedarf kürzen bzw. anpassen.
#-----UserBefehle---------------------------------------------------------
define AA_COMMAND dummy
define nAA_COMMAND notify AA_COMMAND { MyCommands() }

sub MyCommands{
my $aa_command_text    = ReadingsVal("AA_COMMAND","state","");
my ($aa_command_device, $aa_command_state) = split(/:/, $aa_command_text);
my $aa_device_state    = ReadingsVal($aa_command_device,"state","");
my $aa_user            = ReadingsVal("AA_USER","state","");
my $aa_ip              = ReadingsVal("AA_USERIP","state","-");
my $aa_command_exe     = "";
my $aa_command_fullexe = "";

if ($aa_command_text eq "" or $aa_command_state eq "") {
return
}
# Prüfen auf Befehlsberechtigung - DEAKTIVIERT
##if (MyUserRights($aa_user, $aa_command_device, $aa_ip) ne "go") {
## return
##}
if ($aa_command_device eq "fhem-cmd") {
if ($aa_command_state eq "fhem_restart") {
$aa_command_fullexe = "shutdown restart";
} elsif ($aa_command_state eq "system_restart") {
$aa_command_fullexe = "set System.Reboot.Dummy on";
}
} elsif ($aa_command_device =~ /Webcam/) {
if ($aa_command_state eq "caminfoall") {
$aa_command_fullexe = "get $aa_command_device caminfoall";
} elsif ($aa_command_state eq "snapshot") {
$aa_command_fullexe = "set $aa_command_device snap;get $aa_command_device caminfoall";
} elsif ($aa_command_state eq "video") {
$aa_command_fullexe = "set $aa_command_device on 20;get $aa_command_device caminfoall";
} elsif ($aa_command_state eq "sendsnapshot") {
$aa_command_fullexe = "{SendMessage('erwin','m','t','Snapshot von $aa_command_device','LastSnapFilename','')}";
} elsif ($aa_command_state eq "sendvideo") {
$aa_command_fullexe = "{SendMessage('erwin','m','t','Video von $aa_command_device','CamLastRec','')}";
}
Log 1, ("MyCommands: $aa_command_fullexe");
} elsif ($aa_command_state eq "on/off") {
if ($aa_device_state eq "on") {
$aa_command_exe = "off";
} else {
$aa_command_exe = "on";
}
$aa_command_fullexe = "set $aa_command_device $aa_command_exe";
if ($aa_command_device =~ /AA_REC/) {
MyAlarmActions("Betriebsmeldung","$aa_command_device $aa_command_exe");
}
elsif ($aa_command_device eq "AA_MELSIR") {
MyAlarmActions("Betriebsmeldung","Alarmsirene $aa_command_exe");
}
} elsif ($aa_command_device =~ /AA_REC/) {
$aa_command_exe = $aa_command_state;
$aa_command_fullexe = "set $aa_command_device $aa_command_state";
MyAlarmActions("Betriebsmeldung","$aa_command_device: $aa_command_state");
} elsif ($aa_command_state =~ /Speak /) {
$aa_command_exe = $aa_command_state;
$aa_command_fullexe = "set $aa_command_device $aa_command_state";
MyAlarmActions("Betriebsmeldung","Sonos: $aa_command_state");
} elsif ($aa_command_device =~ /ZSTAND/) {
#Log 1, ("MyGetZS: Device: $aa_command_device $aa_command_state");
MyGetZS($aa_command_device, $aa_command_state);
} elsif ($aa_command_device =~ /Pool_Befehl/) {
$aa_device_state    = ReadingsVal("MW",$aa_command_device,"");
if ($aa_device_state eq "1") {
$aa_command_exe = "0";
} else {
$aa_command_exe = "1";
}
$aa_command_fullexe = "setreading MW $aa_command_device $aa_command_exe";
} elsif ($aa_command_device =~ /AA_FEHLALARM/) {
$aa_command_fullexe = "set $aa_command_device $aa_command_state";
} else {
$aa_command_exe = $aa_command_state;
$aa_command_fullexe = "set $aa_command_device $aa_command_state";
}
if ($aa_command_fullexe ne "") {
#Log 1, ("MyCommands: $aa_command_fullexe");
fhem($aa_command_fullexe);
}
return
}





Gruß und viel Erfolg beim Nachbauen (ich hoffe nichts vergessen zu haben!)
moewe

Wuehler

Alternative:

Ein Dummy:
defmod AlarmeLog dummy
attr AlarmeLog readingList log_history


eine Readings-History:
defmod rh_Alarme readingsHistory AlarmeLog:last_log
attr rh_Alarme alwaysTrigger 1
attr rh_Alarme noheading 1
attr rh_Alarme nolinks 1
attr rh_Alarme rows 20


Ein notify zum update des Dummys:
defmod AlarmeLogNotify notify AlarmeLog:linesInTheFile:.* {\
fhem(\
   'define at_update_AlarmeLog_history at +00:00:05 {\
        my $alog=fhem("get rh_Alarme html");;;;\
        $alog =~ s/\;;;;/\;;;;\;;;;/g;;;;\
        fhem("set AlarmeLog log_history ".$alog);;;;\
    }\
');;\
}


und in ftui:

  <div data-type="label" data-device="AlarmeLog" class="medium left-align" data-get="log_history"></div>

choetzu

Zitat von: Wuehler am 16 November 2017, 22:43:23
Alternative:

Ein Dummy:
defmod AlarmeLog dummy
attr AlarmeLog readingList log_history


eine Readings-History:
defmod rh_Alarme readingsHistory AlarmeLog:last_log
attr rh_Alarme alwaysTrigger 1
attr rh_Alarme noheading 1
attr rh_Alarme nolinks 1
attr rh_Alarme rows 20


Ein notify zum update des Dummys:
defmod AlarmeLogNotify notify AlarmeLog:linesInTheFile:.* {\
fhem(\
   'define at_update_AlarmeLog_history at +00:00:05 {\
        my $alog=fhem("get rh_Alarme html");;;;\
        $alog =~ s/\;;;;/\;;;;\;;;;/g;;;;\
        fhem("set AlarmeLog log_history ".$alog);;;;\
    }\
');;\
}


und in ftui:

  <div data-type="label" data-device="AlarmeLog" class="medium left-align" data-get="log_history"></div>


super, herzlichen dank. Kann man das auch für das generelle FHEM Logfile erstellen?
Raspi3, EnOcean, Zwave, Homematic

choetzu

hallo moewe und wuehler

ich habe versucht beide varianten lediglich fürs FHEM-Log zu machen, bin aber kläglich gescheitert.. mittlerweile habe ich soviel rumprobiert, dass ich gar nicht mehr weiss, was ich alles geändert habe. Also nochmals von vorne, Samstag Abend war für die Katz ;)

Wenn ihr ne einfache Variante für einen Laien habt, dann bin ich noch so froh.. Danke.

lg c
Raspi3, EnOcean, Zwave, Homematic