The TAO of Tables - Part Two
This is a series of articles to introduce you to the many uses of tables.
Previously we talked about how tables can be used for counting. The next discussion in this series deals with structure and profiling of iRules.
I encourage iRule authors to keep the logic flat. Its all well and good having beautiful indented arches of if, elseif and else statements. The hard reality of iRules is we want to get in and get out fast. I encourage users to make use of the return command to provide early exits from their code.
If we had the following:
if {[HTTP::basename] ends_with “.html”} {
if {[HTTP::header exists x-myheader]} {
if {[HTTP::header x-myheader] eq 1} {
# run my iRule code
} else {
# run my alternate code
}
}
}
It would become…
# no html
if { not ([HTTP::basename] ends_with “.html” ) } { return }
# no header
if { not ( [HTTP::header exists x-myheader] ) } { return }
if { [HTTP::header x-myheader] == 1 } {
# run main iRule code
return
}
# run alternate code
So in this case we have put the no-run conditionals at the front of the iRule and the rest of the code is not executed unless it needs to be. While this is a simple case of making the code flat without any optimization, when you get to larger iRules you will have multiple no-run conditions which you can put up front to prevent the main code from ever executing. Testing would show you which are the most common and they would be tested first.
There are added benefits as well. It is easier to read this code, the decision logic is very simple, if you don’t meet the conditions then your out! But there is more to this and here is where it gets really interesting. Now you have discrete exit points using return you can use this to begin profiling its behavior.
Say for every exit point, you set a variable which represents why an exit occurred.
when HTTP_REQUEST {
if { not ( [HTTP::basename] ends_with “.html” ) } {
set status “failed:Not html”
return
}
if { not ( [HTTP::header exists x-myheader] ) } {
set status “failed:No header”
return
}
if { [HTTP::header x-myheader] == 1 } {
# run my iRule code
set status “success:Main”
return
}
# run my alternate code
set status “success:Alternate”
}
Why do all this? We can add another iRule which begins execution profiling. After the iRule above add the following…
when HTTP_REQUEST {
set lifetime 60
set uid [expr {rand() * 10000}]
table add –subtable [getfield $status “:” 1] $uid 1 indef $lifetime
table add –subtable “$status” $uid 1 indef $lifetime
table add –subtable tracking $status 1 indef 3600
}
First we create a unique identifier for this execution of the iRule called “uid”.
The first table command is creating a subtable using the first part of the status string as the name. Since that is “success” or “failure” there will be two subtables. We will add a unique entry using the “uid” as the key to one of those tables. This table entry effectively represents a single execution of your iRule. These entries have a lifetime of 60 seconds.
The second and third table commands are related. The second creates unique entries in a subtable named from the entire status string with a lifetime of 60 seconds. Since we do not know what the status strings may be in advance the third table command records these in a tracking table.
Now finally, add the following code to any Virtual on the same F5.
when HTTP_REQUEST {
if {[HTTP::uri] ne “/status”} { return }
set content “iRule Status<p>”
append content “iRule Success: [table keys –count –subtable “success”]<br>”
append content “iRule Failure: [table keys –count –subtable “failure”]<p>”
foreach name [table keys –subtable “tracking”] {
append content “$name: [table keys –count –subtable $name]<br>”
}
HTTP::respond 200 content "<html><body>$content</body></html>"
event disable all
}
Then navigate to /status on that virtual to get execution profile of your iRule in the last minute. In this case 250 requests were sent through the iRule
iRule Status
iRule Success: 234
iRule Failure: 16
failed:No Header 1
failed:No html 15
success:Main 217
success:Alternate 20
So what happens here is we count the success and failure subtables and display the results. This will tell you how much traffic your iRule has been successfully processed over the last minute. Then we display the count of each status subtables and you now have the exact number of times you iRule exited at any point in the last minute.
From here you can do percentages and pretty much how you display this information is up to you. It is not just limited to iRule profiling. It could reflect useful information on any part of the information stream or the performance characteristics of your solution. You could even have an external monitoring system calling an XML formatted version of the same information to track the effectiveness of your iRule.
I hope that you enjoyed this second installment and next week we will talk about another kind of profiling. Please leave any comments you have below.