Datagrabbing

Zuständigkeiten:

Mails: Jan Köpf

Tickets: Nicolas Wimmer & Jan Köpf

Calls: Raimund Machacek & Jan Köpf

Datagrabbing allgemein:

Mails:

Datagrabbing von Mails:

Tickets:

Datagrabbing von Tickets:

  1. Jedes abgeschickte Mail an Support Gruppe löst ein Script aus.
  2. Script übernimmt Ticketinformationen und je nach Filtereigenschaften (z.b. Filtert ob Business oder Privatkunde)
  3. Script trägt Zeitpunkt des eintreffens + Eigenschaften des Tickets in Datenbank ein oder aktualisiert diese, falls Ticket bereits vorhanden

"Stale" Datagrabbing Vor- und Nachteile (alte Methode)

"Live" Datagrabbing Vor- und Nachteile

Wiederherstellung von Daten:

Wiederherstellung von Mails:

  1. Alle Mails des gesamten Jahres abrufen
  2. Message-IDs von eingehenden zu ausgehenden Mails vergleichen und Zeitstempel in Datenbank festhalten
  3. Supporter direkt Fragen, welches Mail, wann bearbeitet wurde.
  4. Vergleich mit gesendeten Mails und Zeitstempeln

Wiederherstellung von Tickets:

  1. Alle Tickets des gesamten Jahres abrufen
  2. Bisherige TTS Logs pro Ticket abgleichen und mit zutreffenden Eigenschaften (z.b. lediglich Tickets an Support oder Tickettyp: .z.b. Privat festhalten)

Technische-Details zu Datagrabbing und Performance

Grund: Im Allgemeinen ist die Datenkonsistenz, sowie die Genauigkeit der Statistik selbst, von der Nachvollziehbarkeit der einzelnen aufzuzeichnenden Ereignisse direkt abhängig.
Im Falle der Mailstatistik gibt es zwei Identifikationsmerkmale, die ein Mail einzigartig und damit eindeutig nachvollziehbar macht. Es gibt die so genannte message-id (Message-ID, MESSAGE-ID) in jedem Mailheader. Diese wird einzigartig von jedem Mailserver vor dem versandt vergeben. Zusätzlich dazu ziehen wir noch die so genannte Dovecot-ID heran. Eine ID welche vom Mailserver intern pro Mailbox/Ordner/Mail vergeben wird und ist eine einzigartige fortlaufende Ganzzahl.
Ursprünglich wurden mittels IMAP-Search (RFC-3501) alle Mails eines einzelnen Tages abgerufen, danach mit gewissen Bedingungen verglichen (Absender/Empfänger -> zur evaluierung des Mailtypes = Business/Social Media/Privat) und anschließend wurde der Mailankunfts-Zeitpunkt samt Message-ID und Mailtyp in einer Datenbank hinterlegt. Um nun die Zeitspanne für die SLA-Berechnung zu erhalten, müssen alle Mails ebenfalls einen Endzeitpunkt beinhalten. Dieser kann jedoch nur ermittelt werden, wenn regelmäßig alle Mails von einem Tag abgerufen und erneut verglichen werden. Zur ermittlung des Mailstatus wurden die bereits im Support genutzten Thunderbird-Stati (extra IMAP-Flags) verwendet.
Warum nun alle Mails eines ganzen Tages für die Statusüberprüfung abrufen und nicht nur die bereits eingetragenen Mails aus der Datenbank?
Wie in RFC-3501 (Page 51) bzw. in RFC-2822 (Section 3.6.4) nachzulesen ist, kann das Header-Field Message-ID in verschieden Varianten geschrieben werden. Da jedoch IMAP-Search unter PHP einigen Beschränkungen unterliegt, ist es nicht möglich zuverlässig die Mail via Message-ID abzurufen. Praxistests über Monate hinweg mit PHP-7.1 - 7.3 / PHP-8 und der IMAP2007-Library zeigen das die Message-IDs zwar eindeutig einzigartig sind, jedoch nicht immer zuverlässig mittels IMAP-Search abgefragt werden können.
Nachdem nun alle Mails eines Tages, mehrmals abgerufen werden müssen (anfängliches Zeitinterval 5min) - ist demnach auch die Serverlast (sowohl am Mailserver als auch am SLA-Berechnungs-Server) sehr hoch.
Ein weiterer Nachteil ist beispielsweise: was passiert bei Löschung eines Mails (weil z.b. Spam) oder bei Verschiebung eines Mails in einem anderen Unterordner als "INBOX".

Der Fallback

Als Fallback wurden die so genannten Dovecot-IDs herangezogen.
Wie kommt man nun zu den "Dovecot-IDs"?
Da diese nicht im Mailheader vorhanden sind, wurde hierzu direkt der Dovecot (Mailserver) befragt. Es wurden also zuerst alle Message-IDs eines Tages abgefragt und anschließend anhand dieser, die dazugehörige Dovcot-ID in der Datenbank hinterlegt.
Diese waren/sind eindeutig jedem Mail innerhalb einer Mailbox zugewiesen und bieten ebenfalls die Möglichkeit via IMAP-Search (UID) einen direkten Abruf der Mail vom Mailserver. Diese Methode ist sowohl performance freundlich, als auch zuverlässig. Der große Nachteil hierbei ist jedoch immer noch das andauernde Abfragen der Mails nach einem bestimmten Zeitinterval und damit das aktive aktualisieren von so genannter Stale-Data (Statischer Informationen).

Die neue Methode

Seit Dovecot Version 2.13 gibt es nun auch die Möglichkeit einer API im Dovecot, welche mittels der Skriptsprache LUA arbeitet. Diese Event-Basierende API läuft direkt als Plugin im Dovecot selbst und kann somit zu jederzeit vom Mailserver direkt ausgeführt werden.
Beispiel:
Ein neues Mail kommt in die Box -> Dieses Event löst einen POST mit dem gesamten Mailheader samt Dovecot-ID an eine Webapi aus -> die Webapi weist der Mail anhand von Kriterien (z.b. Absender/Empfänger) einen Mailtyp zu und trägt diesen in die Datenbank ein.
Ein Mail wird vom Support bearbeitet -> Supporter markiert mittels einem IMAP-Flag im Thunderbird das Mail als erledigt -> Dieses Event löst wieder einen POST aus mit Dovcot-ID und Status erledigt -> Die Webapi übernimmt und trägt den exakten Zeitpunkt in die Datenbank ein.

Damit werden nun 2 Probleme auf einmal beseitigt. Die Serverlasten sind minimal und die Endzeitpunkte jedes Mails sind genau und nicht abhängig von Zeitintervallen. Jedes Mail kann ebenfalls genau nachvollzogen werden und damit wäre dann auch die konsistenz gewähleistet. Zusätzlich dazu werden alle Mails gezählt und nicht nur jene, welche sich genau an die RFC-Spezifikationen halten bzw. welche die selbe Deklarationen der message-ids haben.
Damit haben wir nun auch Live-Data anstatt Stale-Data und entgehen damit einigen Sonderfällen wie z.b. Löschung oder Verschiebung.

Wiederherstellung

Um gleich bei den Mails zu bleiben, wie oben in den einzelschritten beschrieben, ist ein Abruf aller Mails eines ganzen Jahres nötig. (Nachteil: großer Lastaufwand)
Zusätzlich dazu kann wie in RFC-2822 (Section 3.6.4) mittels Mailheader die Einträge "in-reply-to" sowie "references" herangezogen werden um festzustellen, welche Mails beantwortet und wann diese erledigt wurden.
Alle anderen Mails, welche beispielsweise via Ticket erledigt wurden - würden demnach auch keinen entsprechenden "in-reply-to" sowie "references" Einträge im Mailheader besitzen. Hierzu müssten dann die Supporter direkt befragt werden, wann / welches Mail erledigt wurde. Dies wäre natürlich extrem unzuverlässig. (Beispielsweise bei bereits gekündigten Mitarbeitern)

Tickets

Ein ähnliches Problem gibt es im TTS. Die einzige Möglichkeit hierbei Ticket-Start sowie Endzeitpunkt festzustellen ist über den TTS-Log. Dieser beinhaltet pro Ticket fast alle Ereignisse.
Auch hier gibt es einige Sonderfälle zu beachten:
Um nur die häufigsten Sonderfälle zu nennen. Auch hierbei liegt das Hauptproblem bei einer Stale-Data Statistik beim Lastaufwand und der Nachvollziehbarkeit eines jeden Tickets und dessen Bearbeitung.
Ein gutes Beispiel für einen Sonderfall wäre TT1165255 -> laut Status 26.Jan.2021, 17:29 wurde das Ticket von Support an eine andere Gruppe geschickt, anschließend wurde dieses von der Gruppe Support editiert. Danach wurde das Ticket wieder von Support an eine andere Gruppe geschickt.
Dies bedeutet nun folgendes:
  1. Startzeitpunkt 1: 26.Jan.2021, 17:29
  2. Endzeitpunkt 1: ???
  3. Startzeitpunkt 2: ???
  4. Endzeitpunkt 2: 05.Feb.2021, 18:25

Natürlich kann für diesen Spezialfall eine Ausnahme geschrieben werden. Jedoch stellt sich hierbei die Frage, welche Zeit gilt für die SLA Berechnung?
Nimmt man Startzeitpunkt 1 und Endzeitpunkt 2, hätte man eine Zeitspanne, in welcher eindeutig eine andere Abteilung für die Weiterverarbeitung des Tickets zuständig war.
Alternativ könnte man den Log durchsuchen und den nächsten Eintrag, welcher nicht von Support kommt, als Endzeitpunkt heranziehen. (also 01.Feb.2021, 10:34 )
Was passiert jedoch mit Endzeitpunkt 2?
-> Soll dieser ganz verworfen werden? (Beeinträchtigung der Statistikkonsistenz)
-> Soll dieser als Startzeitpunkt den nächsten Supporteintrag nehmen (05.Feb.2021, 18:25 )? (Beeinträchtigung der Genauigkeit)
Dies war jedoch nur eine der Ausnahmen und umso länger die Bearbeitung eines Tickets dauert, desto mehr verliert die Statistik an Genauigkeit und Aussagekraft.

Die Lösung

Hierbei bietet die Statistik aus Live-Data wieder eine Lösung. Bei jedem Klick auf "Ticket Weiterführen" oder "Ticket Schließen", wird ein neuer Zeitstempel samt Ticketid und Tickettyp (Business/Privat) an eine Webapi geschickt.
Je nachdem wer das Ticket, wohin schickt - wird ein Start oder ein Endzeitpunkt in der Datenbank festgehalten. Die Ausnahme "Ticket schließen", setzt dabei für alle Einträge einer Ticket-ID den Endzeitpunkt.
Damit wird sichergestellt, dass alle Tickets ab einem gewissen Punkt auch erledigt sind und keines "ewig" offen bleibt.

Fehlermarge

Natürlich ist keine der hier vorgestellten Varianten Perfekt. Darum arbeite ich bereits an einem Hybrid, welcher gesicherte Informationen aus Live-Data (welche garantiert richtig sind) heranzieht und alle Übrigen, fehlenden Einträge sofern möglich aus Stale-Data hinzufügt.
Derzeit beobachtete Fehlermarge liegt bei ca. +/- 1 Fall pro Woche. Für Mails und Tickets.
Im Vergleich dazu, die Fehlermarge aus reinen Stale-Data Informationen, kann bis zu +/- 1 Fall Pro Tag sein.
Der hybrid wird voraussichtlich +/- 1 Fall Monat Fehlermarge haben.

Ergänzung:

Unter +/- 1 Fall, versteht man einen Fall zu viel bzw. einen Fall zu wenig, wurden in der Berechnung mit einbezogen.

Aufwandsabschätzung Wiederherstellung

Calls

Datagrabbing von Calls:

Stundenübergreifende Calls
Ein wichtiges Kapitel bei der Callstatistik sind all jene Calls in den Randbereichen des Erfassungsintervals. Da es sich in der Statistik um eine Stundenweite auflösung handelt, muss die Statistik mindestens Minutenweise geführt werden. Aktuell wird diese im Backend sekundenweise geführt und eine möglichst genaue Statistik zu gewährleisten. Die Randbereiche sind hierbei die Anfänge / Enden jeder Stunde.

Problemstellung:
Ein denkbares Szenario wäre ein Call, welcher um 08:59:00 ankommt und 20 Sekunden später abgehoben wird. Dieser Call wird dann 3 Minuten später abgeschlossen und aufgelegt. Nun wird als Endzeitpunkt 09:02:20 festgehalten. Versucht man nun eine Berechnung von 08:00-09:00, unter berücksichtigung von Malusneutralen Stunden auszuführen, dann wird dies zwangsläufig zu einigen Problemen Führen.
  1. Für welche Stunde zählt der Call?
  2. Wie berechnet man die Möglichkeit einer malusneutralen Stunde?
  3. Wie wirkt sich das auf Tages/Monatsübergreifende Anrufe aus?

Wie bei Mail/Ticketstatistiken wird beim ersten Problem, immer die Ankunft des Calls gezählt. Also in diesem Beispiel 08:59:00. Dieser Zählt nun für den Betrachtungszeitraum von 08:00-09:00. Da die Berechnung Stundenweise arbeitet, versucht das Script anhand der Call-ID die Endzeit im nächsten Betrachtungszeitraum zu finden. Ebenfalls wird vom Script, jede Call-ID ignoriert, welche nur Endzeitpunkte/Abhebezeitpunkte und keine Ankunftszeit in dem aktuellen Betrachtungszeitraum haben. (Also Calls welche von der vorangegangen Stunde stammen) Im Gegensatz zur alten Statistik, bei welcher dies nur bedingt berücksichtigt wurde, gibt es hier ebenfalls bei größeren Betrachtungszeiträumen (Tage/Monate) für diese Fälle spezielle Ausnahmen. Anschließend schreibt das Script die Differenzen zwischen eingehenden Anruf/Abheben/Auflegen in Sekunden in die Datenbank. Nach Abschluss eines Betrachtungszeitraumes wird dieser mit dem gegebenen Forcast verglichen und anschließend als Malusneutral oder nicht Markiert.
Die Datenbank selbst verfügt über einige Views, um den Betrachtungszeitraum anzupassen und zwischen Bereinigter und Absoluter Werte unterscheiden zu können. Den direkten Vergleich zwischen diesen Werten übernimmt dann das Interface.