Traffic - Overview of traffic by users

This sBNC add-on gives admins a more user-friendly overview of the traffic consumption from their users. Exists to help you detect anomalies in the, clientsBNC and sBNCIRC traffic.

Requirements

Software Version Details
sBNC (w/TCL module) 1.1 Developed and tested on 1.1-371.

Download

Install

  • Download
  • Unzip
  • Place traffic.tcl in scripts/
    • Check if the value of the useraccess variable is to your liking
  • Add source scripts/traffic.tcl to sbnc.tcl
  • Rehash TCL
  • Use

Usage

Admin

/sbnc traffic <number|user [short|long]>
  • Using a number, it will return topN of the users.
    • A positive number between 0 and 50 gives a list of users with the most usage.
    • A negative number between 0 and -50 gives a list of users with the least usage.
  • If a valid user is specified, it will default to short.
    • short will display 2 numbers, clientIRC, for that particular user.
    • long will display all 4 numbers, clientsBNC and sBNCIRC.

User

  • Enabled by default with the useraccess variable in traffic.tcl.
/sbnc traffic [short|long]
  • short will display 2 numbers, clientIRC, for your user.
  • long (default) will display all 4 numbers, clientsBNC and sBNCIRC.

Source

Note that this source will/should be the development version, i.e. all changes noted in the history section, will have been made in this section.

traffic.tcl

#
# @name       Traffic - Overview of traffic by users
# @version    Build 4 (2007-02-23)
# @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
# @author     David Lorentsen <zyberdog@quakenet.org>
# @www        http://wiki.zyberdog.dk/sbnc/traffic
#
 
if {[namespace exists ::traffic]} {
	namespace delete ::traffic
}
 
namespace eval ::traffic {
 
	# Configuration
 
	# Allow normal users to look up their own TRAFFIC details?
	# 1 = enabled, 0 = disabled
	variable useraccess 1
 
	# Hide suspended users from TopN lists
	# 1 = hide, 0 = show
	variable hidesuspended 1
 
	# End of Configuraton
 
	# Binds
	internalbind command [namespace current]::commands
 
	# Main procedure
	proc commands {client parameters} {
		variable useraccess
		set cmd [lindex $parameters 0]
 
		if {[string equal -nocase $cmd "help"]} {
			if {[getbncuser $client "admin"]} {
				bncaddcommand traffic Admin "Overview of traffic by users" "Syntax: traffic <number|user \[short|long\]>\nList traffic usage for topN or specified user.\nA positive number lists N users with highest usage, negative number lists N users with least usage."
			} elseif {$useraccess == 1} {
				bncaddcommand traffic User "Shows your traffic usage" "Syntax traffic \[short|long\]\nShows your traffic usage"
			}
		} elseif {[string equal -nocase $cmd "traffic"]} {
			if {[getbncuser $client "admin"]} {
				if {[llength $parameters] < 2} {
					bncreply "Syntax: /sbnc traffic <number|user \[short|long\]>"
				} else {
					if {[string is integer [lindex $parameters 1]]} {
						set number [lindex $parameters 1]
						if {$number < -50 || $number > 50 || $number == 0} {
							set number 5
						}
						if {$number < 0} {
							set where "least"
						} else {
							set where "most"
						}
						set topn [topn $number]
						bncreply "Top [llength $topn] users ($where traffic):"
						set n 1
						set above [list]
						foreach top $topn {
							bncreply [format "%2d\. %-17s : %10s" $n [lindex $top 0] "[pretty [lindex $top 1]]"]
							incr n 1
							lappend above [lindex $top 0]
						}
						set total [gettotal $above]
						bncreply "  Total (above/all)   : [format "%10s" [pretty [lindex $total 1]]] / [format "%10s" [pretty [lindex $total 0]]]"
						bncreply "  Average (above/all) : [format "%10s" [pretty [expr [lindex $total 1] / [llength $above]]]] / [format "%10s" [pretty [expr [lindex $total 0] / [llength [bncuserlist]]]]]"
					} elseif {![string equal [lsearch -exact [bncuserlist] [lindex $parameters 1]] "-1"]} {
						set user [lindex $parameters 1]
						if {[llength $parameters] < 3 || [string equal -nocase [lindex $parameters 2] "short"]} {
							set traf [getshort $user]
							bncreply "Traffic for $user:"
							bncreply "  Client -> IRC : [format "%10s" [pretty [lindex $traf 1]]]"
							bncreply "  Client <- IRC : [format "%10s" [pretty [lindex $traf 0]]]"
							bncreply "  Total         : [format "%10s" [pretty [expr [lindex $traf 0] + [lindex $traf 1]]]]"
						} else {
							set traf [getlong $user]
							bncreply "Traffic for $user:"
							bncreply "  Client -> sBNC : [format "%10s" [pretty [lindex $traf 0]]]"
							bncreply "  Client <- sBNC : [format "%10s" [pretty [lindex $traf 1]]]"
							bncreply "  sBNC -> Server : [format "%10s" [pretty [lindex $traf 2]]]"
							bncreply "  sBNC <- Server : [format "%10s" [pretty [lindex $traf 3]]]"
							bncreply "  Total          : [format "%10s" [pretty [expr [lindex $traf 0] + [lindex $traf 1] + [lindex $traf 2] + [lindex $traf 3]]]]"
						}
					} else {
						bncreply "No such user."
					}
				}
			} elseif {$useraccess == 1} {
				if {[string equal -nocase [lindex $parameters 1] "short"]} {
					set traf [getshort $client]
					bncreply "Traffic for $client:"
					bncreply "  Client -> IRC : [format "%10s" [pretty [lindex $traf 1]]]"
					bncreply "  Client <- IRC : [format "%10s" [pretty [lindex $traf 0]]]"
					bncreply "  Total         : [format "%10s" [pretty [expr [lindex $traf 0] + [lindex $traf 1]]]]"
				} else {
					set traf [getlong $client]
					bncreply "Traffic for $client:"
					bncreply "  Client -> sBNC : [format "%10s" [pretty [lindex $traf 0]]]"
					bncreply "  Client <- sBNC : [format "%10s" [pretty [lindex $traf 1]]]"
					bncreply "  sBNC -> Server : [format "%10s" [pretty [lindex $traf 2]]]"
					bncreply "  sBNC <- Server : [format "%10s" [pretty [lindex $traf 3]]]"
					bncreply "  Total          : [format "%10s" [pretty [expr [lindex $traf 0] + [lindex $traf 1] + [lindex $traf 2] + [lindex $traf 3]]]]"
				}
			}
 
			haltoutput
		}
	}
 
	proc getshort {username} {
		set traffic [list]
		lappend traffic [expr [trafficstats $username "server" "in"] + [trafficstats $username "client" "out"]]
		lappend traffic [expr [trafficstats $username "server" "out"] + [trafficstats $username "client" "in"]]
		return $traffic
	}
 
	proc getlong {username} {
		set traffic [list]
		# Client > sBNC
		lappend traffic [trafficstats $username "client" "in"]
		# Client < sBNC
		lappend traffic [trafficstats $username "client" "out"]
		# Server < sBNC
		lappend traffic [trafficstats $username "server" "out"]
		# Server > sBNC
		lappend traffic [trafficstats $username "server" "in"]
		return $traffic
	}
 
	proc gettotal {above} {
		set traffic 0
		set traffic_above 0
		foreach user [bncuserlist] {
			set s [trafficstats $user]
			incr traffic $s
			if {![string equal [lsearch -exact $above $user] "-1"]} {
				incr traffic_above $s
			}
		}
 
		return [list $traffic $traffic_above]
	}
 
	# Get list of top $num users
	proc topn {num} {
		variable hidesuspended
		set topnl [list]
		foreach u [bncuserlist] {
			if {$hidesuspended && ![getbncuser $u lock]} {
				lappend topnl [list $u [trafficstats $u]]
			}
		}
		if {$num > 0} {
			return [lrange [lsort -decreasing -integer -index 1 $topnl] 0 [expr $num -1]]
		} else {
			return [lrange [lsort -increasing -integer -index 1 $topnl] 0 [expr [string range $num 1 end] -1]]
		}
	}
 
	# Convert byte input into pretty format
	proc pretty {bytes} {
		if {$bytes < 1024} {
			return [format "%.2f B " $bytes]
		} elseif {$bytes < 1048576} {
			return [format "%.2f KB" [expr $bytes / 1024.]]
		} elseif {$bytes < 1073741824} {
			return [format "%.2f MB" [expr $bytes / 1024. / 1024.]]
		} else {
			return [format "%.2f GB" [expr $bytes / 1024. / 1024. / 1024.]]
		}
	}
 
	# Unload everything
	proc unload {} {
		if {![string equal [lsearch -exact [internalbinds] "command [namespace current]::commands * *"] "-1"]} {
			if {[internalunbind "command" "[namespace current]::commands"]} {
				namespace delete [namespace current]
				return -code ok \
					"traffic.tcl unloaded"
			}
			return -code error \
				"bind found but could not unbind"
		}
		return -code error \
			"could not find bind to unbind"
	}
 
}

History

Changes followed by :!: may need attention when updating from an older build/version.

Build 4 (2007-02-23)

  • Hide suspended users when listing TopN users (if enabled in file) :!:

Build 3 (2007-02-22)

  • Now possible to list TopN users with the least traffic usage. See usage.

Build 2 (2007-01-14)

  • Made use of TCL namespaces.
  • Added unload procedure that will unbind and clean up.
  • TopN total and average now shows for both the listed users and all.
  • Added ability for non-admins to look up their own traffic (if enabled in file) :!:

Build 1 (2006-11-01)

  • No prior releases to compare with.
sbnc/traffic.txt · Last modified: 2007/02/23 20:57 by zyberdog