General Call Record Understanding
We're using the Microsoft Teams Graph API to analyse calls made through Microsoft Teams. We've setup a notification web hook that subscribes to the call records using the Graph API and then uses some more API calls to retrieve the call and user information for the received call. That's all working quite well (despite the time delay - but that's OK). What we struggle with ist the information retrieved from the Call Record API. We receive following data for example (UUIDs, names and phone numbers anonymised):
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#communications/callRecords(sessions())/$entity",
"id": "00000000-0000-0000-0000-000000000000",
"version": 1,
"type": "groupCall",
"modalities": [
"audio",
"screenSharing"
],
"lastModifiedDateTime": "2021-10-18T11:16:03.5458861Z",
"startDateTime": "2021-10-18T10:55:33.712657Z",
"endDateTime": "2021-10-18T10:57:23.1331192Z",
"joinWebUrl": null,
"organizer": {
"user": null,
"acsUser": null,
"spoolUser": null,
"phone": {
"id": "+49XXXXXXXX",
"displayName": null,
"tenantId": null
},
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null
},
"participants": [
{
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": "Firstname Lastname",
"tenantId": "00000000-0000-0000-0000-000000000000"
}
},
{
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": null
}
},
{
"user": null,
"acsUser": null,
"spoolUser": null,
"phone": {
"id": "+49XXXXXXXX",
"displayName": null,
"tenantId": null
},
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null
},
{
"user": null,
"acsUser": null,
"spoolUser": null,
"phone": {
"id": "+49XXXXXXXX",
"displayName": null,
"tenantId": null
},
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null
},
{
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": "00000000-0000-0000-0000-000000000000"
}
},
{
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": "00000000-0000-0000-0000-000000000000"
}
}
],
"sessions#odata.context": "https://graph.microsoft.com/v1.0/$metadata#communications/callRecords('00000000-0000-0000-0000-000000000000')/sessions",
"sessions": [
{
"id": "403139dd-b5c1-457e-a5aa-b07e8c2bcc58",
"modalities": [
"audio"
],
"startDateTime": "2021-10-18T10:55:40.552989Z",
"endDateTime": "2021-10-18T10:57:23.1331192Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": null
}
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.serviceEndpoint",
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
}
}
},
{
"id": "b538ce68-cd12-4b22-b127-69b73a183e78",
"modalities": [
"audio"
],
"startDateTime": "2021-10-18T10:55:41.5686724Z",
"endDateTime": "2021-10-18T10:57:23.1331192Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": null
}
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.serviceEndpoint",
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
}
}
},
{
"id": "beb5c088-70f6-4b77-8a47-fbef0f3b6707",
"modalities": [
"audio"
],
"startDateTime": "2021-10-18T10:55:36.2402487Z",
"endDateTime": "2021-10-18T10:57:23.055049Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"user": null,
"acsUser": null,
"spoolUser": null,
"phone": {
"id": "+49XXXXXXXX",
"displayName": null,
"tenantId": null
},
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.serviceEndpoint",
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
}
}
},
{
"id": "c1fce6ee-8ac6-4680-a079-8384665aeba0",
"modalities": [
"audio"
],
"startDateTime": "2021-10-18T10:55:53.0392071Z",
"endDateTime": "2021-10-18T10:57:23.1331192Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": null
}
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.serviceEndpoint",
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
}
}
},
{
"id": "ce6e4e5d-77ff-421a-9b28-670dd691a119",
"modalities": [
"audio"
],
"startDateTime": "2021-10-18T10:55:36.2402487Z",
"endDateTime": "2021-10-18T10:55:52.4142559Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": "MicrosoftTeamsCallQueueService (20211014.1)",
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": "00000000-0000-0000-0000-000000000000"
}
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.serviceEndpoint",
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
}
}
},
{
"id": "00000000-0000-0000-0000-000000000000",
"modalities": [
"audio"
],
"startDateTime": "2021-10-18T10:55:33.712657Z",
"endDateTime": "2021-10-18T10:57:23.0157168Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"user": null,
"acsUser": null,
"spoolUser": null,
"phone": {
"id": "+49XXXXXXXX",
"displayName": null,
"tenantId": null
},
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": "MicrosoftTeamsCallQueueService (20211014.1)",
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
},
"identity": {
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": null,
"tenantId": "00000000-0000-0000-0000-000000000000"
}
}
}
},
{
"id": "e4f20c64-9343-4d67-b47b-9ba5e34ab373",
"modalities": [
"audio",
"screenSharing"
],
"startDateTime": "2021-10-18T10:55:51.8360806Z",
"endDateTime": "2021-10-18T10:57:23.1331192Z",
"failureInfo": null,
"caller": {
"#odata.type": "#microsoft.graph.callRecords.participantEndpoint",
"feedback": null,
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": "CallSignalingAgent (27/1.4.00.26376//;release_ktolskiy2/hook_R22.2021.22.01.56;releases/CL2021.R22)",
"applicationVersion": null,
"platform": "windows",
"productFamily": "teams"
},
"identity": {
"acsUser": null,
"spoolUser": null,
"phone": null,
"guest": null,
"encrypted": null,
"onPremises": null,
"acsApplicationInstance": null,
"spoolApplicationInstance": null,
"applicationInstance": null,
"application": null,
"device": null,
"user": {
"id": "00000000-0000-0000-0000-000000000000",
"displayName": "Firstname Lastname",
"tenantId": "00000000-0000-0000-0000-000000000000"
}
}
},
"callee": {
"#odata.type": "#microsoft.graph.callRecords.serviceEndpoint",
"userAgent": {
"#odata.type": "#microsoft.graph.callRecords.clientUserAgent",
"headerValue": null,
"applicationVersion": null,
"platform": "unknown",
"productFamily": "unknown"
}
}
}
]
}
To be able to get our heads around the data, we visualise the call sessions like this:
Our interpretation for this call is:
+49XXXXXXXX calls the Call Queue call queue at 12:55:33
at 12:55:51 Firstname Lastname picks up the call from the queue
the call ends at 12:57:23.
Is this correct?
Failure Info
Next thing we encountered is the failureInfo information on a call record session. For some calls that are listed as failed in the Teams Call Record CSV export (administration user interface) we receive no failure info (but the total call duration is 0 seconds), while for others that are listed as successful in the CSV export we receive a failure info such as
"failureInfo": {
"reason": "Other",
"stage": "callSetup"
}
These calls then have a sensible call duration.
Does anybody know of any issues with the failure information or what's the deal with this information?
We're analysing the calls rather extensively but currently we use our own interpretation of the call record sessions to determine what type of call it was, who picked up the call, who could have picked up the call, etc. But unfortunately there's not much information around (at least I could not find any) that describes the nature of these call record sessions: what they represent, what types of services we can encounter (bots, apps, etc.), which information you can extract from them and which not. Is just guessing at the moment for us.
I'd be really grateful for any hint, link, nudge in the right direction to get a better understanding of these call records.
How to deserialize below JSON?
When i am using below code
Response response=engine.getResponse(Method.GET,strURL,strBAUsername,strBAPassword,null,ContentType.JSON);
userEdit=response.as(TestUserRoleInfoList.class); // TestUserRoleInfoList is a POJO class
#JsonIgnoreProperties(ignoreUnknown=true)
public class TestUserRoleInfoList {
#JsonProperty("userRoleInfoList")
List<UserRoleInfo> userRoleInfo=new ArrayList<UserRoleInfo>();
public List<UserRoleInfo> getUserRoleInfo() {
return userRoleInfo;
}
public void setUserRoleInfo(List<UserRoleInfo> userRoleInfo) {
this.userRoleInfo = userRoleInfo;
}
}
Somehow it unable to parse Regions internal class. But i am least bothered. I need collectionRole fields.
How can i get the list of collection roles?
{
"id": 5595,
"userName": "abc",
"firstName": "abc",
"lastName": "ijk",
"additionalName": "Ernest",
"namePrefix": {
"id": null,
"prefix": null,
"createdAt": null,
"updatedAt": null
},
"nameSuffix": {
"id": null,
"suffix": null,
"createdAt": null,
"updatedAt": null
},
"emplId": "11111",
"workDayId": "11111",
"staffEmailAddress": null,
"facultyEmailAddress": "abc.xyz#xxxx.edu",
"userRoleInfoList": [
{
"userId": 5595,
"collectionRole": "program-chair",
"regions": [
{
"id": 1,
"region": "Germany 1",
"regionalDirectorFirstName": "aaaa",
"regionalDirectorLastName": "bbbb",
"associateDirectorFirstName": null,
"associateDirectorLastName": null,
"division": {
"id": 2,
"name": "Europe",
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
},
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
}
],
"school": {
"id": 3,
"name": "Arts and Sciences",
"dean": null,
"createdAt": null,
"updatedAt": null
},
"facultyPhoto": null,
"primary": false
},
{
"userId": 5595,
"collectionRole": "faculty",
"regions": [
{
"id": 3,
"region": "Germany 1",
"regionalDirectorFirstName": "aaaa",
"regionalDirectorLastName": "bbbb",
"associateDirectorFirstName": null,
"associateDirectorLastName": null,
"division": {
"id": 2,
"name": "Europe",
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
},
"deletedFlag": false,
"createdAt": null,
"updatedAt": null
}
],
"school": {
"id": 3,
"name": "Arts and Sciences",
"dean": null,
"createdAt": null,
"updatedAt": null
},
"facultyPhoto": null,
"primary": true
}
]
}
You can use org.json.JSONObject
Response response = when()
.get("api_url")
.then()
.extract().response();
JSONObject jsonObject = new JSONObject(response.getBody().asString());
JSONArray jsonArray = jsonObject.getJSONArray("userRoleInfoList");
List<String> stringList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
stringList.add(jsonArray.getJSONObject(i).getString("collectionRole"));
}
System.out.println(stringList);
This will output [program-chair, faculty]
Hi I am using swagger for documentation of my RESTful web service. wanted to know is there any way to remove the certain properties of objects from the json document response? I mean there are lots of properties that swagger gives for my method param objects and response model (e.g. notes, defaultValue, allowableValue, internalDescription etc.) that are not required for me and are null due to that the response is not much readable
For method params:
"parameters": [
{
"name": "someName1",
"description": null,
"notes": null,
"paramType": "path",
"defaultValue": null,
"allowableValues": null,
"required": true,
"allowMultiple": false,
"paramAccess": null,
"internalDescription": null,
"wrapperName": null,
"dataType": "string",
"valueTypeInternal": null
},
{
"name": "someName2",
"description": null,
"notes": null,
"paramType": "query",
"defaultValue": null,
"allowableValues": null,
"required": true,
"allowMultiple": false,
"paramAccess": null,
"internalDescription": null,
"wrapperName": null,
"dataType": "string",
"valueTypeInternal": null
}
],
-=============================================================================
For response model classes
"SomeResponseClass": {
"required": false,
"name": null,
"id": "SomeResponseClass",
"properties": {
"instanceVariable1": {
"required": false,
"name": null,
"id": null,
"properties": null,
"allowableValues": null,
"description": null,
"notes": null,
"access": null,
"default": null,
"additionalProperties": null,
"items": null,
"uniqueItems": false,
"type": "Date"
},
"instanceVariable2": {
"required": false,
"name": null,
"id": null,
"properties": null,
"allowableValues": null,
"description": null,
"notes": null,
"access": null,
"default": null,
"additionalProperties": null,
"items": null,
"uniqueItems": false,
"type": "double"
}
}
your JSON mapper is not configured to ignore null properties. You can easily address this as follows:
#Provider
#Produces(MediaType.APPLICATION_JSON)
public class JacksonJsonProvider extends JacksonJaxbJsonProvider {
private static ObjectMapper commonMapper = null;
public JacksonJsonProvider() {
if(commonMapper == null){
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
commonMapper = mapper;
}
super.setMapper(commonMapper);
}
}
Add this mapper to your scanning properties in the web.xml and the nulls will be gone.