Update: Get stream statistics from Wowza Media Server

Yesterday I discovered that the function in the article ‘Get stream statistics from Wowza Media Server’ was not working properly. It goes wrong when more Applications are loaded in Wowza. So I have changed the function and used ForEach loops instead of For loops. The For loop would also go wrong when there is only one stream in an Application. Because there is no count property in the XML object then.

Function Get-WowzaStreamStats{
    $webclient = new-Object System.Net.WebClient
    $webclient.credentials = new-Object system.Net.NetworkCredential("user", "password", "")
    [xml]$xml = $webclient.DownloadString("http://wowza-ip:8086/connectioncounts")

    foreach ($vhost in $xml.WowzaMediaServer.VHost) {
    
        foreach ($Application in $xml.WowzaMediaServer.VHost.Application) {

            foreach ($Stream in $Application.ApplicationInstance.Stream) {
                $Node = @{}
                
                $Node.TotalConnections = $Stream.SessionsTotal
                $Node.StreamName = $Stream.Name
                $Node.FlashConnections = $Stream.SessionsFlash
                $Node.SilverlightConnections = $Stream.SessionsSmooth
                $Node.RTSPConnections = $Stream.SessionsRTSP
                $Node.iOSConnections = $Stream.SessionsCupertino
                $Node.Application = $Application.name
                $Node.Vhost = $vhost.name
                
                $StreamStats = new-Object PSObject -Property $Node
                Write-Output $StreamStats
            }
        }
    }
}
Advertisements

Get stream statistics from Wowza Media Server

Recently I needed to know how many connections were made to a stream on our Wowza server, as real time as possible. For Windows Media Services you can use performance counters for that. And you can read these counters with PowerShell. I made a script for that in the past.

For Wowza I wanted something similar for that. The good thing is that Wowza has an xml interface that outputs the current connections. In default configuration you find the interface at http://wowza-ip:8086/connectioncounts. For humans the output is not very readable. So I made a function to parse the output.

Function Get-WowzaStreamStats{
    $webclient = new-Object System.Net.WebClient
    $webclient.credentials = new-Object system.Net.NetworkCredential("user", "password", "")
    [xml]$xml = $webclient.DownloadString("http://wowza-ip:8086/connectioncounts")

    for ($i=0; $i -lt $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream.Count; $i++) {
    $Node = @{}
    
    $Node.TotalConnections = $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream[$i].SessionsTotal
    $Node.StreamName = $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream[$i].Name
    $Node.FlashConnections = $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream[$i].SessionsFlash
    $Node.SilverlightConnections = $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream[$i].SessionsSmooth
    $Node.RTSPConnections = $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream[$i].SessionsRTSP
    $Node.iPadConnections = $xml.WowzaMediaServer.VHost.Application.ApplicationInstance.Stream[$i].SessionsCupertino
    
    $StreamStats = new-Object PSObject -Property $Node
    Write-Output $StreamStats
    }
}

The output of the function is an object. So you can use it in the pipeline. For example you can type:
Get-WowzaStreamStats | Where-Object {$_.StreamName –eq ‘name.stream’}

Upload a file with ftp using PowerShell

Recently I needed a script to upload log files from one server to another server. The servers were in separate networks so I could not use a simple copy command like xcopy or robocopy. For this I had to use FTP. I had already a simple old batch file that uses the built-in ftp command. But I wanted to use PowerShell so that I could make it more advanced. After some searching on PowerShell websites I found some examples. I used these as a start for my function.

function Send-FileToFtp {
    [CmdletBinding()]
    [OutputType([System.Int32])]
    param(
        [Parameter(Position=0, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [System.Object]$SourceFile,

        [Parameter(Position=1, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [System.String]$Destination,
        
        [Parameter(Position=2, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [System.String]$UserName,
        
        [Parameter(Position=3, Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [System.String]$Password
    )

    Process {
        try {
            # Get the object used to communicate with the server. 
            $Request = [System.Net.FtpWebRequest]::Create("ftp://$Destination/$($SourceFile.Name)") 
            $Request.Method = $Request.Method = [System.Net.WebRequestMethods+ftp]::UploadFile 
             
            # This example assumes the FTP site uses anonymous logon. 
            $Request.Credentials = New-Object System.Net.NetworkCredential $UserName,$Password 
             
            # Copy the contents of the file to the request stream. 
            $FileContents = [System.IO.File]::ReadAllBytes($SourceFile.FullName) 
            $Request.ContentLength = $fileContents.Length
            $RequestStream = $request.GetRequestStream() 
            $RequestStream.Write($FileContents, 0, $FileContents.Length) 
            $RequestStream.Close()
            $Response = $Request.GetResponse() 
            $Response.StatusDescription
        }
        catch {
            throw "ERROR: Unable to upload file $($SourceFile.name), status {0}"
        }
        $Response.StatusDescription
        }
    }

The function takes 4 parameters as you can see in the script. Most of them will be self explaining. But the parameter $SourceFile will need some explanation. Instead of using a string I decided to use an object. I did this so I can use the object to construct the filename of the source and also use it to construct the ftp request. To use the function you can write something like this.

$files = Get-ChildItem -Path "c:\windows\system32\logfiles\" -Filter "*.log"
if ($files -ne $null) {
    Foreach ($file in $files) {
        $result = Send-FileToFtp -SourceFile $file -Destination "ftp.domain.com/folder" -UserName "user" -Password "password"
        if ($Result -match "226*"){
            "Upload completed, now deleting source file: $($File.Name)"
        } else {
            "Upload failed!"
        }
    }
}

It gets all the log files from the c:\windows\system32logfiles directory and places them in the variable $files. For every file object in the variable $files it runs the function Send-FileToFtp. If the upload succeeds, the function returns a StatusDescription with the code 226, you can delete the original file or do something else. When the upload fails you can output a message or do somethings else.

For what I wanted to do this works perfect. But for other things it possibly needs to get changed a bit.