Get-VIEventsFaster PowerCLI function...

[Update: Come to find out LucD wrote a Get-VIEventPlus function that I did not find before making mine.  He adds some other switches that might be useful, same idea though.  Just tells me I really should keep up on his blog more often.]

I wrote this function so I could replace the Get-VIEvent cmdlet in my scripts.  The great part is that the output ends up being roughly the same as the cmdlet so just changing my calls to this custom function speeds everything up like 100-fold.  That might be an exaggeration, but yeah, it's WAY faster.

It's written so that most get-vievent common switches are included.  Syntax is 'slightly' different, but usable so you don't have to modify any get-vievent calls too heavily.  I added a 'type' switch which will help shave off even MORE time.  Anyway, feel free to give it a try or let me know if you have any feedback.

Finally, It's written like a cmdlet so you can import it as a module or dot source it.  I've included some examples as well.

The 'entity' switch works 'ok' if you give it a variable captured object like:
$myVM = Get-VM myVMName
Get-VIEventsFaster -Entity $myVM

I want it to work like this:
$myVM | Get-VIEventsFaster -Entity $_
but I can't get it work like this, but $_ or inference doesn't work like how I think it should.  Just my lack of knowledge here really.
Script:


#Get-VIEventsFaster
#
Function Get-VIEventsFaster
{
<#
  .SYNOPSIS
  Uses the PowerCLI Get-View cmdlet to query for events.
  .DESCRIPTION
  This is meant to replace the Get-VIEvent cmdlet in scripts for faster results w/o dramatic changes to code.
  .PARAMETER server
  Connects to vCenter or ESXi server specified.
  .PARAMETER start
  The beginning of the time range. If this property is not set, then events are collected from the earliest time in the database. 
  .PARAMETER finish
  The end of the time range. If this property is not specified, then events are collected up to the latest time in the database. 
  .PARAMETER type
  An array of event types can be specified as a filter.  See examples to see how to get a valid list of event types.
  .PARAMETER entity
  Looking for a vSphere object, VM, host, or otherwise. 
  .EXAMPLE
  $Date = Get-Date ; $Events = Get-VIEventsFaster -Start ($Date.AddMonths(-1)) -Finish $Date
  Gets all events from 'exactly' 1 month ago to today and captures them in the $Events variable.  
  If Get-Date returned Friday, June 13, 2014 11:00:46 AM, one month ago would be Tuesday, May 13, 2014 11:00:46 AM.
  .EXAMPLE
  $Date = Get-Date ; $Events = Get-VIEventsFaster -Start ($Date.AddMonths(-1)) -Finish $Date -Type "VmCreatedEvent","VmClonedEvent","VmDeployedEvent"
  Gets specified event types from 'exactly' 1 month ago to today and captures them in the $Events variable.  
  If Get-Date returned Friday, June 13, 2014 11:00:46 AM, one month ago would be Tuesday, May 13, 2014 11:00:46 AM.
  .EXAMPLE
  $Events | % {($_.gettype()).name} | select -Unique
  You can use this one liner to determine valid event 'types'
  .LINK
  http://tech.zsoldier.com/2014/06/get-vieventsfaster-powercli-function.html
  #>
param (
    [Parameter(Mandatory=$False,HelpMessage="ESXi or vCenter to query events from.")]
    [VMware.VimAutomation.ViCore.Impl.V1.VIServerImpl]
    $Server,

    [Parameter(Mandatory=$False,HelpMessage="Start Date to begin gathering events")]
    [DateTime]
    $Start,

    [Parameter(Mandatory=$False,HelpMessage="End Date to finish gathering events")]
    [DateTime]
    $Finish,

    [Parameter(Mandatory=$False,HelpMessage="Filter down to types of events")]
    [string[]]
    $EventType,
    
    [Parameter(Mandatory=$False,ValueFromPipeline=$True,HelpMessage="Looks for events associated w/ specified entity or entities")]
    [VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl[]]
    $Entity
    )
Begin 
    {
    $AllEvents = @()
    $em = get-view -Server $Server EventManager
    $EventFilterSpec= New-Object VMware.Vim.EventFilterSpec
    #VIServer
    If (!$Server)
    {
    If (!$global:DefaultVIServers){Write-Host "You don't appear to be connected to a vCenter or ESXi server." -ForegroundColor:Red; Break}
    $Server = $global:DefaultVIServers[0]
    }
    #Type
    If ($EventType)
        {
        $EventFilterSpec.EventTypeID = $EventType
        }
    #Time
    If ($Start -or $Finish)
        {
        $EventFilterSpec.Time = New-Object Vmware.Vim.EventFilterSpecByTime
        }
    If ($Start)
        {
        $EventFilterSpec.Time.BeginTime = $Start
        }
    If ($Finish)
        {
        $EventFilterSpec.Time.EndTime = $Finish
        }
    #Entity
    If ($Entity)
        {
        $EventFilterSpec.Entity = New-Object VMware.Vim.EventFilterSpecByEntity
        $EventFilterSpec.Entity.Recursion = "self"
        $EventFilterSpec.Entity.Entity = $Entity.ExtensionData.MoRef
        }
    }
Process
    {
    #Query
    $evCollector = Get-View -Server $Server $em.CreateCollectorForEvents($EventFilterSpec))
    $PageEvents = $evCollector.ReadNextEvents(100)
    While ($PageEvents)
        {
        $AllEvents += $PageEvents
        $PageEvents = $evCollector.ReadNextEvents(100)
        }
    $AllEvents
    }
End {$evCollector.DestroyCollector()}
}
Additional Info:
Time Difference (my function is 900% faster):
Measure-command {Get-VIEventsFaster -Start ($date.AddMonths(-1)) -Finish ($date)}
Hours             : 0
Minutes           : 12
Seconds           : 57
Milliseconds      : 622
Ticks             : 7776226103
TotalDays         : 0.00900026169328704
TotalHours        : 0.216006280638889
TotalMinutes      : 12.9603768383333

Measure-command {Get-VIEvent -Start ($date.AddMonths(-1)) -Finish ($date)}
Hours             : 1
Minutes           : 48
Seconds           : 59
Milliseconds      : 880
Ticks             : 65398800684
TotalDays         : 0.0756930563472222
TotalHours        : 1.81663335233333
TotalMinutes      : 108.99800114

You can use this one liner to determine what 'names' constitute a valid event 'type':
$Events | % {($_.gettype()).name} | select -Unique

No comments: