Scatter Charting Response Times

Problem this snippet solves:

This iRule, silently collects metrics on your application. It stores the HTTP response codes, page sizes, and the duration of time that it took for the app server to process the page. It then uses the Google Charts API to generate scatter plots to represent the data. The first plot is response time by the HTTP response code with the size of the bubble indicating the response size in bytes. The second plot is for the duration by the size of the request. Due to a limitation in the length of the Google Chart URL, a maximum of 500 entries can be reported on. I've added a 3 minute (180 second) timeout for the data in the session table to allow for self-cleanup.

How to use this snippet:

Assign the iRule to a virtual server. Hit some content on the application running on that virtual and then browse to the url [http://virtualserver/scatterchart]

Code :

when HTTP_REQUEST {
  
  set CHART_WIDTH 400
  set CHART_HEIGHT 325
  set MAX_KEYS 500;
  set TIMEOUT 180;
  set LIFETIME indefinite;
  set DATA_TABLE "scatterchart";
  set CODES_TABLE "scatterchartcodes";
  
  switch [HTTP::uri] {
    
    "/scatterchart" {
      
      set content "iRule Scatter Chart
"; append content ""; append content ""; append content "RELOAD"; append content " | RESET"; append content " | DATA"; append content "
"; HTTP::respond 200 Content $content; } "/scatterchart/data" { set content "Scatter Chart raw data
"; append content "RELOAD"; append content ""; foreach key [table keys -subtable $DATA_TABLE] { set code [getfield $key ":" 1]; set len [getfield $key ":" 2]; set duration [getfield $key ":" 3]; append content ""; } append content "
CodeLengthDuration (ms)
${code}${len}${duration}
RELOAD
"; HTTP::respond 200 content $content; } "/scatterchart/d_by_s" { # Duration by Size set d_x ""; set d_y ""; set d_s ""; set rows ""; set XMIN 0; set XMAX 1000; set YMIN 0; set YMAX 500; set SMAX 100; set CUR_KEY 0; foreach key [table keys -subtable $DATA_TABLE] { incr CUR_KEY; if { $CUR_KEY > $MAX_KEYS } { break; } set code [getfield $key ":" 1]; set len [getfield $key ":" 2]; set duration [getfield $key ":" 3]; if { $d_x != "" } { append d_x ","; } append d_x $duration if { $duration > $XMAX } { set XMAX $duration; } if { $d_y != "" } { append d_y ","; } append d_y $len; if { $len > $YMAX } { set YMAX $len; } if { $d_s != "" } { append d_s ","; } append d_s 100; } set chartUrl "http://0.chart.apis.google.com/chart?cht=s"; append chartUrl "&chtt=Web+Requests+Duration+By+Size"; append chartUrl "&chxt=x,y&chs=${CHART_WIDTH}x${CHART_HEIGHT}"; append chartUrl "&chco=F1F12F|989866|000000|224499|AA0033"; append chartUrl "&chxr=0,${XMIN},${XMAX}|1,${YMIN},${YMAX}"; append chartUrl "&chds=0,${XMAX},0,${YMAX},0,${SMAX}"; append chartUrl "&chg=0,10"; append chartUrl "&chd=t:${d_x}|${d_y}|${d_s}" HTTP::redirect $chartUrl; } "/scatterchart/t_by_c" { # Time by response code set d_x ""; set d_y ""; set d_s ""; set CUR_KEY 0; foreach key [table keys -subtable $DATA_TABLE] { incr CUR_KEY; if { $CUR_KEY > $MAX_KEYS } { break; } set code [getfield $key ":" 1]; set len [getfield $key ":" 2]; set duration [getfield $key ":" 3]; set len [expr $len / 75]; if { $len < 300 } { set len 300; } if { $d_x != "" } { append d_x ","; } append d_x $duration if { $d_y != "" } { append d_y ","; } append d_y $code; if { $d_s != "" } { append d_s ","; } append d_s $len; } set CHXL ""; set CHXP ""; # Build Y-Axis labels with the HTTP status codes foreach code [table keys -subtable $CODES_TABLE] { if { $CHXL != "" } { append CHXL "|" } append CHXL $code; if { $CHXP != "" } { append CHXP "," } append CHXP $code; } set XMIN 0; set XMAX 1000; set YMIN 0; set YMAX 500; set SMAX 1000; set chartUrl "http://1.chart.apis.google.com/chart?cht=s"; append chartUrl "&chtt=Web+Requests+Time+By+Status+Code"; append chartUrl "&chxt=x,y&chs=${CHART_WIDTH}x${CHART_HEIGHT}"; append chartUrl "&chco=F1F12F|989866|000000|224499|AA0033"; append chartUrl "&chxr=0,${XMIN},${XMAX}|1,${YMIN},${YMAX}"; append chartUrl "&chds=0,${XMAX},0,${YMAX},0,${SMAX}"; append chartUrl "&chxl=1:${CHXL}"; append chartUrl "&chxp=1,${CHXP}"; append chartUrl "&chg=0,10"; append chartUrl "&chd=t:${d_x}|${d_y}|${d_s}" HTTP::redirect $chartUrl; } "/scatterchart/reset" { table delete -subtable $DATA_TABLE -all; table delete -subtable $CODES_TABLE -all; HTTP::redirect "/scatterchart"; } } set t1 [clock clicks -milliseconds]; } when HTTP_RESPONSE { set t2 [clock clicks -milliseconds]; set duration [expr {$t2 - $t1}]; set code [HTTP::status]; set clen [HTTP::header Content-Length]; # Only monitor application traffic if { [HTTP::header Content-Type] starts_with "text/html" } { # Only allow $MAX_KEYS in table. set data "${code}:${clen}:${duration}"; if { [table incr -subtable $DATA_TABLE -mustexist $data] eq ""} { table set -subtable $DATA_TABLE $data 1 $TIMEOUT $LIFETIME; } if { [table incr -subtable $CODES_TABLE -mustexist $code] eq "" } { table set -subtable $CODES_TABLE $code 1 $TIMEOUT $LIFETIME; } } }
Published Mar 18, 2015
Version 1.0

Was this article helpful?

No CommentsBe the first to comment