Powershell : Analyse Teams for Rooms Diagnostic Logs

I had a problem where a Teams for Rooms device, on Android was going offline all the time which got me curious as to why to from the Team Admin centre navigate to Teams Devices > Teams Rooms on Android as below:


Then locate your device that is not working or going Offline the choose the "History" option then from here you need to find the date that the device went "Offline" as you can see below in the greenbox:


Then we want to download this file, this will be the full diagnostic file for the device itself which should in turn tell you if there are any issues with the room, but there is lots of data to navigate though depending on the data that you download and the type of diagnostics.

Below are some example files you can download, the top file is around the time we had the issue where as the bottom file is the full diagnostics from all components, notice the size differences between them.


Example scan of zip file

This is what the script looks like when it is looking though the log files, it automatically takes the latest zip file in the current folder:



Normal : Log File

First lets look at the larger of the two files, this was in a know good state, so this should return as having no issues so lets see what the script reports:

Teams Room Device Diagnostics Analysis Report
==========================================
Generated: 12/02/2024 13:06:33
Analyzing file: 1732583698_TeamsLogs-1732553735235.zip

Summary:
--------
Fatal Errors: 0
Critical Errors: 0
Errors: 0
Warnings: 0
Network Issues: 0
Offline Events: 0
Authentication Events: 0

Offline : Log File

So lets look at the report for the time where the device was "off the network" this is the smaller report as it would not obtain the larger report due to being offline:

Teams Room Device Diagnostics Analysis Report
==========================================
Generated: 12/02/2024 10:13:18
Analyzing file: 1732497177_44-73-D6-C8-08-B9.1732497119289.updatelogs.zip

Summary:
--------
Total Errors Found: 746
Total Network Issues: 1
Total Offline Events: 2

Network Issues:
-------------
- IP address

Offline Events:
-------------
- Disconnected from Audio Service!


This is very accurate to what you observed locally in the meeting room, so that summary will also have the detailed information shown for further diagnostics, let take a look at this now below.

Detailed Error Extraction

You can see lots of errors (in bold) linked to not being on the network which is what would cause the issue experienced on the day.

 - Exception: IBaseService Service is not ready
 - Exception() :: mIsIgnoreException is [true] :: skipped
 - Exception: Service interface was null in service manager, for class=[com.logitech.service.modeservice.IModeService]
 - Exception: Failed to prepare /sdcard/Android/data/com.logitech.service.policy/files
 - Exception: /mnt/vendor/persist/data/properties
 - Exception: End of input at character 0 of
 - Exception: WIFI_AP_STATE is out of bounds: 0
 - exception android.provider.Settings$SettingNotFoundException: ims_profile_override
 - Exception(64, "Machine is not on the network") <0.04ms>
 - Exception adding interface: java.lang.IllegalStateException: android.os.ServiceSpecificException:
Machine is not on the network (code 64)
 - Exception(64, "Machine is not on the network") <0.03ms>
 - Exception in addRoute for non-gateway: java.lang.IllegalStateException:
android.os.ServiceSpecificException: Machine is not on the network (code 64)
 - Exception in addRoute for gateway: java.lang.IllegalStateException:
android.os.ServiceSpecificException: Machine is not on the network (code 64)
 - Exception(64, "Machine is not on the network") <0.18ms>
 - Exception: Machine is not on the network (code 64)
 - Exception(64, "Machine is not on the network") <0.12ms>

Then it tries to talk to the internet without any Internet connection and fails to talk on SSL:

 - Exception: Read error: ssl=0x7d7b726f08: I/O error during system call, Connection reset by peer
 - Exception: Read error: ssl\u003d0x7d7b726f08: I/O error during system call, Connection reset by peer\n\tat com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method)\n\tat com.android.org.conscrypt.NativeSsl.read(NativeSsl.java:411)\n\tat com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read(ConscryptFileDescriptorSocket.java:549)\n\tat okio.InputStreamSource.read(JvmOkio.kt:93)\n\tat okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:153)\n\tat okio.RealBufferedSource.request(RealBufferedSource.kt:209)\n\tat okio.RealBufferedSource.require(RealBufferedSource.kt:202)\n\tat okhttp3.internal.http2.Http2Reader.nextFrame(Http2Reader.kt:90)\n\tat okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:625)\n\tat okhttp3.internal.http2.Http2Connection$ReaderRunnable.invoke(Http2Connection.kt:616)\n\tat okhttp3.internal.concurrent.TaskQueue$execute$1.runOnce(TaskQueue.kt:106)\n\tat okhttp3.internal.concurrent.TaskRunner.runTask(TaskRunner.kt:122)\n\tat okhttp3.internal.concurrent.TaskRunner.access$runTask

Script : TeamsAnalysis.ps1

# Teams Room Device Diagnostics Analysis Script
param(
    [Parameter(Mandatory=$false)]
    [string]$OutputPath = "TeamsRoomAnalysis.txt"
)

# Find the latest zip file in the current directory
$latestZip = Get-ChildItem -Path $PWD -Filter "*.zip" | 
    Sort-Object LastWriteTime -Descending | 
    Select-Object -First 1

if (-not $latestZip) {
    Write-Host "No diagnostic zip files found in the current directory." -ForegroundColor Red
    Write-Host "Please download the device diagnostics from the Teams Admin Center and place it in this directory." -ForegroundColor Yellow
    exit
}

Write-Host "Found diagnostic file: $($latestZip.Name)" -ForegroundColor Green
$ZipPath = $latestZip.FullName

# Initialize results arrays
$fatalErrors = @()
$criticalErrors = @()
$errors = @()
$warnings = @()
$networkIssues = @()
$offlineEvents = @()
$systemStatus = @()
$authEvents = @()

# Pattern definitions
$patterns = @{
    Fatal = '\[Fatal\].*|Fatal Error:.*|System\.Fatal.*|FATAL:.*'
    Critical = '\[Critical\].*|Critical Error:.*|CRITICAL:.*'
    Error = '\[Error\].*|Error:.*|Failed to.*|Exception.*|Connection lost.*|Timeout.*|Authentication failed.*'
    Warning = '\[Warn\].*|Warning:.*|WARN:.*'
    Network = 'Network connectivity changed.*|DNS resolution failed.*|Network adapter.*|IP address.*|Ping failed.*|SignInState:.*SignedOut|NetworkConnectionStatus:.*|Cannot connect to.*|Certificate validation.*|\[Network\].*'
    Auth = 'Authentication.*|Authorization.*|Token.*|Credential.*|Sign[- ]in.*|Login.*'
    Offline = 'Device offline.*|Connection terminated.*|Lost connection.*|Disconnected from.*|Session ended.*|SignInState: SignedOut|Device State:.*Offline'
}

function Get-LogEvents {
    param (
        [string]$Content,
        [string]$Pattern
    )   
    if ([string]::IsNullOrEmpty($Content)) { return @() }   
    $matches = [regex]::Matches($Content, $Pattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
    return @($matches | ForEach-Object { $_.Value.Trim() } | Select-Object -Unique)
}
try {
    # Create temp directory
    $tempPath = Join-Path $env:TEMP "TeamsRoomDiagnostics"
    if (Test-Path $tempPath) {
        Remove-Item $tempPath -Recurse -Force
    }
    New-Item -ItemType Directory -Path $tempPath | Out-Null

    # Extract zip file
    Write-Host "Extracting diagnostic files..." -ForegroundColor Yellow
    Expand-Archive -Path $ZipPath -DestinationPath $tempPath -Force

    # Get all log file
    $logFiles = Get-ChildItem -Path $tempPath -Recurse | Where-Object { $_.Extension -in ".log", ".json" }

    # Process each file
    foreach ($file in $logFiles) {
        Write-Host "Analyzing file: $($file.Name)" -ForegroundColor Cyan
        $content = Get-Content $file.FullName -Raw -ErrorAction SilentlyContinue
        if ($file.Extension -eq ".log") {
            $fatalErrors += Get-LogEvents -Content $content -Pattern $patterns.Fatal
            $criticalErrors += Get-LogEvents -Content $content -Pattern $patterns.Critical
            $errors += Get-LogEvents -Content $content -Pattern $patterns.Error
            $warnings += Get-LogEvents -Content $content -Pattern $patterns.Warning
            $networkIssues += Get-LogEvents -Content $content -Pattern $patterns.Network
            $offlineEvents += Get-LogEvents -Content $content -Pattern $patterns.Offline
            $authEvents += Get-LogEvents -Content $content -Pattern $patterns.Auth
        }
        elseif ($file.Extension -eq ".json") {
            try {
                $jsonContent = $content | ConvertFrom-Json
                if ($jsonContent.networkConfig) {
                    $systemStatus += "Network Configuration: $($jsonContent.networkConfig | ConvertTo-Json -Compress)"
                }
                if ($jsonContent.systemHealth) {
                    $systemStatus += "System Health: $($jsonContent.systemHealth | ConvertTo-Json -Compress)"
                }
            }
            catch {
                $errors += "Error parsing JSON file $($file.Name): $_"
            }
        }
    }

    # Generate report
    $report = @"
Teams Room Device Diagnostics Analysis Report
==========================================
Generated: $(Get-Date)
Analyzing file: $($latestZip.Name)

Summary:
--------
Fatal Errors: $($fatalErrors.Count)
Critical Errors: $($criticalErrors.Count)
Errors: $($errors.Count)
Warnings: $($warnings.Count)
Network Issues: $($networkIssues.Count)
Offline Events: $($offlineEvents.Count)
Authentication Events: $($authEvents.Count)

Detailed Findings:
----------------
Fatal Errors:
------------
$(($fatalErrors | Sort-Object -Unique) -join "`n")
Critical Errors:
-------------
$(($criticalErrors | Sort-Object -Unique) -join "`n")
Errors:
-------
$(($errors | Sort-Object -Unique) -join "`n")
Warnings:
--------
$(($warnings | Sort-Object -Unique) -join "`n")
Network Issues:
-------------
$(($networkIssues | Sort-Object -Unique) -join "`n")
Offline Events:
-------------
$(($offlineEvents | Sort-Object -Unique) -join "`n")
System Status:
------------
$(($systemStatus | Sort-Object -Unique) -join "`n")
Authentication Events:
-------------------
$(($authEvents | Sort-Object -Unique) -join "`n")
"@
    # Save report
    $report | Out-File -FilePath $OutputPath -Encoding UTF8
    Write-Host "Analysis report saved to: $OutputPath" -ForegroundColor Green
}
catch {
    Write-Error "Error processing diagnostic files: $_"
    Write-Host "Stack Trace: $($_.ScriptStackTrace)" -ForegroundColor Red
}
finally {
    if (Test-Path $tempPath) {
        Remove-Item $tempPath -Recurse -Force -ErrorAction SilentlyContinue
    }
}

Previous Post Next Post

نموذج الاتصال