The context: you have deployed IPv6 on your server, your Ruby on Rails webapp is running fine and is accessed both in IPv4 and IPv6. Nice. Now you want now to get a little report to know the proportion of IPv4/IPv6 requests. OK. I have the same need. When thinking about it, I dediced to fork the excellent request-log-analyser and update it. Then I realized that it could be achieved much more easily with a couple of awk lines.

The script can be downloaded here: count_ipv6_requests.sh (to be renamed .sh after download).

A few explanation

A typical request is written as follow in a Rails logfile:

Processing FooController#my_action (for 12.34.12.34 at 2010-02-17 06:25:30) [GET]
Parameters: {"id"=>"xyz"}
Rendering foo/my_action
Completed in 2ms (DB: 1) | 302 Found [http://www.myapp.com/foo/my_action/xyz]

We need to search for IP addresses only on lines starting with ‘Processing’. With awk, it is quite easy to display the field #n of a specific line. However, in our case this is not useful as sometimes the number of fields preceding the address varies. For example, in the previous example, the IP address is the 4th field, whereas in the line below:

Processing FooController#index to rss (for 12.34.12.34 at 2010-02-17 10:50:38) [GET]

the IP address is on the 5th field… So the solution is to start counting from the last item. Starting reversly, the IP address is always at the 5th field (x=NF-4).

Then we analyse and count each line. We could have use some regexps to identify v4 or v6 address, but in that case searching for ‘.’ (point) and : (semi-column) is enough (example of an IPv6 address: 2001:41d0:2:8bcb::22).

awk section of the script

awk '
  BEGIN { count = 0 ; ipv4 = 0 ; ipv6 = 0 }
  /Processing/ { x=NF-4;
  count += 1;
	if (index($x, ".") > 0) { ipv4 += 1; }
	if (index($x, ":") > 0) { ipv6 += 1; }
  }
  END { print count " requests have been analysed."
	printf("\tcount\t%%\n")
  printf("IPv4\t%d\t%3.2f%%\n", ipv4, ipv4/count*100);
  printf("IPv6\t%d\t%3.2f%%\n", ipv6, ipv6/count*100);
  printf("Total\t%d\t100%%\n", count);
}
' $1

How to use the script

Download it here (count_ipv6_requests.sh) or copy/paste it in a new file, make it executable and run it that way:

fab@nsxxxx:/var/www/yourapp/current$ ~/count_ipv6_requests.sh log/production.log
3945 requests have been analysed.
        count   %
IPv4    3838    97.29%
IPv6    107     2.71%
Total   3945    100%

This script will work until the Rails team decides to change the log file format.

PS : remember to rotate your logfiles regulary. This will improve your disk I/O performances -or at least it will not decrease your performances (a good post on that here).
PS 2: a good awk tutorial is available here. Its title is self speaking: “Explained by examples rather than by definitons”. Will be good to refresh your memories or learn awk. The awk man page is also a good source of knowledge.