Teams Call Auswertung
Diese Seite beschreibt, wie sie mit Graph einen Einzelverbindungsnachweis für PSTN und Direct Routing-Anrufe generieren. Sie können über diesen Weg keine Federation-Anrufe, interne Verbindungen oder Besprechungen erfassen.
Problem
Die Lösung habe ich entwickelt, weil wieder einmal ein konkretes Problem bei einem Kunden mich genervt hat. Folgendes ist passiert.
- Externer Teilnehmer ruft die Zentrale (Call Queue) an
- Ein Mitarbeiter in der Call Queue schnappt sich den Anruf
- Der Anruf wird sauber beendet
Nun kommt aber der Vertrieb und möchte ein paar Auswertungen, z.B.
- Wer hat den Call angekommen
- Wie lange musste der Anwender in der Call-Queue warten
Mit einer Auswertung der CDR-Einträge des SBCs komme ich hier nicht weiter, da ich nur den Start der Verbindung zur CallQueue-Rufnummer und das Ende des Anrufs sehe. Alle internen Vermittlungen und Verweilzeiten sieht der SBC nicht. Diese Daten hat aber Teams.
Grenzen des Teams Admin Portal
Ich bin also auf https://teams.admin.microsoft.com und wollte hier weiter analysieren. Das Problem dabei ist aber, dass es hier gar keine Liste der eingegangenen Anruf gibt. Ich kann nur auf einen Benutzer gehen und mir dessen Anrufe der letzen 30 Tage anzeigen lassen: In dem Fall wusste ich zufällig den Teilnehmer und den Zeitpunkt, so dass ich relativ schnell dann den Call dazu gefunden habe. Die Call-Übersicht erlaubt nämlich keine Suche nach Rufnummern sondern zeigt nur allgemeine Informationen an.
Diese Ansicht ist für die Suche anhand von Anrufen anhand der Rufnummer nicht geeignet. Wenn ich aber über die Zeit den Call finde, dann kann ich mir auch die Details anzeigen lassen:
Allerdings sehen Sie auch hier schon einige Einschränkungen, z.B. sehe ich nur "Bot" und nicht den Namen der Call Queue und auch die Rufnummer des Anrufers ist hier aus Datenschutzgründen teilweise unkenntlich gemacht.
Abfrage per Graph
Damit war klar, dass eine einfache Abfrage per GUI oder Browser mich hier nicht weiter bringt. Sehr schnell bin ich dann auf folgende beide API-Aufrufe in Graph gestoßen.
- callRecord: getDirectRoutingCalls
https://docs.microsoft.com/en-us/graph/api/callrecords-callrecord-getdirectroutingcalls?view=graph-rest-1.0&tabs=http - callRecord: getPstnCalls
https://docs.microsoft.com/en-us/graph/api/callrecords-callrecord-getpstncalls?view=graph-rest-1.0&tabs=http
Ein Blick auf diese APIs zeigt, aber, dass ich als Anwender darauf gar nicht zugreifen kann.
Ich muss eine App in dem Tenant definieren, der ich die erforderlichen Rechte zuweise, z.B.:
Die App selbst muss ich auch authentifizieren. Dazu nutzt sie als "Benutzernamen" die AppID und als Geheimnis entweder ein Zertifikat oder für den Test reicht auch ein Kennwort. Zu den Details gibt es jede Menge anderen Seiten auf der MSFAQ und im Internet.
Token besorgen
Hinweis:
Ich beschreibe hier noch den manuellen Prozess. Mit der
Graph
PowerShell geht das natürlich auch:
Daher ist der erste Schritt einmal die Anmeldung, um ein Zugriffstoken zu erhalten. Den Prozess habe ich auf Graph Token und anderen Seiten beschrieben. Daher hier nur die Kurzfassung:
$LoginUrl="https://login.microsoftonline.com", $AppID="12345678-1234-1234-1234-1234567890ab", $AppSecret= "super geheimes secret der app", $TenantName="tenantname.onmicrosoft.com" $authresponse=Invoke-RestMethod ` -Uri "$($LoginUrl)/$($TenantName)/oauth2/v2.0/token" ` -Method POST ` -ContentType "application/x-www-form-urlencoded" ` -body "client_id=$($AppID) &scope=https%3A%2F%2Fgraph.microsoft.com%2F.default &client_secret=$($AppSecret) &grant_type=client_credentials &api-version=1.0" $accesstoken= $authresponse.access_token
Calls abrufen
Mit dem Access-Token kann ich dann direkt die APIs aufrufen. Ich muss allerdings als Parameter den Zeitraum angeben. Der Code nutzt den vorherigen Tag.
$datefilter = "(fromDateTime=$((get-date).adddays(-2).ToString("yyyy-MM-dd")),toDateTime=$((get-date).adddays(-1).ToString("yyyy-MM-dd")))" $pstncalls = Invoke-RestMethod ` -Uri ('https://graph.microsoft.com/v1.0/communications/callRecords/getPstnCalls'+$datefilter) ` -Method GET ` -Header @{ 'Authorization' = "Bearer $($accesstoken)"} Write-host "PSTNCall Count $($pstncalls.'@odata.count')" $drcalls = Invoke-RestMethod ` -Uri ('https://graph.microsoft.com/v1.0/communications/callRecords/getDirectRoutingCalls'+$datefilter) ` -Method GET ` -Header @{ 'Authorization' = "Bearer $($accesstoken)"} Write-host "PSTNCall Count $($drcalls.'@odata.count')"
Beide Ausgaben halten im Property "Value" eine Liste der Calls. Leider sind die Properties nicht identisch, so dass Sie hier noch etwas nacharbeiten müssen. Ein DirectRouting-Call sieht wie folgt aus:
PS C:\> $drcalls.value[0] id : 12345678-1234-1234-1234-1234567890ab correlationId : 12345678-1234-1234-1234-1234567890ab userId : 12345678-1234-1234-1234567890ab userPrincipalName : Demouser1@msxfaq.de userDisplayName : DemoUser1 startDateTime : inviteDateTime : 09.05.2022 06:00:26 failureDateTime : 09.05.2022 06:00:36 endDateTime : duration : 0 callType : ByotIn successfulCall : False callerNumber : +495251304*** calleeNumber : +4952579388 mediaPathLocation : ukwe signalingLocation : EUNO finalSipCode : 487 callEndSubReason : 540200 finalSipCodePhrase : Call completed elsewhere trunkFullyQualifiedDomainName : sbc.msxfaq.de mediaBypassEnabled : True
Aber auch wenn Sie keine Microsoft Dialpläne nutzen, können Sie PSTN-Calls erhalten. Das sind z.B. Konferenzeinwahlen über die Microsoft-Rufnummern.
PS C:\group\Technik\Skripte\Get-TeamsCallIDs> $pstncalls.value[0] id : 12345678-1234-1234-1234-1234567890ab callId : 123456789_123456789@80.169.27.117 userId : 12345678-1234-1234-1234-1234567890ab userPrincipalName : Demouse1@msxfaq.de userDisplayName : DemoUser startDateTime : 09.05.2022 11:01:10 endDateTime : 09.05.2022 11:37:48 duration : 2198 charge : 0 callType : conf_in currency : EUR calleeNumber : +4969677765841 usageCountryCode : DE tenantCountryCode : DE connectionCharge : 0 callerNumber : +4952579388*** destinationContext : destinationName : Germany conferenceId : 12345678 licenseCapability : MCOMEETADD inventoryType : Service operator : callDurationSource : microsoft
Sie sehen aber auch hier dass die Daten auch hier beschnitten sind. Der Anrufer wird nur verkürzt angezeigt und Details über den Anruf bekommen wir so natürlich nicht
Details mit CallID
Wenn Sie dann die CallID zu einem Anruf haben, dann können Sie per Graph über die "/communications/callrecords"-API sehr einfach weitere Details abfragen
- Graph Get-Callrecord
- Get callRecord
https://docs.microsoft.com/en-us/graph/api/callrecords-callrecord-get
Meine App braucht dazu natürlich wieder die Berechtigungen "CallRecords.Read.All" und muss eine Call-ID in der URL mitgeben.
Es gibt leider hier keine Option, mit "*" o.ä. alle Calls zu bekommen. Diese API funktioniert immer nur genau mit einer gültigen CallID, die zum Tenant passen muss und nicht länger als 60 Tage in er Vergangenheit liegt
Die CallID kan ich aus der Liste entnehmen, die ich im vorigen Abschnitt ermittelt habe. Beim DirectRouting-Call ist es die "correlationID"
$calldetail = Invoke-RestMethod ` -Uri ('https://graph.microsoft.com/v1.0/communications/callRecords/'+$callid+'?$expand=sessions($expand=segments)') ` -Method GET ` -Header @{ 'Authorization' = "Bearer $($accesstoken)"}
Auch das ist auch per Graph PowerShell möglich:
Import-Module Microsoft.Graph.CloudCommunications Connect-MgGraph Get-MgCommunicationCallRecord -CallRecordId $callRecordId
Die Rückgabe ist dann eine JSON-Struktur, die sich in Teilen wiederholt.
Auf die einzelnen Felder und deren Bedeutung gehe ich auf Graph Get-Callrecord genauer ein.
Einschränkung
Über den hier beschrieben Weg kann ich zumindest im Mai 2022 leider nur Calls ermitteln, die über Direct Routing, Operator Connect und Microsoft Dialpläne im Tenant angekommen sind. Ich sehe aber keine Verbindungen der Anwender in Meetings im eigenen oder fremden Tenant und auch keine 1:1 Teams-Gespräche zwischen Personen oder per Federation. Wenn Sie die CallID zu diesen Verbindungen haben, dann können Sie natürlich dann auch die Details abfragen aber solange es keine API zur Auflistung der Anrufe pro Anwender oder aller Anwender gibt, können Sie diese Daten nur asynchron über einen Graph CallReport Webhook stark verzögert oder inoffizielle APIs, die z.B. das Teams Admin Center nutzt erhalten.
Weitere Links
- Graph Token
- Graph und Kennworte
- Graph Berechtigungen
- Graph PowerShell
- callRecord: getDirectRoutingCalls
https://docs.microsoft.com/en-us/graph/api/callrecords-callrecord-getdirectroutingcalls?view=graph-rest-1.0&tabs=http - callRecord: getPstnCalls
https://docs.microsoft.com/en-us/graph/api/callrecords-callrecord-getpstncalls?view=graph-rest-1.0&tabs=http