I am investigating blocking certain countries from visiting our websites but would like to be able to write a count of each country that visits my site out to a file first for analysis. Is this possible within traffic script?
Solved! Go to Solution.
Hi David,
Blocking countries is relatively simple using the geo.* functions in TrafficScript along with connection.close() or http.SendResponse(), but counting the countries first and writing them to file is a little more complicated.
You can't write to files directly with TrafficScript, but you could create an alert and event under System -> Alerts which writes to a file and then call event.emit() within TrafficScript. However that's not very efficient, and you wouldn't want to call it on every request. So you would probably need some code which stored the data in memory using data.local.set(), and then fired off an event.emit() or even a log.info() once an hour.
This example uses log.info() to write the stats to the standard event log once per hour. The stats are recorded using the per process memory store so you will get a count for each Stingray child process (ie one per cpu core in your machine), and you'll need to be running Stingray version 9.4.
sub flushCodes() {
$codes = data.local.get("CountryCount-Codes");
foreach ($cc in string.split($codes)) {
$count = data.local.get("CountryCount-" . $cc );
$log .= $cc . ":" . $count . " ";
}
data.local.reset("CountryCount-");
data.local.set("CountryCount-lastFlush", sys.time() );
log.info("CountryLog " . $log);
}
$cc = geo.getCountryCode( request.getRemoteIP() );
if ( ! $cc ) {
$cc = "UNKNOWN";
}
$count = data.local.get("CountryCount-" . $cc);
if ( ! $count ) {
$codes = data.local.get("CountryCount-Codes");
if ( ! $codes ) {
$codes = $cc;
} else {
$codes .= " " . $cc;
}
data.local.set("CountryCount-Codes", $codes);
$count = 0;
}
data.local.set("CountryCount-" . $cc, ++$count);
$flush = data.local.get("CountryCount-lastFlush");
if ( ! $flush ) {
data.local.set("CountryCount-lastFlush", sys.time() );
} else {
if ( sys.time() - $flush > 3600 ) {
flushCodes();
}
}
Alternatively you could use the Request Logging feature of the Virtual Server, and record the country code from a TrafficScript variable. Then post-process the log to count the incidence of countries later.
Cheers,
Mark
Hi David,
Blocking countries is relatively simple using the geo.* functions in TrafficScript along with connection.close() or http.SendResponse(), but counting the countries first and writing them to file is a little more complicated.
You can't write to files directly with TrafficScript, but you could create an alert and event under System -> Alerts which writes to a file and then call event.emit() within TrafficScript. However that's not very efficient, and you wouldn't want to call it on every request. So you would probably need some code which stored the data in memory using data.local.set(), and then fired off an event.emit() or even a log.info() once an hour.
This example uses log.info() to write the stats to the standard event log once per hour. The stats are recorded using the per process memory store so you will get a count for each Stingray child process (ie one per cpu core in your machine), and you'll need to be running Stingray version 9.4.
sub flushCodes() {
$codes = data.local.get("CountryCount-Codes");
foreach ($cc in string.split($codes)) {
$count = data.local.get("CountryCount-" . $cc );
$log .= $cc . ":" . $count . " ";
}
data.local.reset("CountryCount-");
data.local.set("CountryCount-lastFlush", sys.time() );
log.info("CountryLog " . $log);
}
$cc = geo.getCountryCode( request.getRemoteIP() );
if ( ! $cc ) {
$cc = "UNKNOWN";
}
$count = data.local.get("CountryCount-" . $cc);
if ( ! $count ) {
$codes = data.local.get("CountryCount-Codes");
if ( ! $codes ) {
$codes = $cc;
} else {
$codes .= " " . $cc;
}
data.local.set("CountryCount-Codes", $codes);
$count = 0;
}
data.local.set("CountryCount-" . $cc, ++$count);
$flush = data.local.get("CountryCount-lastFlush");
if ( ! $flush ) {
data.local.set("CountryCount-lastFlush", sys.time() );
} else {
if ( sys.time() - $flush > 3600 ) {
flushCodes();
}
}
Alternatively you could use the Request Logging feature of the Virtual Server, and record the country code from a TrafficScript variable. Then post-process the log to count the incidence of countries later.
Cheers,
Mark
Thanks mark, That looks perfect.
Mark Boddington's solution is a great approach.
Just for completeness, here's a few alternatives that illustrate how to: