From WIRM to Splunk – Translating the Past to the Present

I get to do a lot of cool things at Splunk.  One of the things I have been wanting to do is incorporate the visualizations I built a long time ago for Web Interface for Resource Manger in Splunk applications.  All of those past visualizations were built using Microsoft ASP.NET and Flash.  So, I have had to use alternate methods to accomplish what I want.

 

Calendar Visualization

One of the first things I tackled was the calendar visualization that shows how many users log in each day in a month.  Here is the old calendar from WIRM:

WIRM Calendar

Here is what the calendar looks like in Splunk:

Splunk Calendar

If you want to see how to use this calendar visualization in your own Splunk environment, check out my Splunk blog post.

The cool thing about having this available in Splunk is that it is reusable for various types of data including security, XenDesktop/XenApp, Microsoft Windows, Unix, etc.

Using PowerShell to Retrieve Citrix Monitor Data via OData

Starting with XenDesktop 7, Citrix stores the data the Desktop Director displays in a SQL database. Citrix opened up this data via a Monitor Service API that uses OData.  I’m not going to go deep into the details of the API as it is fairly well documented at the eDocs site.  The examples in the documentation show you how to access this data via web browser, Microsoft Excel, and LinqPad.  What I want to do in this article is show you how to use PowerShell with this API.

To start out, let’s take a look at the Citrix Monitor Service schema (click to enlarge):

 

MonitorDataSchema

Suppose we want to get all sessions as well as the all the connection/disconnections to the session.  The following URL will return the data we want in XML format.

http://localhost/Citrix/Monitor/Odata/v1/Data/Sessions

The trick to get this working with PowerShell is to transform all this information into a nice hierarchical structure.  In the example code below, we use the Invoke-ODataTransform function to do this.

function Global:Invoke-ODataTransform ($records) {

    $propertyNames = ($records | Select -First 1).content.properties |
        Get-Member -MemberType Properties |
        Select -ExpandProperty name

    foreach($record in $records) {

        $h = @{}
        $h.ID = $record.ID
        $properties = $record.content.properties

        foreach($propertyName in $propertyNames) {
            $targetProperty = $properties.$propertyName
            if($targetProperty -is [System.Xml.XmlElement]) {
                $h.$propertyName = $targetProperty.'#text'
            } else {
                $h.$propertyName = $targetProperty
            }
        }

        [PSCustomObject]$h
    }
}

$connections = ""
$uri = "http://localhost/Citrix/Monitor/OData/v1/Data/Sessions?`$expand=Connections"
$connections = Invoke-ODataTransform(Invoke-RestMethod -Uri $uri -UseDefaultCredentials)

foreach($connection in $connections)
{
    $output = $connection | Get-Member -MemberType Properties | ForEach-Object {
        $key = $_.Name
        $value = $connection.$key
        '{0}="{1}"' -f $key,$value
    }

    Write-Host $output
}