I received an email recently ‘Hey Martin, I wanted to call Bob on his mobile phone from Skype for Business this morning. The call didn’t complete, gave me an error. I was at my hotel at that point in time, can you tell me why this call didn’t go through? I’m travelling right now with no coverage, love to hear from you what was going on. Thanks, Joe.’ So far so good, now I need to explain that Joe is the CIO of that company and wanted to call Bob, the CEO. He’s travelling so I won’t be able to get any further details from him, nor will I have access to his machine to get any client-side logs for troubleshooting. It would be just too easy to go to the EventLog of that machine and find an event Source=Lync, EventID=11 highlighting the exact reason. *(see end of blog post)
To start troubleshooting I need logfiles to understand what is going on. I have no chance to get client-side logs as I cannot contact him, what about server-side logs? In an on-premises environment we could leverage the Centralized Logging Service (CLS) to retrieve call details from the Always On scenario. Remember, this scenario is designed to run always so that you access to the log files after an issue occurred without the need to reproduce the scenario. See https://technet.microsoft.com/en-us/library/jj687958.aspx for more details on this.
Joe is hosted online leveraging Cloud Connector Edition for PSTN connectivity, so CLS logger won’t help here. But there’s something similar that I can do, I can retrieve logs from the service by leveraging the Get-CsUserSession cmdlet.
Let’s see what I have, I know the user (Joe) and the time (this morning) and I am a Skype for Business admin in that tenant, that’s all I need.
Instead of specifying a specific date I used the Get-Date cmdlet and subtracted four hours as Joe’s failed call is less than four hours ago. I did not specify the -EndTime parameter to limit the amount of data further. This cmdlet returns me a lot of SIP signalling that Joe initiated:
Now that is great but a pretty long list. So let’s store everything in a variable for easier processing.
To find the event I am interested in I need to find the call that Joe was trying to start. To do so, I use the MediaTypesDescription Parameter. Let’s see what MediaTypes are available for my set of logs:
Joe reported that he wanted to place an audio call, so let’s get details for the audio call:
Okay, so the call was process but the Gateway responded with a 403 forbidden. After checking the gateway configuration associated to his Cloud Connector Edition it turns out that outbound call routing wasn’t setup correctly to support number to Germany (+49). After fixing this configuration issue Joe can place outbound calls to Germany.
Other things you can do with Get-CsUserSession
The other interesting thing is that this also allows you to access the QoEReport (aka VQReport) that is sent after every call, just find the QoEReport property of a completed audio call. This is useful in a scenario where you need to troubleshoot quality or call reliability issues for a specific user.
Things to be aware of
The Get-CsUserSession cmdlet is very powerful to troubleshoot issues of an individual user. Some PII data (like phone numbers in this example) is masked and you can only query for data of a single user at any point in time. But this cmdlet does expose quite sensitive information, therefore only Skype for Business admins have access to this cmdlet. Very like access to CLS or CDR/QoE database access for an on-premises environment.
There’s only a short lag of usually less than 5 minutes before the data is available and data is available for up to 365 days (starting from August 2016 onwards).
Here’s the shortcut if I had access to Joe’s machine with ‘Also collect troubleshooting info using Windows Event Logging’ being turned on in the Skype for Business General settings. Please note that Joe has a PC with German language installed, but as you can see the error message itself is still English.