Functions/Public/Events.ps1

# Event functions

Function Get-NectarEvent {
    <#
        .SYNOPSIS
        Return a list of current or historic Nectar monitored device events
         
        .DESCRIPTION
        Return a list of current or historic Nectar monitored device events
         
        .PARAMETER TimePeriod
        The time period to show event data from. Select from 'LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','CUSTOM'.
        CUSTOM requires using TimePeriodFrom and TimePeriodTo parameters.
 
        .PARAMETER TimePeriodFrom
        The earliest date/time to show event data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodTo parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TimePeriodTo
        The latest date/time to show event data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodFrom parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER LastTimeAfter
        Only return results that occurred more recently than the entered value. Use date-time format as in 2020-04-20T17:46:37.554
         
        .PARAMETER EventAlertLevels
        Return only events that meet the specified alert level. Choose one or more from CRITICAL, MAJOR, MINOR, WARNING, GOOD, NO_ACTIVITY
 
        .PARAMETER Locations
        Show alerts for one or more specified locations
 
        .PARAMETER SearchQuery
        Search for events that contain the specified string
         
        .PARAMETER OrderByField
        Order the resultset by the specified field. Choose from id, type, lastTime, displayName, deviceName, description, eventId, time, delay, source, location, sourceId
         
        .PARAMETER EventState
        Return either current events or previously acknowledged events
 
        .PARAMETER CountOnly
        Only return a total count of events
         
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
 
        .PARAMETER PageSize
        The size of the page used to return data. Defaults to 1000
         
        .PARAMETER ResultSize
        The total number of results to return. Defaults to 1000. Maximum result size is 9,999,999 results
 
        .EXAMPLE
        Get-NectarEvent -EventAlertLevels CRITICAL,MAJOR
        Returns a list of current events in the last hour that are either critical or major
         
        .EXAMPLE
        Get-NectarEvent -SearchQuery BadServer -EventState Historic -TimePeriod LAST_WEEK
        Returns a list of historical events from the last week that include the word 'badserver'
 
        .NOTES
        Version 1.0
    #>

    
    Param (
        [Parameter(Mandatory=$False)]
        [ValidateSet('LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','TODAY','YESTERDAY','WEEK_TO_NOW','MONTH_TO_NOW','CUSTOM', IgnoreCase=$True)]
        [string]$TimePeriod = 'LAST_HOUR',
        [Parameter(Mandatory=$False)]
        [Alias("StartDateFrom")]
        [string]$TimePeriodFrom,
        [Parameter(Mandatory=$False)]
        [Alias("StartDateTo")]
        [string]$TimePeriodTo,
        [Parameter(Mandatory=$False)]
        [string]$LastTimeAfter,        
        [Parameter(Mandatory=$False)]
        [ValidateSet('CRITICAL', 'MAJOR', 'MINOR', 'WARNING', 'GOOD', 'NO_ACTIVITY', IgnoreCase=$True)]
        [string[]]$EventAlertLevels,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [Alias("SiteName")]
        [string[]]$Locations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$SearchQuery,
        [Parameter(Mandatory=$False)]
        [ValidateSet('id', 'type', 'lastTime', 'displayName', 'deviceName', 'description', 'eventId', 'time', 'delay', 'source', 'location', 'sourceId', IgnoreCase=$True)]
        [string]$OrderByField,
        [Parameter(Mandatory=$False)]
        [ValidateSet('asc', 'desc', IgnoreCase=$True)]
        [string]$OrderDirection,
        [Parameter(Mandatory=$False)]
        [ValidateSet('Current', 'Historic', IgnoreCase=$True)]
        [string]$EventState = 'Current',
        [Parameter(Mandatory=$False)]
        [switch]$CountOnly,    
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,100000)]
        [int]$PageSize = 1000,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,9999999)]
        [int]$ResultSize
    )
    
    Begin {
        Connect-NectarCloud
    }
    Process {
        # Use globally set tenant name, if one was set and not explicitly included in the command
        If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
            $TenantName = $Global:NectarTenantName 
        }

        $Params = @{
            'TimePeriod' = $TimePeriod
        }
    
        # Convert any PowerShell array objects to comma-separated strings to add to the GET querystring
        If ($LastTimeAfter) { $Params.Add('LastTimeAfter',$LastTimeAfter) } 
        If ($EventAlertLevels) { $EventAlertLevels | ForEach-Object { $EventAlertLevelsStr += ($(If($EventAlertLevelsStr){","}) + $_) }; $Params.Add('EventAlertLevels',$EventAlertLevelsStr) }
        If ($Locations) { $Locations | ForEach-Object { $LocationsStr += ($(If($LocationsStr){","}) + $_) }; $Params.Add('Locations',$LocationsStr) }
        If ($SearchQuery) { $Params.Add('q',$SearchQuery) }
        If ($OrderByField) { $Params.Add('OrderByField',$OrderByField) }
        If ($OrderDirection) { $Params.Add('OrderDirection',$OrderDirection) }
        If ($TenantName) { $Params.Add('Tenant',$TenantName) }

        # Convert date to UNIX timestamp
        If($TimePeriodFrom) {
            $TimePeriodFrom = (Get-Date -Date $TimePeriodFrom -UFormat %s) + '000'
            $Params.Add('StartDateFrom',$TimePeriodFrom)
        }
        
        If($TimePeriodTo) {
            $TimePeriodTo = (Get-Date -Date $TimePeriodTo -UFormat %s) + '000'
            $Params.Add('StartDateTo',$TimePeriodTo)
        }

        # Only return 1 item if -CountOnly is selected
        If ($CountOnly) {
            $ResultSize    = 1
            $PageSize     = 1
        }
        
        # Set the page size to the result size if -ResultSize switch is used to limit the number of returned items
        # Otherwise, set page size (defaults to 1000)
        If ($ResultSize) {
            $Params.Add('pageSize',$ResultSize)
        } Else {
            $Params.Add('pageSize',$PageSize)
        }

        If ($EventState -eq 'Current') {
            $URI = "https://$Global:NectarCloud/dapi/event/current/all"
        } Else {
            $URI = "https://$Global:NectarCloud/dapi/event/historic/all"
        }
        
        Write-Verbose $URI

        Try {
            $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params
            
            If ($CountOnly) {
                Return $JSON.totalElements
            } Else {
                $TotalPages = $JSON.totalPages
                
                If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
                $JSON.elements
                
                If ($TotalPages -gt 1 -and !($ResultSize)) {
                    $PageNum = 2
                    Write-Verbose "Page size: $PageSize"
                    While ($PageNum -le $TotalPages) {
                        Write-Verbose "Working on page $PageNum of $TotalPages"
                        $PagedURI = $URI + "?pageNumber=$PageNum"
                        $JSON = Invoke-RestMethod -Method GET -URI $PagedURI -Headers $Global:NectarAuthHeader -Body $Params
                        If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
                        $JSON.elements
                        $PageNum++
                    }
                }
            }
        }
        Catch {
            Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }
        }
    }
}


Function Get-NectarEventCount {
    <#
        .SYNOPSIS
        Return a sampling of event counts for a given time period grouped by event severity.
         
        .DESCRIPTION
        Return a sampling of event counts for a given time period grouped by event severity. This is only a sample and is not intended to provide a true count of the number of events in a given period.
        Its useful for situations where you want to get a sense of event distribution without having to pull the entire list of events, which can take a lot of time.
         
        .PARAMETER TimePeriod
        The time period to show event data from. Select from 'LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','CUSTOM'.
        CUSTOM requires using TimePeriodFrom and TimePeriodTo parameters.
 
        .PARAMETER TimePeriodFrom
        The earliest date/time to show event data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodTo parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TimePeriodTo
        The latest date/time to show event data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodFrom parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
 
        .EXAMPLE
        Get-NectarEventCount -TimePeriod LAST_WEEK
        Returns a count of events grouped by severity for the last week
 
        .NOTES
        Version 1.0
    #>

    
    Param (
        [Parameter(Mandatory=$False)]
        [ValidateSet('LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','TODAY','YESTERDAY','WEEK_TO_NOW','MONTH_TO_NOW','CUSTOM', IgnoreCase=$True)]
        [string]$TimePeriod = 'LAST_DAY',
        [Parameter(Mandatory=$False)]
        [Alias("StartDateFrom")]
        [DateTime]$TimePeriodFrom,
        [Parameter(Mandatory=$False)]
        [Alias("StartDateTo")]
        [DateTime]$TimePeriodTo,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName
    )
    
    Begin {
        Connect-NectarCloud
    }
    Process {
        Try {
            # Use globally set tenant name, if one was set and not explicitly included in the command
            If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }

            $URI = "https://$Global:NectarCloud/dapi/event/alerts/summary?timePeriod=$TimePeriod&tenant=$TenantName"            
            Write-Verbose $URI        
            
            Try {
                $RawCount = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader
            }
            Catch {  # DXP versions less than 1.15.0 use a trend, which is removed in 1.15.0. This allows this function to still work during the transition.
                $URI = "https://$Global:NectarCloud/dapi/event/alerts/trend?timePeriod=$TimePeriod&tenant=$TenantName"
                Write-Verbose $URI
                $RawCount = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader
            }

            $ResultSummary = [System.Collections.ArrayList]@()

            ForEach ($Event in $RawCount) {
                $EventSummary = [pscustomobject][ordered]@{
                    'EventType' = $Event.Type
                    'Count'        = $Event.data.count
                }
                $ResultSummary += $EventSummary
            }
            
            Return $ResultSummary        
        }
        Catch {
            Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }
        }
    }
}


Function Get-NectarEventDetail {
    <#
        .SYNOPSIS
        Return information about a specific event
         
        .DESCRIPTION
        Return information about a specific event
 
        .PARAMETER EventID
        The ID of the event to return details about
         
        .PARAMETER EventState
        Return either current events or previously acknowledged events
         
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
 
        .EXAMPLE
        Get-MSTeamsCallRecord -CallRecordID ed672235-5417-40ce-8425-12b8b702a505
 
        .NOTES
        Version 1.0
    #>

    
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)]
        [string]$ID,
        [Parameter(Mandatory=$False)]
        [ValidateSet('Current', 'Historic', IgnoreCase=$True)]
        [string]$EventState = 'Current',        
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName
    )
    
    Begin {
        Connect-NectarCloud
    }
    Process {
        Try {
            # Use globally set tenant name, if one was set and not explicitly included in the command
            If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }

            $Params = @{
                'eventId' = $ID
            }
        
            If ($TenantName) { $Params.Add('Tenant',$TenantName) }

            If ($EventState -eq 'Current') {
                $URI = "https://$Global:NectarCloud/dapi/event/current/view"
            }
            Else {
                $URI = "https://$Global:NectarCloud/dapi/event/historic/view"
            }
            
            Write-Verbose $URI        
            
            $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params    
            
            If ($TenantName) {$JSON | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
            
            $JSON | Add-Member -TypeName 'Nectar.EventDetail'
            $JSON
        }
        Catch {
            Write-Error "Could not find event with ID $EventID. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }
        }
    }
}