Ps Rate Based Statistics

Problem this snippet solves:

One of the key features of iControl is the ability to monitor statistics of the various objects on the system. Whether it's for capacity planning or auditing and billing purposes, the numbers behind how your applications are being utilized on the network are very important. The iControl API allows for querying of statistics for most of the major objects including Virtual Servers, Pools, Pool Members, and Node Addresses. This data is returned as counters but most often the desired presentation of this data is in the form of a rate such as bits or connections per second. This article will show how to query the counter values and calculate rate based statistics for a given virtual server.

Code :

#----------------------------------------------------------------------------
# The contents of this file are subject to the "END USER LICENSE AGREEMENT FOR F5
# Software Development Kit for iControl"; you may not use this file except in
# compliance with the License. The License is included in the iControl
# Software Development Kit.
#
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
#
# The Original Code is iControl Code and related documentation
# distributed by F5.
#
# The Initial Developer of the Original Code is F5 Networks,
# Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2007 F5 Networks,
# Inc. All Rights Reserved.  iControl (TM) is a registered trademark of F5 Networks, Inc.
#
# Alternatively, the contents of this file may be used under the terms
# of the GNU General Public License (the "GPL"), in which case the
# provisions of GPL are applicable instead of those above.  If you wish
# to allow use of your version of this file only under the terms of the
# GPL and not to allow others to use your version of this file under the
# License, indicate your decision by deleting the provisions above and
# replace them with the notice and other provisions required by the GPL.
# If you do not delete the provisions above, a recipient may use your
# version of this file under either the License or the GPL.
#----------------------------------------------------------------------------
param (
  $g_bigip = $null,
  $g_uid = $null,
  $g_pwd = $null,
  $g_virtual = $null
);

$g_gmt_offset = "";

Set-PSDebug -strict;

#-------------------------------------------------------------------------
# function Write-Usage
#-------------------------------------------------------------------------
function Write-Usage()
{
  Write-Host "Usage: VirtualRates.ps1 host uid pwd [virtual_server]";
  exit;
}

#-------------------------------------------------------------------------
# function Get-TimeFromTimeStamp
#-------------------------------------------------------------------------
function Get-TimeFromTimeStamp()
{
  param ($TimeStamp);
  $dt = new-object -typename System.DateTime
  $dt = $dt.AddYears($TimeStamp.year-1)
    .AddMonths($TimeStamp.month-1)
    .AddDays($TimeStamp.day-1)
    .AddHours($TimeStamp.hour)
    .AddMinutes($TimeStamp.minute)
    .AddSeconds($TimeStamp.second);
  return $dt;
}

################################################################################ 
## Invoke-Inline.ps1 (originally from Lee Holmes)
## Library support for inline C# 
## 
## Modified by Joel Bennett to accept include statements, and return collections
##
## Usage 
##  1) Define just the body of a C# method, and store it in a string.  "Here 
##     strings" work great for this.  The code can be simple: 
## 
##     $codeToRun = "Console.WriteLine(Math.Sqrt(337));" 
## 
##     or more complex, using result.Add(): 
## 
##     $codeToRun = @" 
##         string firstArg = (string) ((System.Collections.ArrayList) arg)[0]; 
##         int secondArg = (int) ((System.Collections.ArrayList) arg)[1]; 
## 
##         Console.WriteLine("Hello {0} {1}", firstArg, secondArg ); 
##      
##         result.Add(secondArg * 3); 
##     "@ 
## 
##  2) If you must pass arguments, you should make them strongly-typed, 
##   so that PowerShell doesn't wrap it as a PsObject. 
## 
##  3) Invoke the inline code, optionally retrieving the return value.  You can 
##     set the return values in your inline code by assigning it to the 
##     "return" collection as shown above. 
## 
##     $result = Invoke-Inline $usingStatements, $codeToRun $arguments 
##     $result = Invoke-Inline  $codeToRun $arguments 
## 
## 
##     If your code is simple enough, you can even do this entirely inline: 
## 
##     Invoke-Inline "Console.WriteLine(Math.Pow(337,2));" 
##   
################################################################################ 
function Invoke-Inline()
{
  param(
    [string[]] $code, 
    [object[]] $arguments,
    [string[]] $reference = @()
  )

  ## Stores a cache of generated inline objects.  If this library is dot-sourced 
  ## from a script, these objects go away when the script exits. 
  if(-not (Test-Path Variable:\inlineCode.Cache))
  {
    ${GLOBAL:inlineCode.Cache} = @{}
  }

  $using = $null;
  $source = $null;
  if($code.length -eq 1) {
    $source = $code[0]
  } elseif($code.Length -eq 2){
    $using = $code[0]
    $source = $code[1]
  } else {
    Write-Error "You have to pass some code, or this won't do anything ..."
  }

  ## un-nesting magic (why do I need this?)
  $params = @()
  foreach($arg in $arguments) { $params += $arg }
  $arguments = $params

  ## The main function to execute inline C#.   
  ## Pass the argument to the function as a strongly-typed variable.  They will  
  ## be available from C# code as the Object variable, "arg". 
  ## Any values assigned to the "returnValue" object by the C# code will be  
  ## returned to MSH as a return value. 

  ## See if the code has already been compiled and cached 
  $cachedObject = ${inlineCode.Cache}[$source] 
  #Write-Verbose "Type: $($arguments[0].GetType())"

  ## The code has not been compiled or cached 
  if($cachedObject -eq $null)
  {
    $codeToCompile = 
@"
    using System;
    using System.Collections.Generic;
    $using

    public class InlineRunner 
    { 
      public List Invoke(Object[] args) 
      { 
        List result = new List(); 

        $source 

        if( result.Count > 0 ) {
            return result;
        } else {
            return null;
        }
      } 
    } 
"@
    Write-Verbose $codeToCompile

    ## Obtains an ICodeCompiler from a CodeDomProvider class. 
    $provider = New-Object Microsoft.CSharp.CSharpCodeProvider 

    ## Get the location for System.Management.Automation DLL 
    $dllName = [PsObject].Assembly.Location

    ## Configure the compiler parameters 
    $compilerParameters = New-Object System.CodeDom.Compiler.CompilerParameters 

    $assemblies = @("System.dll", $dllName) 
    $compilerParameters.ReferencedAssemblies.AddRange($assemblies) 
    $compilerParameters.ReferencedAssemblies.AddRange($reference)
    $compilerParameters.IncludeDebugInformation = $true 
    $compilerParameters.GenerateInMemory = $true 

    ## Invokes compilation.  
    $compilerResults =
      $provider.CompileAssemblyFromSource($compilerParameters, $codeToCompile) 

    ## Write any errors if generated.         
    if($compilerResults.Errors.Count -gt 0) 
    { 
      $errorLines = "" 
      foreach($error in $compilerResults.Errors) 
      { 
        $errorLines += "`n`t" + $error.Line + ":`t" + $error.ErrorText 
      } 
      Write-Error $errorLines 
    } 
    ## There were no errors.  Store the resulting object in the object 
    ## cache. 
    else 
    { 
      ${inlineCode.Cache}[$source] = 
        $compilerResults.CompiledAssembly.CreateInstance("InlineRunner") 
    } 

    $cachedObject = ${inlineCode.Cache}[$source] 
   } 

   Write-Verbose "Argument $arguments`n`n$cachedObject"
   ## Finally invoke the C# code 
   if($cachedObject -ne $null)
   {
     return $cachedObject.Invoke($arguments)
   }
}

#-------------------------------------------------------------------------
# function Convert-To64Bit
#-------------------------------------------------------------------------
function Convert-To64Bit()
{
  param($high, $low);
  return Invoke-Inline "result.Add((Convert.ToUInt64($high)<<32) | (Convert.ToUInt64($low)));"
}

#-------------------------------------------------------------------------
# Get-Virtuals
#-------------------------------------------------------------------------
function Get-Virtuals()
{
  $vs_list = (Get-F5.iControl).LocalLBVirtualServer.get_list();
  Write-Host "Available Virtual Servers:";
  foreach ($vs in $vs_list)
  {
    Write-Host "  $vs";
  }
}

#-------------------------------------------------------------------------
# Get-VirtualRates
#-------------------------------------------------------------------------
Function Get-VirtualRates()
{
  param($virtual_server);
  
  $bFirst = 1;
  
  $b0 = 0;
  $p0 = 0;
  $c0 = 0;
  $t0 = [DateTime]::Now;
  
  Write-Host "Rates for Virtual Server: $virtual_server"
  
  while (1)
  {
    $VirtualServerStatistics = (Get-F5.iControl).LocalLBVirtualServer.get_statistics( (, $virtual_server) );
    $t1 = Get-TimeFromTimeStamp $VirtualServerStatistics.time_stamp;
    $VirtualServerStatisticEntry = $VirtualServerStatistics.statistics[0];
    $Statistics = $VirtualServerStatisticEntry.statistics;

    foreach ($Statistic in $Statistics)
    {
      switch ($Statistic.type) {
        "STATISTIC_CLIENT_SIDE_BYTES_IN" {
          $b1 = Convert-To64Bit $Statistic.value.high $Statistic.value.low;
        }
        "STATISTIC_CLIENT_SIDE_PACKETS_IN" {
          $p1 = Convert-To64Bit $Statistic.value.high $Statistic.value.low;
        }
        "STATISTIC_CLIENT_SIDE_TOTAL_CONNECTIONS" {
          $c1 = Convert-To64Bit $Statistic.value.high $Statistic.value.low;
        }
      }
    }
    
    if ($bFirst -eq 1 )
    {
      $bFirst = 0;
      $b0 = $b1;
      $p0 = $p1;
      $c0 = $c1;
      $t0 = $t1;
    }
    else
    {
      $b2 = $b1 - $b0;
      $p2 = $p1 - $p0;
      $c2 = $c1 - $c0;
      $t2 = $t1 - $t0;
      $sec = $t2.Seconds;
      if  ( $sec -eq 0 ) { $sec = 1 }
      
      if ( ($b2 -lt 0) -or ($p2 -lt 0) -or ($c2 -lt 0) )
      {
        # either the counters increased past 2^64 or they were reset so start over.
        $bFirst = 1;
      }
      else
      {
        # Calculate rates
        $br = $b2/$sec;
        $pr = $p2/$sec;
        $cr = $c2/$sec;
        
        Write-Host "$br bps; $pr pps; $cr cps"
      }
    }
    
    Start-Sleep -s 1
  }
}

#-------------------------------------------------------------------------
# Do-Initialize
#-------------------------------------------------------------------------
function Do-Initialize()
{
  if ( (Get-PSSnapin | Where-Object { $_.Name -eq "iControlSnapIn"}) -eq $null )
  {
    Add-PSSnapIn iControlSnapIn
  }
  $success = Initialize-F5.iControl -HostName $g_bigip -Username $g_uid -Password $g_pwd;
  
  return $success;
}

#-------------------------------------------------------------------------
# Main Application Logic
#-------------------------------------------------------------------------
if ( ($g_bigip -eq $null) -or ($g_uid -eq $null) -or ($g_pwd -eq $null) )
{
  Write-Usage;
}

if ( Do-Initialize )
{
  if ( $g_virtual -eq $null )
  {
    Get-Virtuals;
  }
  else
  {
    Get-VirtualRates $g_virtual;
  }
}
else
{
  Write-Error "ERROR: iControl subsystem not initialized"
}
Published Mar 09, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment