#region Log Analysis Scripts
function Find-LIMSErrors {
param(
[string]$LogPath = "C:\inetpub\logs\LogFiles\W3SVC1",
[int]$Hours = 24,
[string]$OutputPath = "C:\temp\lims_analysis.txt"
)
$startTime = (Get-Date).AddHours(-$Hours)
$results = @()
# Common LIMS error patterns
$patterns = @{
"Database_Timeout" = "timeout|deadlock|database.*error"
"File_Upload_Issues" = "upload.*fail|file.*error|413|Request Entity Too Large"
"Authentication_Problems" = "401|403|authentication.*fail|login.*error"
"Session_Issues" = "session.*timeout|session.*invalid|viewstate"
"Integration_Errors" = "instrument.*error|integration.*fail|api.*error"
"Memory_Issues" = "out.*memory|memory.*exception|w3wp.*crash"
"Slow_Requests" = "time-taken" # Will filter >30000ms separately
}
Get-ChildItem "$LogPath\*.log" | Where-Object { $_.LastWriteTime -ge $startTime } | ForEach-Object {
$content = Get-Content $_.FullName | Where-Object { $_ -notlike "#*" }
$fields = (Get-Content $_.FullName | Where-Object { $_ -like "#Fields:*" } | Select-Object -First 1) -replace "#Fields: ", "" -split " "
foreach ($line in $content) {
$values = $line -split " "
if ($values.Length -ge $fields.Length) {
$entry = @{}
for ($i = 0; $i -lt $fields.Length; $i++) {
$entry[$fields[$i]] = $values[$i]
}
# Check for slow requests (>30 seconds)
if ($entry['time-taken'] -and [int]$entry['time-taken'] -gt 30000) {
$results += [PSCustomObject]@{
Timestamp = "$($entry['date']) $($entry['time'])"
Type = "Slow_Request"
Details = "URL: $($entry['cs-uri-stem']) | Time: $($entry['time-taken'])ms | Status: $($entry['sc-status'])"
IP = $entry['c-ip']
UserAgent = $entry['cs(User-Agent)']
}
}
# Check for error patterns
foreach ($pattern in $patterns.GetEnumerator()) {
$lineText = $line.ToLower()
if ($lineText -match $pattern.Value -and $entry['sc-status'] -match "^[45]") {
$results += [PSCustomObject]@{
Timestamp = "$($entry['date']) $($entry['time'])"
Type = $pattern.Key
Details = "URL: $($entry['cs-uri-stem']) | Status: $($entry['sc-status']) | Bytes: $($entry['sc-bytes'])"
IP = $entry['c-ip']
UserAgent = $entry['cs(User-Agent)']
}
}
}
}
}
}
# Generate report
$report = @"
LIMS Troubleshooting Report - Last $Hours Hours
Generated: $(Get-Date)
========================================
SUMMARY:
"@
$results | Group-Object Type | Sort-Object Count -Descending | ForEach-Object {
$report += "`n$($_.Name): $($_.Count) occurrences"
}
$report += "`n`nDETAILED ERRORS:`n"
$results | Sort-Object Timestamp -Descending | ForEach-Object {
$report += "$($_.Timestamp) [$($_.Type)] $($_.Details) (IP: $($_.IP))`n"
}
$report | Out-File $OutputPath
Write-Host "Report saved to: $OutputPath" -ForegroundColor Green
return $results
}
function Test-LIMSDatabase {
param(
[string]$ConnectionString,
[string]$TestQuery = "SELECT 1"
)
try {
$connection = New-Object System.Data.SqlClient.SqlConnection($ConnectionString)
$connection.Open()
$command = New-Object System.Data.SqlClient.SqlCommand($TestQuery, $connection)
$result = $command.ExecuteScalar()
$connection.Close()
return [PSCustomObject]@{
Status = "Success"
ResponseTime = (Measure-Command { $command.ExecuteScalar() }).TotalMilliseconds
Timestamp = Get-Date
}
}
catch {
return [PSCustomObject]@{
Status = "Failed"
Error = $_.Exception.Message
Timestamp = Get-Date
}
}
}
function Monitor-LIMSAppPool {
param(
[string]$AppPoolName,
[int]$IntervalSeconds = 30,
[int]$DurationMinutes = 60
)
Import-Module WebAdministration
$endTime = (Get-Date).AddMinutes($DurationMinutes)
$results = @()
while ((Get-Date) -lt $endTime) {
$pool = Get-IISAppPool -Name $AppPoolName
$process = Get-Process -Name "w3wp" | Where-Object {
(Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine -like "*$AppPoolName*"
}
$result = [PSCustomObject]@{
Timestamp = Get-Date
State = $pool.State
ProcessId = if ($process) { $process.Id } else { "N/A" }
WorkingSet = if ($process) { [math]::Round($process.WorkingSet64 / 1MB, 2) } else { 0 }
CPU = if ($process) { $process.CPU } else { 0 }
Handles = if ($process) { $process.Handles } else { 0 }
Threads = if ($process) { $process.Threads.Count } else { 0 }
}
$results += $result
Write-Host "$(Get-Date -Format 'HH:mm:ss') - Pool: $($result.State) | Memory: $($result.WorkingSet)MB | PID: $($result.ProcessId)"
Start-Sleep $IntervalSeconds
}
return $results
}
function Monitor-LIMSFileSystem {
param(
[string[]]$Paths = @("C:\inetpub\wwwroot\uploads", "C:\Windows\Temp", "C:\inetpub\temp"),
[int]$ThresholdMB = 1000
)
$results = @()
foreach ($path in $Paths) {
if (Test-Path $path) {
$files = Get-ChildItem $path -Recurse -File | Where-Object { $_.LastWriteTime -gt (Get-Date).AddHours(-24) }
$totalSize = ($files | Measure-Object Length -Sum).Sum / 1MB
$oldFiles = Get-ChildItem $path -Recurse -File | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) }
$results += [PSCustomObject]@{
Path = $path
RecentFiles = $files.Count
TotalSizeMB = [math]::Round($totalSize, 2)
OldFiles = $oldFiles.Count
Status = if ($totalSize -gt $ThresholdMB) { "WARNING" } else { "OK" }
}
}
}
return $results
}
function Start-LIMSMonitoring {
param(
[string]$LogPath = "C:\inetpub\logs\LogFiles\W3SVC1",
[string[]]$AlertPatterns = @("500", "timeout", "error", "exception", "fail")
)
$logFile = Get-ChildItem $LogPath -Filter "*.log" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
Write-Host "Monitoring LIMS errors in real-time..." -ForegroundColor Yellow
Write-Host "Log file: $($logFile.FullName)" -ForegroundColor Cyan
Write-Host "Press Ctrl+C to stop monitoring" -ForegroundColor Gray
Get-Content $logFile.FullName -Tail 0 -Wait | ForEach-Object {
$line = $_
foreach ($pattern in $AlertPatterns) {
if ($line -match $pattern) {
$timestamp = Get-Date -Format "HH:mm:ss"
Write-Host "[$timestamp] ALERT: $line" -ForegroundColor Red
# Log to file for later analysis
"[$timestamp] $line" | Add-Content "C:\temp\lims_alerts.log"
break
}
}
}
}
#endregion
#region Performance Analysis
function Analyze-LIMSPerformance {
param(
[string]$LogPath = "C:\inetpub\logs\LogFiles\W3SVC1",
[int]$Hours = 24
)
$startTime = (Get-Date).AddHours(-$Hours)
$slowRequests = @()
Get-ChildItem "$LogPath\*.log" | Where-Object { $_.LastWriteTime -ge $startTime } | ForEach-Object {
$content = Get-Content $_.FullName
$fields = ($content | Where-Object { $_ -like "#Fields:*" } | Select-Object -First 1) -replace "#Fields: ", "" -split " "
$content | Where-Object { $_ -notlike "#*" -and $_ -ne "" } | ForEach-Object {
$values = $_ -split " "
if ($values.Length -ge $fields.Length) {
$entry = @{}
for ($i = 0; $i -lt $fields.Length; $i++) {
$entry[$fields[$i]] = $values[$i]
}
if ($entry['time-taken'] -and [int]$entry['time-taken'] -gt 5000) {
$slowRequests += [PSCustomObject]@{
URL = $entry['cs-uri-stem']
TimeTaken = [int]$entry['time-taken']
Status = $entry['sc-status']
Method = $entry['cs-method']
IP = $entry['c-ip']
Timestamp = "$($entry['date']) $($entry['time'])"
}
}
}
}
}
# Analysis
Write-Host "`nSLOW REQUEST ANALYSIS (>5 seconds):" -ForegroundColor Yellow
$slowRequests | Group-Object URL | Sort-Object Count -Descending | Select-Object -First 10 | ForEach-Object {
$avg = ($_.Group | Measure-Object TimeTaken -Average).Average
Write-Host "$($_.Name): $($_.Count) requests, avg: $([math]::Round($avg/1000,2))s" -ForegroundColor Cyan
}
return $slowRequests
}
function Get-LIMSMemoryUsage {
param(
[string]$AppPoolName,
[int]$Samples = 10,
[int]$IntervalSeconds = 30
)
$results = @()
for ($i = 1; $i -le $Samples; $i++) {
$process = Get-Process -Name "w3wp" | Where-Object {
(Get-WmiObject Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine -like "*$AppPoolName*"
}
if ($process) {
$results += [PSCustomObject]@{
Sample = $i
Timestamp = Get-Date
WorkingSetMB = [math]::Round($process.WorkingSet64 / 1MB, 2)
PrivateMemoryMB = [math]::Round($process.PrivateMemorySize64 / 1MB, 2)
VirtualMemoryMB = [math]::Round($process.VirtualMemorySize64 / 1MB, 2)
PagedMemoryMB = [math]::Round($process.PagedMemorySize64 / 1MB, 2)
Handles = $process.Handles
Threads = $process.Threads.Count
}
Write-Host "Sample $i/$Samples - Working Set: $([math]::Round($process.WorkingSet64 / 1MB, 2))MB"
}
if ($i -lt $Samples) { Start-Sleep $IntervalSeconds }
}
return $results
}
#endregion
#region Network and Dependencies
function Test-LIMSDependencies {
param(
[hashtable]$Dependencies = @{
"Database" = @{ Type = "SQL"; Server = "localhost"; Port = 1433 }
"FileServer" = @{ Type = "SMB"; Server = "fileserver.domain.com"; Share = "\\fileserver\lims" }
"EmailServer" = @{ Type = "SMTP"; Server = "mail.domain.com"; Port = 25 }
"WebService" = @{ Type = "HTTP"; URL = "https://api.vendor.com/health" }
}
)
$results = @()
foreach ($dep in $Dependencies.GetEnumerator()) {
$name = $dep.Key
$config = $dep.Value
try {
switch ($config.Type) {
"SQL" {
$connection = New-Object System.Net.Sockets.TcpClient
$connection.Connect($config.Server, $config.Port)
$connection.Close()
$status = "Available"
}
"SMB" {
$test = Test-Path $config.Share
$status = if ($test) { "Available" } else { "Unavailable" }
}
"SMTP" {
$connection = New-Object System.Net.Sockets.TcpClient
$connection.Connect($config.Server, $config.Port)
$connection.Close()
$status = "Available"
}
"HTTP" {
$response = Invoke-WebRequest $config.URL -UseBasicParsing -TimeoutSec 10
$status = if ($response.StatusCode -eq 200) { "Available" } else { "Error: $($response.StatusCode)" }
}
}
}
catch {
$status = "Failed: $($_.Exception.Message)"
}
$results += [PSCustomObject]@{
Dependency = $name
Type = $config.Type
Status = $status
Timestamp = Get-Date
}
}
return $results
}
#endregion
#region Event Log Analysis
function Get-LIMSEventLogs {
param(
[int]$Hours = 24,
[string[]]$LogNames = @("Application", "System", "Security")
)
$startTime = (Get-Date).AddHours(-$Hours)
$events = @()
foreach ($logName in $LogNames) {
$logEvents = Get-WinEvent -FilterHashtable @{
LogName = $logName
StartTime = $startTime
Level = @(1,2,3) # Critical, Error, Warning
} -ErrorAction SilentlyContinue | Where-Object {
$_.Message -match "IIS|w3wp|application pool|ASP.NET|SQL|LIMS" -or
$_.Id -in @(1000, 1001, 1002, 1309, 2001, 2002, 5011, 5186)
}
$events += $logEvents
}
return $events | Sort-Object TimeCreated -Descending | Select-Object -First 50
}
#endregion
<#
QUICK TROUBLESHOOTING WORKFLOW:
1. Check for recent errors:
Find-LIMSErrors -Hours 2
2. Monitor app pool health:
Monitor-LIMSAppPool -AppPoolName "YourLIMSAppPool" -DurationMinutes 10
3. Test dependencies:
Test-LIMSDependencies
4. Check performance:
Analyze-LIMSPerformance -Hours 4
5. Real-time monitoring:
Start-LIMSMonitoring
6. Check system events:
Get-LIMSEventLogs -Hours 4 | Format-Table TimeCreated, LevelDisplayName, Id, Message -Wrap
#>