Anrufstatistiken in Grafana

Julia
06.07.2022 1 20:04 min

Was ist sipgate.io?

SMS oder Faxe senden und empfangen, den Anrufverlauf abrufen,  Anrufe initiieren und manipulieren – das alles kann sipgate.io! Mit unseren APIs können Sie unsere Telekommunikationsfunktionen flexibel in Ihren Projekten integrieren. Unsere Library und Tutorials unterstützen Sie dabei, Ihre Telefonie möglichst bequem zu gestalten. 

Vorteile der Anrufstatistiken

Warum Sie eine sipgate-Grafana-Integration nutzen sollten  erfahren Sie auf unserer Website.

Die notwendigen Live-Daten für dieses Projekt können Sie mit unserer sipgate.io Node-Library abrufen.

In diesem Tutorial

Erfahren Sie in dieser Schritt-für-Schritt-Anleitung, wie Sie einen kleinen Server einrichten, die empfangenen Call-Events verarbeiten und diese in eine Datenbank schreiben können.

Mithilfe von Grafana erstellen Sie anhand Ihrer Datenbank ein personalisiertes Dashboard für Ihre Anrufstatistiken. Unter anderem können Sie folgende Fragen zu Ihrer Telefonie im Dashboard beantworten:

  • Wie viele Kund:innen befinden sich momentan in der Warteschlange?
  • Wie viele Anrufe sind derzeit aktiv?
  • Wie lange müssen Kund:innen durchschnittlich warten?
  • Wann werden Sie am häufigsten angerufen?
  • Wie lange dauert ein durchschnittliches Telefonat?
  • Wie viel Prozent der Anrufe werden auf die Voicemail umgeleitet?

Den Code für dieses Tutorial finden Sie in unserem GitHub.

Einblick in die Projekt-Architektur

Um einen besseren Überblick über die verschiedenen Komponenten dieses Projekts zu bekommen, werden folgende Bestandteile definiert:

  • Call Statistics Service: ist das Herz des Projekts. Dieser Service empfängt und verarbeitet die Anrufinformationen von sipgate.io. Im Grunde ist der Service eine Schnittstelle zwischen sipgate.io und Grafana. Er basiert auf Node.js und nutzt die  sipgate.io Node Library für die Kommunikation mit sipgate. Weiterhin übernimmt dieser Service die Authentifizierung gegenüber der sipgate REST-API mittels  OAuth2.
  • Database: Alle Anrufe, Gruppen und Teams werden hier gespeichert. In diesem Tutorial verwenden wir MariaDB von MySQL als Datenbank.
  • Grafana: verwenden wir, um die Daten zu visualisieren.

Um eine konsistente und einfache Einrichtung sowohl in der Entwicklungs- als auch in der Produktionsumgebung zu gewährleisten, verwenden wir einen Docker-Container.

Aufsetzen des Projekts

Docker installieren

Um verschiedene Container für die Installation der Abhängigkeiten zu orchestrieren und einzurichten, sind Docker und Docker Compose erforderlich. Bitte folgen Sie den Anweisungen auf der Seite Get DockerInstall Docker Compose für Ihr System.

Danach ist Ihr System bereit, mehrere virtuelle Container als Multicontainer-Anwendung zu hosten.

Für Mac User: Öffnen Sie Ihre installierte Docker-Anwendung und überprüfen Sie, ob der Docker läuft. Installieren Sie zusätzlich Homebrew, um die folgenden Befehle ausführen zu können:

   brew install coreutils
   ln -s /usr/local/bin/greadlink /usr/local/bin/readlink

Port-Forwarding

Wenn Sie Webhooks in Ihrer Live-Umgebung verwenden, sollten Sie Ihren Code auf einem geeigneten Webserver mit einer geeigneten Adresse ausführen. Für Entwicklungszwecke empfehlen wir jedoch die Nutzung eines Dienstes, der Ihre lokale Umgebung über das Internet zugänglich macht. Dies erleichtert erheblich das Testen Ihres geschriebenen Codes. Es gibt verschiedene kostenlose Dienste, die dafür genutzt werden können. Einige Beispiele sind localhost.run oder ngrok. Beide stellen Ihnen eine öffentliche URL zur Verfügung, mit der Sie Webhooks von sipgate.io empfangen können. Achten Sie darauf, dass Sie den richtigen Port weiterleiten (in diesem Tutorial Port 8080) und dass der von Ihnen gewählte Anbieter sichere Verbindungen über HTTPS bietet. Um das Grafana-Dashboard zugänglich zu machen, leiten Sie auch den Port 3009 weiter.

Webhook, OAuth2 Client und Umgebungsvariablen

Für die Integration mit sipgate.io führen Sie folgende Schritte durch:

  • Richten Sie einen OAuth2-Client ein, um den Anrufstatistik-Dienst zu autorisieren.
  • Konfigurieren Sie die Webhook-URLs für Ereignisse in beide Richtungen.
  • Definieren Sie einige erforderliche Umgebungsvariablen.

Um diese Schritte erfolgreich abzuschließen, gibt es folgende Möglichkeiten:

a) Setup-Dialog

Diese Option ist nur unter Verwendung von Linux- oder Mac-Systemen verfügbar. In dieser Variante führen Sie einen Setup-Dialog aus, der die zuvor genannten Schritte ausführt. Sie können das vollständige Skript unter setup.sh finden und wie folgt ausführen: 

chmod +x ./setup.sh
./setup.sh

Folgende Informationen werden dafür gebraucht:

  • Ihre sipgate-Anmeldedaten
  • Ihre Webhook-URL
  • Die Basis-URL für den Authentifizierungsserver

Diese Informationen werden benötigt, um einen OAuth2-Client zu erstellen und die Webhook-URLs in Ihrem sipgate-Konto zu konfigurieren. 

Ihre sipgate-Anmeldedaten werden nur einmal verwendet und nicht gespeichert. Die Basis-URL hängt von dem System ab, auf dem Sie das Projekt ausführen möchten. In den meisten Fällen funktioniert die Standard-URL http://localhost:8080. Falls Sie das Projekt auf einem Headless-Server ausführen, geben Sie einen Hostnamen oder eine Domain ein, damit Sie den Dienst authentifizieren können.

?Anmerkung: Wenn Sie den Port ändern, müssen Sie diesen auch in der Datei docker-compose.yml ändern.

Die folgenden Informationen sind für die Einrichtung der Datenbank erforderlich. Sie können die im Skript enthaltenen Standardwerte verwenden und ein sicheres Passwort wählen.

  • MySQL-Host
  • MySQL-Datenbank
  • MySQL-Benutzer
  • MySQL-Kennwort

?Anmerkung: Wenn Sie die MySQL-Datenbank ändern, müssen Sie diese auch in der Datei .initdb.d/1_init_schema.sql verwenden.

b) Manuell

Diese alternative Option beschreibt, wie Sie die Schritte manuell ausführen können, wenn Sie sich mehr Überblick über Ihr Projekt wünschen, oder der Einrichtungsdialog nicht funktioniert.

  1. Rufen Sie console.sipgate.com auf, und erstellen Sie einen neuen OAuth2-Client.

Fügen Sie eine Redirect-URI zu http://localhost:8080/auth-code hinzu. Falls Sie ein Headless CMS verwenden, können Sie stattdessen auch einen Hostnamen oder eine Domain verwenden, um den Dienst authentifizieren zu können. Der Endpunkt /auth-code ist für die Verifizierung des Anrufstatistik-Dienstes via Auth-Token zuständig.

?Anmerkung: Wenn Sie den Port ändern, ändern Sie den Port in der Datei docker-compose.yml.

?Anmerkung: Wenn Sie den Endpunkt /auth-code ändern, ändern Sie die definierte Konstante in der Datei call-statistics-service/src/AuthServer.ts AUTHENTICATION_CODE_ENDPOINT.

Benennen Sie die Datei .env.example in .env um:

   mv .env.example .env

Kopieren Sie im Abschnitt Client-Details die Id, Secret und redirect URI fügen Sie folgende Werte in die .env -Datei ein:

   SIPGATE_CLIENT_ID='...'
   SIPGATE_CLIENT_SECRET='...'
   SERVICE_BASE_URL=http://localhost:8080 # part of the redirect URI
  1. Gehen Sie zu den „Webhooks“-Optionen und setzen Sie die incoming und outgoing  URLs auf die Adresse, unter der der Anrufstatistik-Dienst verfügbar sein wird. Diese URL ist entweder Ihr Hostname oder Ihre Domain. Weitere Informationen dazu, wie Sie Ihren Server zugänglich machen können, finden Sie hier. Auch hier setzen Sie die Variable in Ihrer .env-Datei:
   SIPGATE_WEBHOOK_URL=https://your-address.com
  1. Als Nächstes geben Sie in der.env -Datei einige erforderliche Informationen für die Einrichtung der Datenbank ein. Verwenden Sie die hier angegebenen Standardwerte und wählen Sie ein sicheres Passwort:
   MYSQL_HOST=db
   MYSQL_DATABASE=call_statistics
   MYSQL_USER=user
   MYSQL_PASSWORD=<your_secret_password>

?Anmerkung: Wenn Sie die MySQL-Datenbank in der .env Datei ändern, geben Sie auch das Datenbankmodell in der Datei .initdb.d/1_init_schema.sql ein.

Ausführen des Projekts

Nachdem Sie den Oauth2-Client und die Umgebungsvariablen eingerichtet haben, können Sie das Projekt auf folgende Weise ausführen:

sudo docker-compose up

Nun navigieren Sie zu https://localhost:8080/auth, um zunächst Ihr sipgate-Konto zu authentifizieren und REST-API-Calls durchführen zu können. Daraufhin werden Sie zu Grafana weitergeleitet.

An dieser Stelle sollten Sie sich mit dem Standardkonto von Grafana user: admin, password: admin anmelden. Sie werden daraufhin aufgefordert, Ihre Anmeldedaten zu ändern. Nachdem Sie sich erfolgreich eingeloggt haben, sollten Sie zum Grafana-Dashboard weitergeleitet werden.

?Anmerkung: Grafana kann nur Statistiken für Ereignisse anzeigen, die gesammelt wurden, während der Anrufstatistik-Dienst lief. Wenn Sie eine neue Instanz des Dienstes einrichten, sind noch keine Ereignisse vorhanden. Daher kann Ihr Dashboard leer sein oder keine Daten anzeigen:

Das Projekt-Dashboard können Sie auch im Menü auf der linken Seite aufrufen. Folgen  Sie dem folgenden Pfad “Dashboards (Symbol mit vier Quadraten) → Manage→ Call  Statistics”.

Für eine ausführlichere Beschreibung des Statistik-Dashboards lesen Sie das Kapitel Ein Überblick über das Grafana-Dashboard.

Custom Teams

Sie können Ihre Anrufstatistiken in Grafana nach benutzerdefinierten Gruppen und Ihren Teams filtern. Gruppen werden automatisch aus Ihrem sipgate-Konto übernommen. Wenn Sie benutzerdefinierte Teams hinzufügen möchten, können Sie dies tun, indem Sie die entsprechenden Rufnummern zu einem Team-Label in der teams.json folgendermaßen hinzufügen. Dabei muss ein Team mindestens zwei Rufnummern enthalten.

[
  {
    "name": "Sales Team for Product A",
    "numbers": ["+49211975379020", "+4921197537902"]
  }
]

Ihre Umsetzungsmöglichkeiten

Wie bereits erwähnt wurde, reagiert der Service auf Call-Events der sipgate.io Push-API. Diese Calls werden dann in die Datenbank geschrieben. Schließlich fragt Grafana diese Daten ab und visualisiert sie im Dashboard.

Call-Events

Es gibt drei Arten von call-events, die in der Statistik erfasst werden:

  • NewCallEvent: übermittelt, dass ein neuer Anruf ankommt.
  • AnswerEvents: wird ausgelöst, wenn der Anruf angenommen wird. 
  • HangUpEvents: signalisiert, dass ein Anruf beendet wurde. 

Datenbank-Schema

Wenn die Datenbankinstanz zum ersten Mal initialisiert wird, wird das unten beschriebene Schema einmal ausgeführt. Es wird in .initdb.d/1_init_schema.sql gespeichert.

Calls

Die wichtigste Tabelle ist die Tabelle der Anrufe (calls):

CREATE TABLE calls (
    call_id VARCHAR(255) PRIMARY KEY,
    start DATETIME NOT NULL,
    end DATETIME,
    answered_at DATETIME,
    direction ENUM('in','out') NOT NULL,
    mastersip_id VARCHAR(255),
    extension VARCHAR(255),
    caller_number VARCHAR(255) NOT NULL,
    callee_number VARCHAR(255) NOT NULL,
    answering_number VARCHAR(255),
    hangup_cause ENUM('normalClearing', 'busy', 'cancel', 'noAnswer', 'congestion', 'notFound', 'forwarded'),
    group_extension VARCHAR(255) NULL,
    voicemail BOOLEAN NOT NULL DEFAULT false,
    crashed BOOLEAN NOT NULL DEFAULT false
);

Wenn der Anrufstatistik-Dienst ein NewCallEvent, empfängt, wird eine neue Datenzeile mit grundlegenden Informationen wie Anrufer-/Abonnentennummer, Erstellungszeitpunkt etc. erstellt. Wichtig ist, dass die Zeitstempel answered_at und end den Wert NULL haben. Sie werden später ausgefüllt, wenn das Answer- und HangupEvent empfangen werden.

Die SQL-Abfragen können nun zwischen aktiven und inaktiven Anrufen unterscheiden und erkennen, ob ein Anruf angenommen wurde, da die jeweiligen Zeitstempel NULL sind.

Groups

Die groups-Tabelle speichert die Gruppen aus Ihrem sipgate-Account für die von Ihnen initiierten oder an sie gerichteten Anrufe:

CREATE TABLE groups (
    extension VARCHAR(255) PRIMARY KEY,
    alias VARCHAR(255)
);

Um die Integrität der Gruppentabelle sicherzustellen, fügen Sie einen Fremdschlüssel zur calls-Tabelle hinzu. Der Schlüssel verweist auf die Extension-Spalte der Gruppentabelle und verhindert, dass Gruppen entfernt werden, auf die die calls-Tabelle noch verweist:

ALTER TABLE calls ADD FOREIGN KEY (group_extension) REFERENCES groups(extension) ON UPDATE CASCADE ON DELETE RESTRICT;

Um den Benutzern die Möglichkeit zu geben, Aufrufe im Grafana-Dashboard zu filtern, die keiner Gruppe angehören, fügen Sie eine benutzerdefinierte Gruppe zu unserer Tabelle hinzu:

INSERT INTO groups VALUES('other', 'Other');
Teams

Die benutzerdefinierten Teams werden in der teams-Tabelle angezeigt:

CREATE TABLE teams (
    id INTEGER PRIMARY KEY,
    name VARCHAR(255) NOT NULL
);

Um Telefonnummern zu einem Team hinzuzufügen, erstellen Sie eine teams_numbers-Beziehungstabelle, die auf die teams-Tabelle verweist:

CREATE TABLE teams_numbers (
    team_id INTEGER NOT NULL,
    number VARCHAR(255) NOT NULL,
    FOREIGN KEY(team_id) REFERENCES teams(id)
);

Analog zu Standardgruppen werden die teams-Variablen definiert:

INSERT INTO teams VALUES(0, 'Other');
Authentication parameters

Die folgende Tabelle enthält die Tokens, die für die Authentifizierung OAuth2 erforderlich sind:

CREATE TABLE authentication_params (
    token_type ENUM('access', 'refresh') PRIMARY KEY,
    token_value TEXT NOT NULL
);

Event-Handler

Die Klasse EventHandler ist in call-statistics-service/src/EventHandler.ts implementiert und verarbeitet eingehende Webhook-Ereignisse, die von der sipgate Push-API gesendet werden.

Für jeden Event-Typ gibt es drei öffentliche Behandlungsmethoden.

handleOnNewCall
public handleOnNewCall = async (
    newCallEvent: NewCallEvent
  ): Promise<void> => {
    console.log(`newCall from ${newCallEvent.from} to ${newCallEvent.to}`);

    if (this.isVoicemailCall(newCallEvent)) {
      await this.handleVoicemail(newCallEvent, new Date());
      return;
    }

    await this.handleRegularNewCall(newCallEvent, new Date());

    await this.insertCallIntoGroups(newCallEvent);
};

Zunächst wird geprüft, ob der Anruf an die Voicemail weitergeleitet wird, da er dann in der Datenbank explizit als Voicemail gekennzeichnet wird. Andernfalls wird er wie ein normaler Anruf behandelt und alle empfangenen Event-Informationen werden in der Datenbank gespeichert. Zusätzlich fragen Sie für die Nummern (je nach Richtung, Anrufer- oder Angerufenen-Nummer) weitere Informationen ab, um herauszufinden, ob sie einer Gruppe zugeordnet sind. Wenn ja, aktualisieren Sie die Gruppeninformationen in der groups-Tabelle und aktualisieren die group_extension Anrufe in der Datenbank.

handleOnAnswer
 public async handleOnAnswer(answerEvent: AnswerEvent) {
    console.log(`answer from ${answerEvent.from} to ${answerEvent.to}`);
    await this.updateAnswerDateAndNumber(answerEvent, new Date());
  }

Wenn der Event-Handler ein AnswerEvent empfängt, aktualisiert er einen Datenbankeintrag mit der aktuellen Zeit:

private async updateAnswerDateAndNumber(
    answerEvent: AnswerEvent,
    date: Date
  ) {
    let callData = {
      answeredAt: date,
      answeringNumber: answerEvent.answeringNumber,
      crashed: false,
    };

    if (answerEvent.fullUserId) {
      const splitUserIdResult = splitFullUserId(answerEvent.fullUserId);
      callData["masterSipId"] = splitUserIdResult.masterSipId;
      callData["userExtension"] = splitUserIdResult.userExtension;
    }

    await this.database.updateCall(answerEvent.callId, callData);
  }

Mit dieser Methode wird ein callData -Objekt erstellt, um den Anruf in der Datenbank zu aktualisieren. Zuvor wird geprüft, ob das answerEvent eine fullUserId enthält, da Sie bei einem Gruppen-Anruf nicht wissen, wer den Anruf beantwortet hat, bis das answerEvent empfangen wird.

handleOnHangUp
public async handleOnHangUp(hangUpEvent: HangUpEvent) {
    console.log(`hangup from ${hangUpEvent.from} to ${hangUpEvent.to}`);
    await this.updateEndDateOnCall(hangUpEvent, new Date());
}

Wenn ein HangUpEvent empfangen wird, wird der Datenbankeintrag mit den entsprechenden Event-Informationen aktualisiert:

 private async updateEndDateOnCall(hangupEvent: HangUpEvent, date: Date) {
    await this.database.updateCall(hangupEvent.callId, {
      end: date,
      hangupCause: hangupEvent.cause,
      crashed: false,
    });
}

Hier setzen Sie nur die Endzeit des Anrufs und die hangupCause , die wir vom hangupEvent erhalten haben.

Sonderfälle

Im vorherigen Kapitel haben wir den Event-Handler vereinfacht. Hier beschreiben wir einige weitere Details, die wir implementiert haben, um die Sonderfälle zu behandeln.

Voicemail

Wie bereits im vorherigen Kapitel erwähnt wurde, überprüfen Sie, ob es sich bei eingehenden NewCallEvents um Voicemail-Anrufe handelt oder nicht:

private isVoicemailCall(newCallEvent: NewCallEvent) {
    return (
      newCallEvent.users?.length == 1 && newCallEvent.users[0] == "voicemail"
    );
}

Um einen Anruf auf der Voicemail zu bearbeiten, entscheidet die folgende Methode, ob ein neuer Anruf eingefügt oder ein bestehender Anruf aktualisiert wird. Dies hängt davon ab, wie die Voicemail erreicht wurde. Es gibt zwei Fälle:

  • Der Anruf wurde direkt angenommen (z. B. wenn Ihr Telefon offline ist), dann wird ein neuer Anruf hinzugefügt.
  • Der Anruf wird nach einer bestimmten Zeit entgegengenommen, dann wird der Anruf aktualisiert.
private async handleVoicemail(newCallEvent: NewCallEvent, date: Date) {
  const origCallEvent = await this.database.getCall(
    newCallEvent.originalCallId
  );
  if (origCallEvent.length == 0) {
    await this.database.addCall(newCallEvent.callId, {
      start: date,
      direction: newCallEvent.direction,
      callerNumber: newCallEvent.from,
      calleeNumber: newCallEvent.to,
      voicemail: true,
    });
  } else {
    await this.database.updateCall(newCallEvent.originalCallId, {
      callId: newCallEvent.callId,
      voicemail: true,
    });
  }
}

Um die Filterung von Voicemail-Anrufen zu aktivieren, setzen Sie das Attribut voicemail auf den Wert true gesetzt wird.

Abgebrochene Anrufe

Wenn der Server zum Startzeitpunkt aktive Anrufe ohne HangUpEvent registriert, werden diese zunächst mit  einer Crash-Flag gekennzeichnet. Auf diese Weise können Sie, wenn der Server während der Ausfallzeit HangUpEvents, verpasst, diese aus der Statistik der aktiven Anrufe heraushalten.

Die folgende Methode ist in der Klasse Database implementiert, die unter  call-statistics-service/src/Database.ts zu finden ist:

public async crashCheck() {
  let queryString: string =
    "UPDATE calls SET crashed=true WHERE end IS NULL;";
  await this.query(queryString);
}

Wenn ein AnswerEvent oder ein HangupEvent für einen solchen gekennzeichneten Anruf eintrifft, wird das crashed-Tag im oben erwähnten Event-Handler zurückgesetzt.

Queries in Grafana

Um zu erklären, wie die Datenbankabfragen funktionieren, gehen wir den Prozess der Erstellung der Query „Durchschnittliche Antwortzeit“ durch.

Die einzige Information, an der wir interessiert sind, ist der start und answered_at Zeitstempel. Wir berechnen die Differenz zwischen ihnen mit AVG(TIME_TO_SEC(TIMEDIFF(answered_at, start))) as „time in seconds“.

Grafana verlangt von uns die time_sec Angabe, die zum Filtern und Gruppieren von Events nach Zeit verwendet wird. Dafür stellt Grafana das $__timeGroup Macro zur Verfügung. Sie können mehr über die Grafana-Macros in der Dokumentation lesen.

Die Query sieht nun wie folgt aus:

SELECT
  $__timeGroup(start, '$time_unit', 0) as time_sec,
  AVG(TIME_TO_SEC(TIMEDIFF(answered_at, start))) as "time in seconds"
FROM calls
GROUP BY time_sec

Jetzt sollte die Query funktionieren und Sie sollten die Ergebnisse im Diagramm sehen können. Wir möchten jedoch auch die Filterung nach Teams und Gruppen aktivieren.

Wir haben Grafana so konfiguriert, dass die in der Datenbank gespeicherten Teams und Gruppen in die Variablen teams und groups geladen werden. Der Benutzer kann dann in der Filterleiste eine beliebige Gruppen- und/oder Teamkonstellation auswählen. Nehmen wir an, dass der Benutzer bei den Gruppen die Kästchen Sales und Other ankreuzt. Wir können diese Werte mit  ${groups:pipe} zu Sales|Other zusammengefügt. Mit ${groups:pipe} REGEXP fieldName OR (${groups:pipe} REGEX „Other“) können wir prüfen, ob eine Gruppe einbezogen werden soll.

Zuerst müssen wir groups, teams_numbers und teams wie folgt joinen:

LEFT JOIN groups on calls.group_extension=groups.extension
LEFT JOIN teams_numbers on calls.callee_number=teams_numbers.number or calls.caller_number=teams_numbers.number
LEFT JOIN teams on teams_numbers.team_id=teams.id

Das WHERE der Query prüft dann, ob der Gruppenalias mit der Benutzergruppe oder dem Team übereinstimmt:

WHERE (('${groups:pipe}' REGEXP groups.alias) OR ('${groups:pipe}' REGEXP "Other" AND calls.group_extension IS NULL))
AND   (('${teams:pipe}'  REGEXP teams.name) OR ('${teams:pipe}' REGEXP "Other"))

Die vollständige Query sieht folgendermaßen aus:

SELECT
  $__timeGroup(start, '$time_unit', 0) as time_sec,
  AVG(TIME_TO_SEC(TIMEDIFF(answered_at, start))) as "time in seconds"
FROM calls

LEFT JOIN groups on calls.group_extension=groups.extension
LEFT JOIN teams_numbers on calls.callee_number=teams_numbers.number or calls.caller_number=teams_numbers.number
LEFT JOIN teams on teams_numbers.team_id=teams.id

WHERE (('${groups:pipe}' REGEXP groups.alias) OR ('${groups:pipe}' REGEXP "Other" AND calls.group_extension IS NULL))
AND   (('${teams:pipe}'  REGEXP teams.name) OR ('${teams:pipe}' REGEXP "Other"))

GROUP BY time_sec

Ein Überblick über Grafana-Dashboard

Die gesamte Visualisierung der Statistiken erfolgt mit Grafana, das Sie unter http://localhost:3009  in Ihrem Browser aufrufen können. Melden Sie sich mit den Anmeldedaten an, die Sie festgelegt haben. Wenn Sie das Call-Statistics-Dashboard schon einmal aufgerufen haben, sollten Sie es im Abschnitt “Recently viewed dashboards” auf der Startseite verlinkt sehen können.

Andernfalls können Sie auf das Dashboard zugreifen, indem Sie dem folgenden Pfad im Menü auf der linken Seite folgen:  Dashboards (Symbol mit vier Quadraten) → Manage → General. Dort finden Sie einen Link zu Ihrem Dashboard.

Ihr Dashboard sollte ähnlich zu dem folgenden Screenshot aufgebaut sein:

Vorhandene Bereiche

In diesem Kapitel werden die einzelnen Bereiche des Anrufstatistik-Dashboards kurz beschrieben.

Die in jedem Bereich angezeigten Daten beziehen sich auf die Zeitspanne, die in der oberen, rechten Ecke definiert ist.

  • Waiting in queue (In der Warteschlange): In diesem Bereich werden alle Anrufe angezeigt, die noch nicht angenommen oder aufgelegt wurden.
  • Active calls (Aktuelle Anrufe): Aktuelle Anrufe werden in zwei separaten Feldern mit dem angegebenen Titel angezeigt. Das linke zeigt die Anzahl der Anrufe an, die angenommen und noch nicht aufgelegt wurden. Das rechte Feld zeigt weitere Details (die Startzeit, die Richtung und die Nummer des Besitzers)  zu jedem aktiven Anruf in einer Tabelle an. 
  • Incoming and outgoing pick-up ratio (Verhältnis von ein- und ausgehenden Anrufen): In diesen Tortendiagrammen wird das Verhältnis zwischen angenommenen und nicht angenommenen Anrufen dargestellt. In der Legende wird jeweils die Gesamtzahl und die relative Anzahl der (nicht-)angenommenen Anrufe angegeben.
  • Incoming and outcoming calls graph (Grafik der ein- und ausgehenden Anrufe): Diese Diagramme zeigen die unbeantworteten und beantworteten eingehenden und ausgehenden Anrufe.
  • Mean call answer time (Durchschnittszeit bis zur Anrufannahme): In diesem Diagramm wird die durchschnittliche Zeit bis zur Annahme eines Anrufes dargestellt.
  • Longest waiting times (Längste Wartezeiten): Hier werden die eingehenden Anrufe angezeigt, die die längste Wartezeit bis zur Annahme durch einen Mitarbeiter aufweisen.
  • Average call duration (Durchschnittliche Gesprächsdauer): Hier wird die durchschnittliche Dauer aller ausgehenden und eingehenden Anrufe angezeigt.
  • Longest calls (Längste Anrufe): In diesem Feld werden die Anfangszeit und die Dauer der zwanzig längsten Anrufe in absteigender Reihenfolge aufgeführt.
  • Total calls (Gesamte Anrufe): Die Anzahl der gesamten Anrufe wird in diesem Bereich angezeigt.
  • Total voicemail calls (Gesamte Voicemail-Anrufe): In diesem Diagramm werden alle Voicemail-Anrufe mit deren Uhrzeit angezeigt.
  • Most calling numbers (Die häufigsten Rufnummern): Diese Tabelle zeigt die zwanzig Nummern, die Ihre Hotline am häufigsten anrufen, mit der jeweiligen Anzahl der Anrufe in absteigender Reihenfolge.

Filter-Optionen

Das Grafana-Dashboard bietet mehrere Filter-Optionen, um bestimmte Anrufstatistiken verwalten zu können. Sie können diese Filter aus jeder der folgenden Optionen frei kombinieren:

  • Gruppen

Die Gruppen werden direkt aus Ihrem sipgate.io-Kontomportiert. Sie können nach Anrufen mit Teilnehmern aus einer bestimmten Gruppe oder einer Sammlung von Gruppen filtern.

  • Teams

Die Teams definieren Sie selbst in der teams.json-Datei. Wie bei den Gruppen können Sie nach Gesprächen mit Teilnehmern aus einem bestimmten Team oder einer Sammlung von Teams filtern.

  • Zeiteinheit

Je nach Zeiteinheit werden die Dashboard-Daten in Minuten, Stunden, Tagen oder jeder anderen Zeiteinheit zusammengefasst.

  • Zeitspanne

Mit dieser Option können Sie die Zeitspanne für Ihre Anrufstatistiken beliebig definieren. Sie können zum Beispiel die Zeitspanne von einem Tag auf sieben Tage oder auch nur auf die letzte Stunde ändern.

 

Fazit

In diesem Tutorial haben Sie gelernt, wie Sie die Grafana-Dashboards für Ihr Unternehmen mit sipgate.io-Integration erstellen können, um Ihre Anrufstatistiken immer im Blick zu behalten.

Das vollständige Projekt finden Sie  in unserem GitHub- Repository.

Wenn Sie mehr über die Möglichkeiten unserer sipgate.io Node-Library erfahren möchten, schauen Sie sich unsere anderen Tutorials in unserem Blog an.

1 Kommentar


Raphael:

Diese Integration finde ich klasse.

Leider gelingt es mir trotz Anleitung nicht, es zum Laufen zu bringen. Allein bei der Authentifizierung über https://localhost:8080/auth, erhalte ich von Sipgate die Fehlermeldung „Client nicht gefunden“. Nach ein wenig Recherche, scheint die URL „https://login.sipgate.com/auth/realms/sipgate-apps/protocol/openid-connect/auth“ aufzufrufen. Mit der URL „https://login.sipgate.com/auth/realms/third-party/protocol/openid-connect/auth“ scheint die API zumindest einen „session_state“ sowie „code“ zurückzugeben. Leider geht es an dieser Stelle für mich nicht mehr weiter. Da ich diese Integration gerne selbst nutzen und für weitere WebApps verwenden möchte, bitte ich Euch um Rückmeldung, mit wem ich hierzu sprechen kann. Danke Euch!

antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert