cancel
Showing results for 
Search instead for 
Did you mean: 
Andy_McGrath
Cumulonimbus
Cumulonimbus

Problem this snippet solves:

Needed to record the resource impact of iRules on the F5 system, this script was written to convert the iRule stats output from TMSH into CSV format.


If you clear the stats down and get the stats post testing or after a set interval e.g. 1 hour of production traffic. You should be able to work out the resource hungry iRules and as we did optimise them.

How to use this snippet:

Usage:

  statformating.py -i <iRule Stats input txt file> -o <output CSV file>


This script takes the output of F5 iRule stats from the commend `tmsh show ltm rule` and formats into a CSV file

to allow for easy analysis of iRule resource impact.


Recommend clearing all iRule stats between running. 



The following commands are examples used to clear and capture the iRule stats for a traffic test:


Clear all iRules from Bash:

  tmsh reset-stats ltm rule "/*/*"


Run test traffic


Capture iRule stats and save to file from Bash:

  tmsh show ltm rule "/*/*" > irulestats.txt


Copy off irulesstas.txt file and run against this script using:

  statformating.py -i irulestats.txt -o irulestats.csv

Code :

#!/usr/bin/python
'''
Usage:
    statformating.py -i  -o 

This script takes the output of F5 iRule stats from the commend `tmsh show ltm rule` and formats into a CSV file
to allow for easy analysis of iRule resource impact.

Recommend clearing all iRule stats between running. 


The following commands are examples used to clear and capture the iRule stats for a traffic test:

Clear all iRules from Bash:
    `tmsh reset-stats ltm rule "/*/*"`

Run test traffic

Capture iRule stats and save to file from Bash:
    `tmsh show ltm rule "/*/*" > irulestats.txt`

Copy off irulesstas.txt file and run agains this script using:
    statformating.py -i irulestats.txt -o irulestats.csv

'''

import re
import os
import sys
import argparse

def iruleStatsFormat(inputFile, outputFile):
    '''
    iruleStatsFormat(_io.TextIOWrapper, _io.TextIOWrapper) -> NoneType

    Takes 'inputFile' text file object of F5 iRule raw stats, inputFile example:
        -------------------------------------------------------------------------------------------------------
        Ltm::Rule Event: /partitionname/http_header_rule:HTTP_REQUEST
        -------------------------------------------------------------------------------------------------------
        Priority                      4
        Executions             
        Total                      22
        Failures                    0
        Aborts                      0
        CPU Cycles on Executing
        Average                 42382
        Maximum                115095
        Minimum                 14157

        (raw)                 
        ------------------------------------------------------------------------------------------
        Ltm::Rule Event: /partitionname/http_dc_cookie_decrypt:CLIENT_ACCEPTED
        ------------------------------------------------------------------------------------------
        Priority                     13
        Executions             
        Total                      52
        Failures                    0
        Aborts                      0
        CPU Cycles on Executing
        Average                139933
        Maximum                189777
        Minimum                110646

        (raw)
    
    Formats into a CSV and write to 'outputFile' text file object, outputFile example:
        partitionname,http_header_rule,HTTP_REQUEST,4,22,0,0,42382,115095,14157
        partitionname,http_dc_cookie_decrypt,CLIENT_ACCEPTED,13,52,0,0,139933,189777,110646
    '''
    print('\nReading \'{}\''.format(inputFile.name))
    iruleStats = inputFile.read()

    iruleStats = re.sub(r'[ ]{2,}', ' ', iruleStats)
    iruleStats = re.sub(r'\n\s\(raw\)\s{1,}', '', iruleStats)
    iruleStats = re.sub(r'[-]{2,}\n', '', iruleStats)
    iruleStats = re.sub(r'\n ', r'\n', iruleStats)
    iruleStats = re.sub(r'CPU Cycles on Executing\n', '', iruleStats)
    iruleStats = re.sub(r'Executions \n', '', iruleStats)
    iruleStats = re.sub(r'\nPriority (\d{1,})\nTotal (\d{1,})\nFailures (\d{1,})\nAborts (\d{1,})\nAverage (\d{1,})\nMaximum (\d{1,})\nMinimum (\d{1,})', r'\t\1\t\2\t\3\t\4\t\5\t\6\t\7', iruleStats)
    iruleStats = re.sub(r'Ltm::Rule Event: /(.*?)/(.*?):(.*?\t)', r'\1\t\2\t\3', iruleStats)
    iruleStats = re.sub(r'Ltm::Rule Event: (.*?):(.*?\t)', r'Common\t\1\t\2', iruleStats)
    iruleStats = re.sub(r'\n{2,}', r'\n', iruleStats)
    iruleStats = re.sub(r'\t', r',', iruleStats)

    print('Saving output csv to \'{}\''.format(outputFile.name))
    print(iruleStats, file=outputFile)

def validateFile(fileName):
    '''
    validateFile(str) -> str

    Takes a filename and validates if file already exists. 
    If so prompts the user to confirm or provide another filename.

    returns filename - str
    '''
    if fileName and os.path.isfile(fileName):
        if input('\nFile \'{}\' already exists do you want to overwrite? (y to overwrite) '.format(fileName)) != 'y':
            fileName = validateFile(input('Enter new output filename? '))
    elif not fileName:
        fileName = validateFile(input('Invalid output filename, enter new output filename? '))
    return fileName

if __name__=='__main__':
    # Read cli arguments into argparse, -i input file, -o (optional) as output file
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', dest='input', help='Raw F5 iRule stats input file', nargs='?', type=argparse.FileType('rt'), required=True)
    parser.add_argument('-o', dest='output', help='F5 iRule stats output file (CSV format)', nargs='?', type=argparse.FileType('wt'))
    args = parser.parse_args()

    # Check input file is valid and contains some data
    if args.input:
        # if output file not provided use input filename replacing extention with 'csv'
        if not args.output:
            # Validates output file to ensure not overwriting existing file, opens as writeable
            args.output = open(validateFile(args.input.name[:-3] + 'csv'), 'wt')
        # Calls formatting function
        iruleStatsFormat(args.input, args.output)

    else:
        parser.print_help()

Tested this on version:

12.1
Version history
Last update:
‎12-Jun-2019 00:48
Updated by:
Contributors