Nebbor: Verfügbarkeitsreport

Hallo zusammen,

habe folgendes Problem: Ich habe eine Tabelle in der der Status von jedem Service eines Hosts archiviert wird. Sobald sich der Status ändert, wird dies in dieser Tabelle dokumentiert. Die Tabelle besteht aus ID, CreateTime, ServiceName, StatusNr.
Für einen Verfügbarkeitsreport muss ich nun berechnen, wie lange ein Service den Status 0, 1, 2 etc hatte.
Dort steht z.B.
ID CreateTime           ServiceName StatusNr
1  08.04.2014 08:00:00  Service 1   0
2  08.04.2014 09:00:00  Service 1   1
3  08.04.2014 10:00:00  Service 1   0
.  ..
.  ..

Man nehme nun an, der Start des Services war 08.04.2014 8 Uhr und am 08.04.2014 11 Uhr mache ich die Abfrage. Das heißt der Service läuft 3 Stunden, davon hatte er 1 Stunde Status 1 und 2 Stunden Status 0. In meinem Report möchte ich dann folgendes stehen haben:
ServiceName Status0 Status1 Status2
Service 1   66%     33%     0%
..          ..

Hoffe ihr könnt mir folgen. Leider habe ich noch keine Idee, dies zu verwirklichen. Habe Grundkenntnisse in SQL bzw. PL/SQL.

Vielen Dank und viele Grüße,

Nebbor

  1. Hello,

    habe folgendes Problem: Ich habe eine Tabelle in der der Status von jedem Service eines Hosts archiviert wird. Sobald sich der Status ändert, wird dies in dieser Tabelle dokumentiert. Die Tabelle besteht aus ID, CreateTime, ServiceName, StatusNr.
    Für einen Verfügbarkeitsreport muss ich nun berechnen, wie lange ein Service den Status 0, 1, 2 etc hatte.
    Dort steht z.B.
    ID CreateTime           ServiceName StatusNr
    1  08.04.2014 08:00:00  Service 1   0
    2  08.04.2014 09:00:00  Service 1   1
    3  08.04.2014 10:00:00  Service 1   0
    .  ..
    .  ..

    Man nehme nun an, der Start des Services war 08.04.2014 8 Uhr und am 08.04.2014 11 Uhr mache ich die Abfrage. Das heißt der Service läuft 3 Stunden, davon hatte er 1 Stunde Status 1 und 2 Stunden Status 0. In meinem Report möchte ich dann folgendes stehen haben:
    ServiceName Status0 Status1 Status2
    Service 1   66%     33%     0%
    ..          ..

    Du registrierst also jede Änderung des Service in der Tabelle, auch wenn er ausfällt?
    Außerdem fehlt noch eine Angabe des Zeitfensters, in dem der Status konsolidiert werden soll.

    Könnte es auch passieren, dass da zwei oder mehr direkt aufeinanderfolgende Zeilen für denselben Service mit demselben Status kommen können?

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bikers-lodge.com
    1. Hi,

      danke für die schnelle Antwort.

      Du registrierst also jede Änderung des Service in der Tabelle, auch wenn er ausfällt?

      Ja.

      Außerdem fehlt noch eine Angabe des Zeitfensters, in dem der Status konsolidiert werden soll.

      Weiß nicht genau, ob ich deine Frage richtig verstehe, aber in der Tabelle gibt es zu jedem Status einen "ersten Eintrag". Das Zeitfenster ist dann also die Zeit zwischen erstem Eintrag und Zeitpunkt der Abfrage.

      Könnte es auch passieren, dass da zwei oder mehr direkt aufeinanderfolgende Zeilen für denselben Service mit demselben Status kommen können?

      Leider passiert das auch, ja.

      Gruß,

      Nebbor

      1. ..aber in der Tabelle gibt es zu jedem Status einen "ersten Eintrag"..

        ...zu jedem Service natürlich... ;)

        1. Hello,

          ..aber in der Tabelle gibt es zu jedem Status einen "ersten Eintrag"..
          ...zu jedem Service natürlich... ;)

          Und die Services haben ja nichts miteinander zu tun, oder?
          Die laufen da einfach parallel und ihre Meldungen werden nur gemeinsam gesammelt.

          Vieviel Services sind es?

          Ich mach mir immer gerne eine grafische Darstellung von solchen Bewegungsdaten-Auswertungen. Liegt jetzt hier vor mir:-)

          Ist mMn ganz einfach, wenn sichergestellt ist, dass die Statu(u)s pro Service nicht gleichzeitig auftreten können. Sagt aber eigentlich der Begriff schon :-O

          Liebe Grüße aus dem schönen Oberharz

          Tom vom Berg

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bikers-lodge.com
          1. Und die Services haben ja nichts miteinander zu tun, oder?
            Die laufen da einfach parallel und ihre Meldungen werden nur gemeinsam gesammelt.

            Genau ;).

            Vieviel Services sind es?

            In meiner Testumgebung zur Zeit ca. 30. Soll später aber auf größeren Umgebungen übertragen werden.

            Ist mMn ganz einfach, wenn sichergestellt ist, dass die Statu(u)s pro Service nicht gleichzeitig auftreten können. Sagt aber eigentlich der Begriff schon :-O

            Also die Statu(u)s können natürlich nicht gleichzeitig auftreten. Jedoch ist die Tabelle eine Art Archiv. Das Problem ist dabei, dass bei einigen Services zum Beispiel bei einem Reboot des Servers der Status erneut in die Tabelle geschrieben wird, egal ob es der selbe Status ist wie vorher.

            1. Hello,

              Also die Statu(u)s können natürlich nicht gleichzeitig auftreten. Jedoch ist die Tabelle eine Art Archiv. Das Problem ist dabei, dass bei einigen Services zum Beispiel bei einem Reboot des Servers der Status erneut in die Tabelle geschrieben wird, egal ob es der selbe Status ist wie vorher.

              Das stört nicht. Schau Dir doch das kleine "Nassi-Shniderman"-Diagramm an.

              Du musst nur einen Aufsetzpunkt in der Tabelle pro Service haben. Daher hatte ich vorgeschlagen, es mit einer Datenbank-Tabelle zu machen und pro Servive eine Abfrage zu fahren ab Aufsetzpunkt. Dann kann man immer dieselbe Strored Routine benutzen und muss einfach nur die Parameter (@Service, @von, @bis) übergeben. Wenn man es ganz gebau wissen muss, muss man die untere Grenze noch um eine genügend große "Epsilon-Umgebung" erweitern, also wenn Startzeitpunkt kleiner ist, als erster Eintrag des selektierten Service, musst Du einen Datensatz rückwärts blicken für den Service, in welchen Status er für diesen Zeitraum gelaufen ist.

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
            2. Hello,

              Wenn Du möchtest, dass hier mal jemand was bastelt, dann solltest Du mal ein paar Musterdaten (so 100 DS) bereitstellen als Datei. Dann steigen die Chancen enorm :-)

              Liebe Grüße aus dem schönen Oberharz

              Tom vom Berg

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
              1. Wenn Du möchtest, dass hier mal jemand was bastelt, dann solltest Du mal ein paar Musterdaten (so 100 DS) bereitstellen als Datei. Dann steigen die Chancen enorm :-)

                Das wäre super..hier eine csv-Datei mit Daten aus der Tabelle..
                http://www.file-upload.net/download-8795865/daten.csv.html

                1. Hello,

                  Wenn Du möchtest, dass hier mal jemand was bastelt, dann solltest Du mal ein paar Musterdaten (so 100 DS) bereitstellen als Datei. Dann steigen die Chancen enorm :-)

                  Das wäre super..hier eine csv-Datei mit Daten aus der Tabelle..
                  http://www.file-upload.net/download-8795865/daten.csv.html

                  Ich habe Dir mal eine Minimallösung mit PHP gebastelt.
                  Dazu gibt es aber noch einiges zu sagen:

                  Zur Zeit filtert die Lösung mur einen Service und berechnet den.
                  Daraus kann man nun eine Funktion machen, vorab in einem Wrapper die Services extrahieren und dann die Liste für jeden gefundenen durchgehen. Die Datei in einem Durchlauf für alle Services durchzugehen, könnte kritisch werden ->

                  Da die Liste unbedingt nach dem Timestamp sortiert sein muss, habe ich diese für _einen_ Service vollständig in den Speicher geladen. Wenn die Datenmenge pro Service aber zu groß wird, geht das nicht mehr.

                  Dass die Anzahl der Services zu groß werden wird, dass man deren Namen nicht mehr im Speicher sammeln kann (steht ja dann jeder nur einmal drin), glaube ich weniger.

                  Außerdem muss die CSV-Datei "sauber" sein! Das bedeutet, keine leeren Zeilen, alle Zeilen haben dieselben Spalten. Man kann auch das abfangen, aber dann wird es langsam aufwändig.

                  Du solltest also eine Einschätzung vornehmen, wieviele Eintragungen pro Service maximal kommen werden. Bereits berechnete Daten sollten in eine Archivdatei ausgelagert werden.

                  Bei heutigen Speichergrößen sind 10MB Dateigröße mit 5 Services nicht zuviel, oder 100MB mit 50 Services, usw., soweit die ungefähr gleich viele Zeilen produzieren...
                  Es geht beim Speicher im Prinzip immer nur um das Sortieren.

                  Wenn die Datei allerdings garantiert nach Datum+Zeit sortiert vorliegt, kann die fast so groß werden, bis Deine Platte platzt. Etwas Platz brauchst Du dann sicherlich noch für die Ergebnisse und das Script :-))

                  Allerdings will man ja auch nicht jedes Mal von vorne anfangen zu rechnen, also würde ich schon "Monatsabschlüsse" machen.

                  Wenn Dir PHP etwas nützt, kann ich Dir das gerne fertig machen. Kleiner Obolus für Strom und Internet wird immer gerne entgegen genommen ;-)

                    
                  <?php   ### logbuch.php ### utf-8  ### ÄÖÜäöü  
                    
                  #*---------------------------------  
                  # Datei nach Datum und Zeit sortiert!  
                  # (alte Zeit) = Startzeit  
                  # n = aktiver Status  
                  #  
                  # |   -> nächster Datensatz  
                  # |   Status[n] += (neue Zeit) - (alte Zeit)  
                  # |   n = neuer Status  
                  # |   (alte Zeit) = (neue Zeit)  
                  #  
                  # Ergebnisse aus Status[x] auslesen  
                  #*---------------------------------  
                    
                    
                  $fp = fopen('daten.csv', 'rb');  
                  $_list = array();  
                    
                  ## erste Zeile mit Überschriften wegschneiden  
                  $_rec = fgetcsv($fp, 0);  
                    
                  $alias = 'server1_check-net-snmp';  
                  #$alias = 'server1_check-net-snmp_disk-io-bytes_device-sda';  
                    
                  $i = 0;  
                  while ($_rec = fgetcsv($fp, 0))  
                  {  
                      if ($_rec[0] === $alias)  
                  	{  
                  		$_list['alias'][$i] = $_rec[0];  
                  		$_list['datetime'][$i] = $_rec[1];  
                  		$_list['timestamp'][$i] = strtotime($_rec[1]);  
                  		$_list['status'][$i] = $_rec[2];  
                          $i++;  
                  	}	  
                  }  
                  fclose($fp);  
                    
                  echo "<pre>\r\n";  
                  echo htmlspecialchars(print_r($_list,1)) . "\r\n";  
                  asort($_list['timestamp'], SORT_NUMERIC);  
                  echo ($key = key($_list['timestamp'])) . ',' . $_list['timestamp'][$key] . "\r\n";  
                  echo "</pre>\r\n";  
                    
                  $_status[0] = 0;  
                  $_status[1] = 0;  
                  $_status[2] = 0;  
                    
                  $time  = $_list['timestamp'][$key];  
                  $stat  = $_list['status'][$key];  
                    
                  # ersten Datensatz (nur Index) löschen:  
                  unset($_list['timestamp'][$i]);  
                    
                  foreach ($_list['timestamp'] as $key => $value)  
                  {  
                  	$_status[$stat] += $value - $time;  
                  	$stat = $_list['status'][$key];  
                  	$time = $value;  
                  }  
                    
                  echo "<pre>\r\n";  
                  echo htmlspecialchars(print_r($_status,1)) . "\r\n";  
                  echo "</pre>\r\n";  
                    
                    
                  ?>  
                    
                  
                  

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bikers-lodge.com
      2. Hello,

        ok, das Ganze ist eine Art "Gruppenwechsel".
        Ob man das nun sinnvoll mit einer DB-Abfrage lösen kann, weiß ich noch nicht.
        Dazu würde mir dann aber auf jeden Fall einfallen:

        • Benutzerdefinierte Variablen
          (- Gruppierung)
        • Filtern nach Service
        • Sortierung nach Datum und Zeit

        Allgemein benötigt man:

        • auszuwertender Service
        • aktueller Zustand bei Beginn
        • kumulierte Zeit pro Status

        *---------------------------------
        Datei nach Datum und Zeit sortiert!
        (alte Zeit) = Startzeit
        n = aktiver Status

        |   -> nächster Datensatz
        |   Status[n] += (neue Zeit) - (alte Zeit)
        |   n = neuer Status
        |   (alte Zeit) = (neue Zeit)

        Ergebnisse aus Status[x] auslesen
        *---------------------------------

        | = solange nicht am Ende der Datei

        Mehr sollte da nicht nötig sein.

        Ich denke, dass das bei MySQL mit einer Abfrage-Gruppe pro Service am übersichtlichsten ginge.
        Schau Dir mal die Arbeit mit benutzerdefinierten Variablen an.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bikers-lodge.com
        1. Ob man das nun sinnvoll mit einer DB-Abfrage lösen kann, weiß ich noch nicht.

          Wie könnte man das alternativ zur DB-Abfrage lösen?

          Ansonsten schonmal vielen Dank für die schnelle Hilfe, ich werde das nun versuchen umzusetzen :)

          Viele Grüße,

          Nebbor

          1. Hello,

            Ob man das nun sinnvoll mit einer DB-Abfrage lösen kann, weiß ich noch nicht.

            Wie könnte man das alternativ zur DB-Abfrage lösen?

            Am leichtesten mittels Flat-File, also die normale CSV-Datei, die für Access-Logs auch benutzt wird. Und dann mit Perl oder PHP oder einer Hochsprache, oder Bash-Scripting (wäre mir zu fummelig), oder ...

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bikers-lodge.com