Skip to content

Commit

Permalink
Read-DbaXEFile - Refactoring to get the command working again (#9007)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasjordan committed Jun 22, 2023
1 parent b094240 commit 9a49a6f
Showing 1 changed file with 71 additions and 63 deletions.
134 changes: 71 additions & 63 deletions public/Read-DbaXEFile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ function Read-DbaXEFile {
.DESCRIPTION
Read XEvents from a *.xel or *.xem file.
The file that the XESession is currently writing to can not be accessed and will be skipped using pipeline input from Get-DbaXESession.
.PARAMETER Path
The path to the *.xem or *.xem file. This is relative to the computer executing the command. UNC paths are supported.
Piping from Get-DbaXESession is also supported.
.PARAMETER Raw
If this switch is enabled, the Microsoft.SqlServer.XEvent.Linq.PublishedEvent enumeration object will be returned.
If this switch is enabled, an array of Microsoft.SqlServer.XEvent.XELite.XEvent objects will be returned.
.PARAMETER EnableException
By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
Expand Down Expand Up @@ -39,7 +43,7 @@ function Read-DbaXEFile {
Returns events from all .xel files in C:\temp\xe.
.EXAMPLE
PS C:\> Get-DbaXESession -SqlInstance sql2014 -Session deadlocks | Read-DbaXEFile
PS C:\> Get-DbaXESession -SqlInstance sql2019 -Session deadlocks | Read-DbaXEFile
Reads remote XEvents by accessing the file over the admin UNC share.
Expand All @@ -54,83 +58,87 @@ function Read-DbaXEFile {
)
process {
if (Test-FunctionInterrupt) { return }
foreach ($file in $path) {
foreach ($pathObject in $Path) {
# in order to ensure CSV gets all fields, all columns will be
# collected and output in the first (all all subsequent) object
$columns = @("name", "timestamp")

if ($file -is [System.String]) {
$currentfile = $file
#Variable marked as unused by PSScriptAnalyzer
#$manualadd = $true
} elseif ($file -is [System.IO.FileInfo]) {
$currentfile = $file.FullName
#Variable marked as unused by PSScriptAnalyzer
#$manualadd = $true
} else {
if ($file -isnot [Microsoft.SqlServer.Management.XEvent.Session]) {
Stop-Function -Message "Unsupported file type."
return
}

if ($file.TargetFile.Length -eq 0) {
Stop-Function -Message "This session does not have an associated Target File."
return
if ($pathObject -is [System.String]) {
$files = $pathObject
} elseif ($pathObject -is [System.IO.FileInfo]) {
$files = $pathObject.FullName
} elseif ($pathObject -is [Microsoft.SqlServer.Management.XEvent.Session]) {
if ($pathObject.TargetFile.Length -eq 0) {
Stop-Function -Message "The session [$pathObject] does not have an associated Target File." -Continue
}

$instance = [dbainstance]$file.ComputerName

$instance = [DbaInstance]$pathObject.ComputerName
if ($instance.IsLocalHost) {
$currentfile = $file.TargetFile
$targetFile = $pathObject.TargetFile
} else {
$currentfile = $file.RemoteTargetFile
$targetFile = $pathObject.RemoteTargetFile
}
}

$accessible = Test-Path -Path $currentfile
$whoami = whoami

if (-not $accessible) {
if ($file.Status -eq "Stopped") { continue }
Stop-Function -Continue -Message "$currentfile cannot be accessed from $($env:COMPUTERNAME). Does $whoami have access?"
}

if ($Raw) {
return (SqlServer.XEvent\Read-SqlXEvent -FileName $currentfile)
}

# use the SqlServer.XEvent\Read-SqlXEvent cmdlet from Microsoft
# because the underlying Class uses Tasks
# which is hard to handle in PowerShell

$enum = SqlServer.XEvent\Read-SqlXEvent -FileName $currentfile
$newcolumns = ($enum.Fields.Name | Select-Object -Unique)

$actions = ($enum.Actions.Name | Select-Object -Unique)
foreach ($action in $actions) {
$newcolumns += ($action -Split '\.')[-1]
$targetFile = $targetFile.Replace('.xel', '*.xel').Replace('.xem', '*.xem')
$files = Get-ChildItem -Path $targetFile | Sort-Object LastWriteTime
if ($pathObject.Status -eq 'Running') {
$files = $files | Select-Object -SkipLast 1
}
Write-Message -Level Verbose -Message "Received $($files.Count) files based on [$targetFile]"
} else {
Stop-Function -Message "The Path [$pathObject] has an unsupported file type of [$($pathObject.GetType().FullName)]."
}

$newcolumns = $newcolumns | Sort-Object
$columns = ($columns += $newcolumns) | Select-Object -Unique

# Make it selectable, otherwise it's a weird enumeration
foreach ($event in $enum) {
$hash = [ordered]@{ }

foreach ($column in $columns) {
$null = $hash.Add($column, $event.$column)
foreach ($file in $files) {
if (-not (Test-Path -Path $file)) {
Stop-Function -Message "$file cannot be accessed from $($env:COMPUTERNAME)." -Continue
}

foreach ($key in $event.Actions.Keys) {
$hash[$key] = $event.Actions[$key]
}
# use the SqlServer\Read-SqlXEvent cmdlet from Microsoft
# because the underlying Class uses Tasks
# which is hard to handle in PowerShell

foreach ($key in $event.Fields.Keys) {
$hash[$key] = $event.Fields[$key]
if ($Raw) {
try {
Read-XEvent -FileName $file
} catch {
Stop-Function -Message "Failure" -ErrorRecord $_ -Target $file -Continue
}
} else {
try {
$enum = Read-XEvent -FileName $file
} catch {
Stop-Function -Message "Failure" -ErrorRecord $_ -Target $file -Continue
}
$newcolumns = ($enum.Fields.Name | Select-Object -Unique)

$actions = ($enum.Actions.Name | Select-Object -Unique)
foreach ($action in $actions) {
$newcolumns += ($action -Split '\.')[-1]
}

$newcolumns = $newcolumns | Sort-Object
$columns = ($columns += $newcolumns) | Select-Object -Unique

# Make it selectable, otherwise it's a weird enumeration
foreach ($event in $enum) {
$hash = [ordered]@{ }

foreach ($column in $columns) {
$null = $hash.Add($column, $event.$column)
}

foreach ($key in $event.Actions.Keys) {
$hash[$key] = $event.Actions[$key]
}

foreach ($key in $event.Fields.Keys) {
$hash[$key] = $event.Fields[$key]
}

[PSCustomObject]$hash
}
}

[pscustomobject]$hash
}
}
}
Expand Down

0 comments on commit 9a49a6f

Please sign in to comment.