We are new to traffic script and just planning out our deployment of some Stingray devices. I'm looking to see if I can easily create and attach a unique ID in roughly the same way as mod_unique_id works on apache (see http://httpd.apache.org/docs/2.2/mod/mod_unique_id.html).
In apache they use the time, local I, pid and a counter local to the thread.
I don't mind how this is achieved, except that it must contain some uniqueness for the individual Stingray (a management IP address?) and some uniqueness for the request (pid, epoch and counter seem to make sense).
As such I imagine I'd be doing something like this:
$pid=sys.getpid();
$epoch=sys.time();
$counter=counter.increment(1)
$ip=request.getLocalIP();
$id= string.base64encode($epoch) . string.base64encode($ip) . string.base64encode($pid) . string.base64encode($counter);
http.removeHeader("UniqueId");
http.addHeader( "UniqueId", $id );
Except I don't think I can extract the counter like this. Is there already a built in way of generating a unique id that I'm missing, or is there some other way of better doing this?
Solved! Go to Solution.
To identify the individual traffic manager you can use
$host = sys.hostname();
The counter functions can't return their value to TrafficScript, they are only visible through the activity monitor or via SNMP. It's not really practical to try and implement a counter using the global hash table (data.get() and data.set()) because of the race condition involved in reading the counter, incrementing it and writing it back to memory. The best approach is therefore to combine a random number with the time of the request; although there is a chance of a collision we can minimise this beyond reasonable expectations.
$random = math.random(0x7ffffffe);
Instead of sys.time() we can use
$epoch = sys.time.highres();
Which gives the time since epoch in microseconds, so there won't be many requests passing through with that particular value.
Concatonate these, hash the result and you can be pretty confident that every request will be uniquely identifiable.
$randomdata = http.getHeader( "User-Agent" ) .
sys.hostname() .
request.getRemoteIP() .
sys.time.highres() .
math.random( 0x7ffffffe );
$uid = string.hexEncode( string.hashMD5( $randomdata ) );
Here's a function you can call in any rule to get the unique ID (UID). It stores the unique id in client-side cookie, and only generates one if it's missing:
sub getUID() {
$c = http.getCookie( "Z-UID" );
if( $c ) return $c;
# Perhaps we've just set it, and the client has not recieved the response
$c = connection.data.get( "Z-UID" );
if( $c ) return $c;
# Generate for the first time
$randomdata = http.getHeader( "User-Agent" ) .
sys.hostname() .
request.getRemoteIP() .
sys.time.highres() .
math.random( 0x7ffffffe );
$c = string.hexEncode( string.hashMD5( $randomdata ) );
http.setResponseCookie( "Z-UID", $c );
connection.data.set( "Z-UID", $c );
return $c;
}
To identify the individual traffic manager you can use
$host = sys.hostname();
The counter functions can't return their value to TrafficScript, they are only visible through the activity monitor or via SNMP. It's not really practical to try and implement a counter using the global hash table (data.get() and data.set()) because of the race condition involved in reading the counter, incrementing it and writing it back to memory. The best approach is therefore to combine a random number with the time of the request; although there is a chance of a collision we can minimise this beyond reasonable expectations.
$random = math.random(0x7ffffffe);
Instead of sys.time() we can use
$epoch = sys.time.highres();
Which gives the time since epoch in microseconds, so there won't be many requests passing through with that particular value.
Concatonate these, hash the result and you can be pretty confident that every request will be uniquely identifiable.
$randomdata = http.getHeader( "User-Agent" ) .
sys.hostname() .
request.getRemoteIP() .
sys.time.highres() .
math.random( 0x7ffffffe );
$uid = string.hexEncode( string.hashMD5( $randomdata ) );
Here's a function you can call in any rule to get the unique ID (UID). It stores the unique id in client-side cookie, and only generates one if it's missing:
sub getUID() {
$c = http.getCookie( "Z-UID" );
if( $c ) return $c;
# Perhaps we've just set it, and the client has not recieved the response
$c = connection.data.get( "Z-UID" );
if( $c ) return $c;
# Generate for the first time
$randomdata = http.getHeader( "User-Agent" ) .
sys.hostname() .
request.getRemoteIP() .
sys.time.highres() .
math.random( 0x7ffffffe );
$c = string.hexEncode( string.hashMD5( $randomdata ) );
http.setResponseCookie( "Z-UID", $c );
connection.data.set( "Z-UID", $c );
return $c;
}
Hi Owen,
i used the string.hashMD5( ) function and took the load balancer off air, apparently there is a memory leak.
How can i check for memory leaks in the lab?
Stuart
stuart taylor wrote:
i used the string.hashMD5( ) function and took the load balancer off air, apparently there is a memory leak.
This is a known issue in some versions of the traffic manager - it is not present in recent versions (9.6 onward). Please contact Riverbed support if you need support on specific versions.