BIND 10 stats201209-auth-merge, updated. 00a035d825e6a3f71955a78afec99c25517f3147 [stats201209-auth-merge] update auth.spec

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Aug 10 11:37:18 UTC 2012


The branch, stats201209-auth-merge has been updated
       via  00a035d825e6a3f71955a78afec99c25517f3147 (commit)
       via  005fc2840cc084ec0283b9bc788fc63b12504c36 (commit)
       via  8a001c349081b102849fc3566b57975ffd4629da (commit)
       via  155de05953fa54cb5e542cc7d297073a5f8c40be (commit)
       via  dfe1d6a967a7d1b88861d1c43021b49d906e279b (commit)
       via  8f91c6138419fbd5a15b4282ed399f3877e408af (commit)
       via  6bb1bc44919fc7017defe146b53f7c6378bae2be (commit)
       via  24c58ab484026263ab431a5ec412eb658b04d7bd (commit)
       via  f75d94f9e893d7019d1f2a7006669121fdaba300 (commit)
       via  ef68dd049b947d88aad20a8f8650a04b9e3e5f1a (commit)
       via  89a704be98580c6d433705887dac6a6ac96594e7 (commit)
       via  e62db3a0fc55c052561c4fa812600fcd1d057ba3 (commit)
       via  83419547e7edd4c3ae8295e5f87265fa9202799d (commit)
      from  3cd1c7285c20f84b14bc2bb5ae1435c6e6bd1e5e (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 00a035d825e6a3f71955a78afec99c25517f3147
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date:   Fri Aug 10 20:14:43 2012 +0900

    [stats201209-auth-merge] update auth.spec
    
    Updated statistics section of auth.spec for new statistics items.

commit 005fc2840cc084ec0283b9bc788fc63b12504c36
Merge: 3cd1c72 8a001c3
Author: Yoshitaka Aharen <aharen at jprs.co.jp>
Date:   Fri Aug 10 20:10:00 2012 +0900

    [stats201209-auth-merge] Merge branch 'trac2157'
    
    Conflicts:
    	ChangeLog
    	src/bin/auth/auth_srv.h
    	src/bin/auth/statistics.cc
    	src/bin/auth/statistics.h
    	src/bin/auth/tests/statistics_unittest.cc

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                 |    6 +
 doc/Doxyfile                              |    4 +-
 src/bin/auth/auth.spec.pre.in             |  924 ++++++++++++++++++++++++-----
 src/bin/auth/auth_srv.cc                  |  109 ++--
 src/bin/auth/auth_srv.h                   |   57 +-
 src/bin/auth/b10-auth.xml                 |   21 +-
 src/bin/auth/command.cc                   |    4 +-
 src/bin/auth/statistics.cc                |  457 ++++++++++----
 src/bin/auth/statistics.h                 |  209 ++++---
 src/bin/auth/statistics_items.h           |  376 ++++++++++++
 src/bin/auth/tests/auth_srv_unittest.cc   |  211 +++++--
 src/bin/auth/tests/statistics_unittest.cc |  436 ++++----------
 12 files changed, 1998 insertions(+), 816 deletions(-)
 create mode 100644 src/bin/auth/statistics_items.h

-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index 7716b44..f9ec128 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+TBD.	[func]		fujiwara, y-aharen
+	b10-auth collects and sends query/response statistics items
+	defined in wiki:StatisticsItems.
+	Per-zone query/response statistics and socket statistics are
+	planned to be implemented.
+
 458.	[build]*	jinmei
 	BIND 10 now relies on Boost offset_ptr, which caused some new
 	portability issues.  Such issues are detected at ./configure time.
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 7e122e9..ee85eef 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -579,8 +579,8 @@ INPUT                  = ../src/lib/exceptions ../src/lib/cc \
     ../src/lib/log/compiler ../src/lib/asiolink/ ../src/lib/nsas \
     ../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
     ../src/bin/sockcreator/ ../src/lib/util/ ../src/lib/util/io/ \
-    ../src/lib/resolve ../src/lib/acl ../src/bin/dhcp6 ../src/lib/dhcp \
-    ../src/bin/dhcp4 ../tests/tools/perfdhcp devel
+    ../src/lib/resolve ../src/lib/acl ../src/lib/statistics ../src/lib/dhcp \
+    ../src/bin/dhcp4 ../src/bin/dhcp6 ../tests/tools/perfdhcp devel
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
diff --git a/src/bin/auth/auth.spec.pre.in b/src/bin/auth/auth.spec.pre.in
index b9587e6..55220d8 100644
--- a/src/bin/auth/auth.spec.pre.in
+++ b/src/bin/auth/auth.spec.pre.in
@@ -136,284 +136,932 @@
     ],
     "statistics": [
       {
-        "item_name": "queries.tcp",
+        "item_name": "auth.server.qr.request.v4",
         "item_type": "integer",
         "item_optional": false,
         "item_default": 0,
-        "item_title": "Queries TCP ",
-        "item_description": "A number of total query counts which all auth servers receive over TCP since they started initially"
+        "item_title": "request.v4",
+        "item_description": "Number of IPv4 requests received"
       },
       {
-        "item_name": "queries.udp",
+        "item_name": "auth.server.qr.request.v6",
         "item_type": "integer",
         "item_optional": false,
         "item_default": 0,
-        "item_title": "Queries UDP",
-        "item_description": "A number of total query counts which all auth servers receive over UDP since they started initially"
+        "item_title": "request.v6",
+        "item_description": "Number of IPv6 requests received"
       },
       {
-        "item_name": "opcode.query",
+        "item_name": "auth.server.qr.request.edns0",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received query requests",
-        "item_description": "The number of total request counts whose opcode is query"
+        "item_title": "request.edns0",
+        "item_description": "Number of requests with EDNS(0) received"
       },
       {
-        "item_name": "opcode.iquery",
+        "item_name": "auth.server.qr.request.badednsver",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received inverse query requests",
-        "item_description": "The number of total request counts whose opcode is inverse query"
+        "item_title": "request.badednsver",
+        "item_description": "Number of requests with unsupported EDNS version received"
       },
       {
-        "item_name": "opcode.status",
+        "item_name": "auth.server.qr.request.tsig",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received status requests",
-        "item_description": "The number of total request counts whose opcode is status"
+        "item_title": "request.tsig",
+        "item_description": "Number of requests with TSIG received"
       },
       {
-        "item_name": "opcode.reserved3",
+        "item_name": "auth.server.qr.request.sig0",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 3",
-        "item_description": "The number of total request counts whose opcode is 3 (reserved)"
+        "item_title": "request.sig0",
+        "item_description": "Number of requests with SIG(0) received; not implemented in BIND 10"
       },
       {
-        "item_name": "opcode.notify",
+        "item_name": "auth.server.qr.request.badsig",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received notify requests",
-        "item_description": "The number of total request counts whose opcode is notify"
+        "item_title": "request.badsig",
+        "item_description": "Number of requests with invalid TSIG or SIG(0) signature received"
       },
       {
-        "item_name": "opcode.update",
+        "item_name": "auth.server.qr.request.udp",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received update requests",
-        "item_description": "The number of total request counts whose opcode is update"
+        "item_title": "request.udp",
+        "item_description": "Number of UDP requests received"
       },
       {
-        "item_name": "opcode.reserved6",
+        "item_name": "auth.server.qr.request.tcp",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 6",
-        "item_description": "The number of total request counts whose opcode is 6 (reserved)"
+        "item_title": "request.tcp",
+        "item_description": "Number of TCP requests received"
       },
       {
-        "item_name": "opcode.reserved7",
+        "item_name": "auth.server.qr.request.dnssec_ok",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 7",
-        "item_description": "The number of total request counts whose opcode is 7 (reserved)"
+        "item_title": "request.dnssec_ok",
+        "item_description": "Number of requests with DO bit"
       },
       {
-        "item_name": "opcode.reserved8",
+        "item_name": "auth.server.qr.opcode.query",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 8",
-        "item_description": "The number of total request counts whose opcode is 8 (reserved)"
+        "item_title": "opcode.query",
+        "item_description": "Number of Opcode=QUERY requests received"
       },
       {
-        "item_name": "opcode.reserved9",
+        "item_name": "auth.server.qr.opcode.iquery",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 9",
-        "item_description": "The number of total request counts whose opcode is 9 (reserved)"
+        "item_title": "opcode.iquery",
+        "item_description": "Number of Opcode=IQUERY requests received"
       },
       {
-        "item_name": "opcode.reserved10",
+        "item_name": "auth.server.qr.opcode.status",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 10",
-        "item_description": "The number of total request counts whose opcode is 10 (reserved)"
+        "item_title": "opcode.status",
+        "item_description": "Number of Opcode=STATUS requests received"
       },
       {
-        "item_name": "opcode.reserved11",
+        "item_name": "auth.server.qr.opcode.notify",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 11",
-        "item_description": "The number of total request counts whose opcode is 11 (reserved)"
+        "item_title": "opcode.notify",
+        "item_description": "Number of Opcode=NOTIFY requests received"
       },
       {
-        "item_name": "opcode.reserved12",
+        "item_name": "auth.server.qr.opcode.update",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 12",
-        "item_description": "The number of total request counts whose opcode is 12 (reserved)"
+        "item_title": "opcode.update",
+        "item_description": "Number of Opcode=UPDATE requests received"
       },
       {
-        "item_name": "opcode.reserved13",
+        "item_name": "auth.server.qr.opcode.other",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 13",
-        "item_description": "The number of total request counts whose opcode is 13 (reserved)"
+        "item_title": "opcode.other",
+        "item_description": "Number of requests in other OpCode received"
       },
       {
-        "item_name": "opcode.reserved14",
+        "item_name": "auth.server.qr.qtype.a",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 14",
-        "item_description": "The number of total request counts whose opcode is 14 (reserved)"
+        "item_title": "qtype.a",
+        "item_description": "Number of QTYPE = A queries received"
       },
       {
-        "item_name": "opcode.reserved15",
+        "item_name": "auth.server.qr.qtype.ns",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Received requests opcode 15",
-        "item_description": "The number of total request counts whose opcode is 15 (reserved)"
+        "item_title": "qtype.ns",
+        "item_description": "Number of QTYPE = NS queries received"
       },
       {
-        "item_name": "rcode.noerror",
+        "item_name": "auth.server.qr.qtype.md",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent success response",
-        "item_description": "The number of total responses with rcode 0 (NOERROR)"
+        "item_title": "qtype.md",
+        "item_description": "Number of QTYPE = MD queries received"
       },
       {
-        "item_name": "rcode.formerr",
+        "item_name": "auth.server.qr.qtype.mf",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'format error' response",
-        "item_description": "The number of total responses with rcode 1 (FORMERR)"
+        "item_title": "qtype.mf",
+        "item_description": "Number of QTYPE = MF queries received"
       },
       {
-        "item_name": "rcode.servfail",
+        "item_name": "auth.server.qr.qtype.cname",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'server failure' response",
-        "item_description": "The number of total responses with rcode 2 (SERVFAIL)"
+        "item_title": "qtype.cname",
+        "item_description": "Number of QTYPE = CNAME queries received"
       },
       {
-        "item_name": "rcode.nxdomain",
+        "item_name": "auth.server.qr.qtype.soa",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'name error' response",
-        "item_description": "The number of total responses with rcode 3 (NXDOMAIN)"
+        "item_title": "qtype.soa",
+        "item_description": "Number of QTYPE = SOA queries received"
       },
       {
-        "item_name": "rcode.notimp",
+        "item_name": "auth.server.qr.qtype.mb",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'not implemented' response",
-        "item_description": "The number of total responses with rcode 4 (NOTIMP)"
+        "item_title": "qtype.mb",
+        "item_description": "Number of QTYPE = MB queries received"
       },
       {
-        "item_name": "rcode.refused",
+        "item_name": "auth.server.qr.qtype.mg",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'refused' response",
-        "item_description": "The number of total responses with rcode 5 (REFUSED)"
+        "item_title": "qtype.mg",
+        "item_description": "Number of QTYPE = MG queries received"
       },
       {
-        "item_name": "rcode.yxdomain",
+        "item_name": "auth.server.qr.qtype.mr",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'name unexpectedly exists' response",
-        "item_description": "The number of total responses with rcode 6 (YXDOMAIN)"
+        "item_title": "qtype.mr",
+        "item_description": "Number of QTYPE = MR queries received"
       },
       {
-        "item_name": "rcode.yxrrset",
+        "item_name": "auth.server.qr.qtype.null",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'rrset unexpectedly exists' response",
-        "item_description": "The number of total responses with rcode 7 (YXRRSET)"
+        "item_title": "qtype.null",
+        "item_description": "Number of QTYPE = NULL queries received"
       },
       {
-        "item_name": "rcode.nxrrset",
+        "item_name": "auth.server.qr.qtype.wks",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'no such rrset' response",
-        "item_description": "The number of total responses with rcode 8 (NXRRSET)"
+        "item_title": "qtype.wks",
+        "item_description": "Number of QTYPE = WKS queries received"
       },
       {
-        "item_name": "rcode.notauth",
+        "item_name": "auth.server.qr.qtype.ptr",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'not authoritative' response",
-        "item_description": "The number of total responses with rcode 9 (NOTAUTH)"
+        "item_title": "qtype.ptr",
+        "item_description": "Number of QTYPE = PTR queries received"
       },
       {
-        "item_name": "rcode.notzone",
+        "item_name": "auth.server.qr.qtype.hinfo",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'name not in zone' response",
-        "item_description": "The number of total responses with rcode 10 (NOTZONE)"
+        "item_title": "qtype.hinfo",
+        "item_description": "Number of QTYPE = HINFO queries received"
       },
       {
-        "item_name": "rcode.reserved11",
+        "item_name": "auth.server.qr.qtype.minfo",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent response with rcode 11",
-        "item_description": "The number of total responses with rcode 11 (reserved)"
+        "item_title": "qtype.minfo",
+        "item_description": "Number of QTYPE = MINFO queries received"
       },
       {
-        "item_name": "rcode.reserved12",
+        "item_name": "auth.server.qr.qtype.mx",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent response with rcode 12",
-        "item_description": "The number of total responses with rcode 12 (reserved)"
+        "item_title": "qtype.mx",
+        "item_description": "Number of QTYPE = MX queries received"
       },
       {
-        "item_name": "rcode.reserved13",
+        "item_name": "auth.server.qr.qtype.txt",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent response with rcode 13",
-        "item_description": "The number of total responses with rcode 13 (reserved)"
+        "item_title": "qtype.txt",
+        "item_description": "Number of QTYPE = TXT queries received"
       },
       {
-        "item_name": "rcode.reserved14",
+        "item_name": "auth.server.qr.qtype.rp",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent response with rcode 14",
-        "item_description": "The number of total responses with rcode 14 (reserved)"
+        "item_title": "qtype.rp",
+        "item_description": "Number of QTYPE = RP queries received"
       },
       {
-        "item_name": "rcode.reserved15",
+        "item_name": "auth.server.qr.qtype.afsdb",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent response with rcode 15",
-        "item_description": "The number of total responses with rcode 15 (reserved)"
+        "item_title": "qtype.afsdb",
+        "item_description": "Number of QTYPE = AFSDB queries received"
       },
       {
-        "item_name": "rcode.badvers",
+        "item_name": "auth.server.qr.qtype.x25",
         "item_type": "integer",
-        "item_optional": true,
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.x25",
+        "item_description": "Number of QTYPE = X25 queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.isdn",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.isdn",
+        "item_description": "Number of QTYPE = ISDN queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.rt",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.rt",
+        "item_description": "Number of QTYPE = RT queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nsap",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nsap",
+        "item_description": "Number of QTYPE = NSAP queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nsap-ptr",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nsap-ptr",
+        "item_description": "Number of QTYPE = NSAP-PTR queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.sig",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.sig",
+        "item_description": "Number of QTYPE = SIG queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.key",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.key",
+        "item_description": "Number of QTYPE = KEY queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.px",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.px",
+        "item_description": "Number of QTYPE = PX queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.gpos",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.gpos",
+        "item_description": "Number of QTYPE = GPOS queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.aaaa",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.aaaa",
+        "item_description": "Number of QTYPE = AAAA queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.loc",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.loc",
+        "item_description": "Number of QTYPE = LOC queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nxt",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nxt",
+        "item_description": "Number of QTYPE = NXT queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.eid",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.eid",
+        "item_description": "Number of QTYPE = EID queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nimloc",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nimloc",
+        "item_description": "Number of QTYPE = NIMLOC queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.srv",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.srv",
+        "item_description": "Number of QTYPE = SRV queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.atma",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.atma",
+        "item_description": "Number of QTYPE = ATMA queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.naptr",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.naptr",
+        "item_description": "Number of QTYPE = NAPTR queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.kx",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.kx",
+        "item_description": "Number of QTYPE = KX queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.cert",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.cert",
+        "item_description": "Number of QTYPE = CERT queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.a6",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.a6",
+        "item_description": "Number of QTYPE = A6 queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.dname",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.dname",
+        "item_description": "Number of QTYPE = DNAME queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.sink",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.sink",
+        "item_description": "Number of QTYPE = SINK queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.opt",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.opt",
+        "item_description": "Number of QTYPE = OPT queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.apl",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.apl",
+        "item_description": "Number of QTYPE = APL queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.ds",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.ds",
+        "item_description": "Number of QTYPE = DS queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.sshfp",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.sshfp",
+        "item_description": "Number of QTYPE = SSHFP queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.ipseckey",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.ipseckey",
+        "item_description": "Number of QTYPE = IPSECKEY queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.rrsig",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.rrsig",
+        "item_description": "Number of QTYPE = RRSIG queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nsec",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nsec",
+        "item_description": "Number of QTYPE = NSEC queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.dnskey",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.dnskey",
+        "item_description": "Number of QTYPE = DNSKEY queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.dhcid",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.dhcid",
+        "item_description": "Number of QTYPE = DHCID queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nsec3",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nsec3",
+        "item_description": "Number of QTYPE = NSEC3 queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.nsec3param",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.nsec3param",
+        "item_description": "Number of QTYPE = NSEC3PARAM queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.hip",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.hip",
+        "item_description": "Number of QTYPE = HIP queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.ninfo",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.ninfo",
+        "item_description": "Number of QTYPE = NINFO queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.rkey",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.rkey",
+        "item_description": "Number of QTYPE = RKEY queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.talink",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.talink",
+        "item_description": "Number of QTYPE = TALINK queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.spf",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.spf",
+        "item_description": "Number of QTYPE = SPF queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.uinfo",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.uinfo",
+        "item_description": "Number of QTYPE = UINFO queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.uid",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.uid",
+        "item_description": "Number of QTYPE = UID queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.gid",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.gid",
+        "item_description": "Number of QTYPE = GID queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.unspec",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.unspec",
+        "item_description": "Number of QTYPE = UNSPEC queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.tkey",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.tkey",
+        "item_description": "Number of QTYPE = TKEY queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.tsig",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.tsig",
+        "item_description": "Number of QTYPE = TSIG queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.ixfr",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.ixfr",
+        "item_description": "Number of QTYPE = IXFR queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.axfr",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.axfr",
+        "item_description": "Number of QTYPE = AXFR queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.mailb",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.mailb",
+        "item_description": "Number of QTYPE = MAILB queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.maila",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.maila",
+        "item_description": "Number of QTYPE = MAILA queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.uri",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.uri",
+        "item_description": "Number of QTYPE = URI queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.caa",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.caa",
+        "item_description": "Number of QTYPE = CAA queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.ta",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.ta",
+        "item_description": "Number of QTYPE = TA queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.dlv",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.dlv",
+        "item_description": "Number of QTYPE = DLV queries received"
+      },
+      {
+        "item_name": "auth.server.qr.qtype.other",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qtype.other",
+        "item_description": "Number of queries in other QTYPE received"
+      },
+      {
+        "item_name": "auth.server.qr.response",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "response",
+        "item_description": "Number of responses sent"
+      },
+      {
+        "item_name": "auth.server.qr.response.truncated",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "response.truncated",
+        "item_description": "Number of truncated responses sent"
+      },
+      {
+        "item_name": "auth.server.qr.response.edns0",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "response.edns0",
+        "item_description": "Number of responses with EDNS0; not implemented in BIND 10"
+      },
+      {
+        "item_name": "auth.server.qr.response.tsig",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "response.tsig",
+        "item_description": "Number of responses with TSIG"
+      },
+      {
+        "item_name": "auth.server.qr.response.sig0",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "response.sig0",
+        "item_description": "Number of responses with SIG(0); not implemented in BIND 10"
+      },
+      {
+        "item_name": "auth.server.qr.qrysuccess",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qrysuccess",
+        "item_description": "Number of queries resulted in rcode = NOERROR and answer RR >= 1"
+      },
+      {
+        "item_name": "auth.server.qr.qryauthans",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qryauthans",
+        "item_description": "Number of queries resulted in authoritative answer"
+      },
+      {
+        "item_name": "auth.server.qr.qrynoauthans",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qrynoauthans",
+        "item_description": "Number of queries resulted in non-authoritative answer"
+      },
+      {
+        "item_name": "auth.server.qr.qryreferral",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qryreferral",
+        "item_description": "Number of queries resulted in referral answer"
+      },
+      {
+        "item_name": "auth.server.qr.qrynxrrset",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "qrynxrrset",
+        "item_description": "Number of queries resulted in NOERROR but answer RR == 0"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.noerror",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.noerror",
+        "item_description": "Number of queries resulted in RCODE = 0 (NoError)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.formerr",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.formerr",
+        "item_description": "Number of queries resulted in RCODE = 1 (FormErr)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.servfail",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.servfail",
+        "item_description": "Number of queries resulted in RCODE = 2 (ServFail)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.nxdomain",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.nxdomain",
+        "item_description": "Number of queries resulted in RCODE = 3 (NXDomain)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.notimp",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.notimp",
+        "item_description": "Number of queries resulted in RCODE = 4 (NotImp)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.refused",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.refused",
+        "item_description": "Number of queries resulted in RCODE = 5 (Refused)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.yxdomain",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.yxdomain",
+        "item_description": "Number of queries resulted in RCODE = 6 (YXDomain)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.yxrrset",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.yxrrset",
+        "item_description": "Number of queries resulted in RCODE = 7 (YXRRSet)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.nxrrset",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.nxrrset",
+        "item_description": "Number of queries resulted in RCODE = 8 (NXRRSet)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.notauth",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.notauth",
+        "item_description": "Number of queries resulted in RCODE = 9 (NotAuth)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.notzone",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.notzone",
+        "item_description": "Number of queries resulted in RCODE = 10 (NotZone)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badsigvers",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badsigvers",
+        "item_description": "Number of queries resulted in RCODE = 16 (BADVERS, BADSIG)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badkey",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badkey",
+        "item_description": "Number of queries resulted in RCODE = 17 (BADKEY)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badtime",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badtime",
+        "item_description": "Number of queries resulted in RCODE = 18 (BADTIME)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badmode",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badmode",
+        "item_description": "Number of queries resulted in RCODE = 19 (BADMODE)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badname",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badname",
+        "item_description": "Number of queries resulted in RCODE = 20 (BADNAME)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badalg",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badalg",
+        "item_description": "Number of queries resulted in RCODE = 21 (BADALG)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.badtrunc",
+        "item_type": "integer",
+        "item_optional": false,
+        "item_default": 0,
+        "item_title": "rcode.badtrunc",
+        "item_description": "Number of queries resulted in RCODE = 22 (BADTRUNC)"
+      },
+      {
+        "item_name": "auth.server.qr.rcode.other",
+        "item_type": "integer",
+        "item_optional": false,
         "item_default": 0,
-        "item_title": "Sent 'EDNS version not implemented' response",
-        "item_description": "The number of total responses with rcode 16 (BADVERS)"
+        "item_title": "rcode.other",
+        "item_description": "Number of queries resulted in other RCODEs"
       }
     ]
   }
diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc
index 0f8ba00..55a1d84 100644
--- a/src/bin/auth/auth_srv.cc
+++ b/src/bin/auth/auth_srv.cc
@@ -85,6 +85,7 @@ using namespace isc::xfr;
 using namespace isc::asiolink;
 using namespace isc::asiodns;
 using namespace isc::server_common::portconfig;
+using isc::auth::statistics::Counters;
 
 namespace {
 // A helper class for cleaning up message renderer.
@@ -248,7 +249,7 @@ public:
     AbstractSession* xfrin_session_;
 
     /// Query counters for statistics
-    AuthCounters counters_;
+    Counters counters_;
 
     /// Addresses we listen on
     AddressList listen_addresses_;
@@ -286,27 +287,26 @@ public:
 
     /// \brief Resume the server
     ///
-    /// This is a wrapper call for DNSServer::resume(done), if 'done' is true,
-    /// the Rcode set in the given Message is counted in the statistics
-    /// counter.
+    /// This is a wrapper call for DNSServer::resume(done). Query/Response
+    /// statistics counters are incremented in this method.
     ///
     /// This method is expected to be called by processMessage()
     ///
     /// \param server The DNSServer as passed to processMessage()
     /// \param message The response as constructed by processMessage()
-    /// \param done If true, the Rcode from the given message is counted,
-    ///             this value is then passed to server->resume(bool)
+    /// \param stats_attrs query/response attributes for statistics which is
+    ///                    not explained in \p messsage
+    /// \param done If true, it indicates there is a response.
+    ///             this value will be passed to server->resume(bool)
     void resumeServer(isc::asiodns::DNSServer* server,
                       isc::dns::Message& message,
-                      bool done);
+                      statistics::QRAttributes& stats_attrs,
+                      const bool done);
 
 private:
     bool xfrout_connected_;
     AbstractXfroutClient& xfrout_client_;
 
-    /// Increment query counter
-    void incCounter(const int protocol);
-
     // validateStatistics
     bool validateStatistics(isc::data::ConstElementPtr data) const;
 
@@ -485,6 +485,12 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
                         OutputBuffer& buffer, DNSServer* server)
 {
     InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
+    statistics::QRAttributes stats_attrs;
+
+    // statistics: check transport carrying the message (IP, transport)
+    stats_attrs.setQueryIPVersion(io_message.getRemoteEndpoint().getFamily());
+    stats_attrs.setQueryTransportProtocol(
+        io_message.getRemoteEndpoint().getProtocol());
 
     // First, check the header part.  If we fail even for the base header,
     // just drop the message.
@@ -494,13 +500,13 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
         // Ignore all responses.
         if (message.getHeaderFlag(Message::HEADERFLAG_QR)) {
             LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_RECEIVED);
-            impl_->resumeServer(server, message, false);
+            impl_->resumeServer(server, message, stats_attrs, false);
             return;
         }
     } catch (const Exception& ex) {
         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_HEADER_PARSE_FAIL)
                   .arg(ex.what());
-        impl_->resumeServer(server, message, false);
+        impl_->resumeServer(server, message, stats_attrs, false);
         return;
     }
 
@@ -511,13 +517,13 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PROTOCOL_ERROR)
                   .arg(error.getRcode().toText()).arg(error.what());
         makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode());
-        impl_->resumeServer(server, message, true);
+        impl_->resumeServer(server, message, stats_attrs, true);
         return;
     } catch (const Exception& ex) {
         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PARSE_ERROR)
                   .arg(ex.what());
         makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
-        impl_->resumeServer(server, message, true);
+        impl_->resumeServer(server, message, stats_attrs, true);
         return;
     } // other exceptions will be handled at a higher layer.
 
@@ -540,21 +546,35 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
                                            **impl_->keyring_));
         tsig_error = tsig_context->verify(tsig_record, io_message.getData(),
                                           io_message.getDataSize());
+        // statistics: check TSIG attributes
+        // SIG(0) is currently not implemented in Auth
+        stats_attrs.setQuerySig(true, false,
+                                ( tsig_error == TSIGError::NOERROR() ));
     }
 
     if (tsig_error != TSIGError::NOERROR()) {
         makeErrorMessage(impl_->renderer_, message, buffer,
                          tsig_error.toRcode(), tsig_context);
-        impl_->resumeServer(server, message, true);
+        impl_->resumeServer(server, message, stats_attrs, true);
         return;
     }
 
     const Opcode opcode = message.getOpcode();
     bool send_answer = true;
     try {
-        // update per opcode statistics counter.  This can only be reliable
-        // after TSIG check succeeds.
-        impl_->counters_.inc(message.getOpcode());
+        // statistics: check EDNS
+        //     note: This can only be reliable after TSIG check succeeds.
+        {
+            ConstEDNSPtr edns = message.getEDNS();
+            if (edns != NULL) {
+                stats_attrs.setQueryEDNS(true, edns->getVersion() == 0);
+                stats_attrs.setQueryDO(edns->getDNSSECAwareness());
+            }
+        }
+
+        // statistics: check OpCode
+        //     note: This can only be reliable after TSIG check succeeds.
+        stats_attrs.setQueryOpCode(opcode.getCode());
 
         if (opcode == Opcode::NOTIFY()) {
             send_answer = impl_->processNotify(io_message, message, buffer,
@@ -596,7 +616,7 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE_UNKNOWN);
         makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
     }
-    impl_->resumeServer(server, message, send_answer);
+    impl_->resumeServer(server, message, stats_attrs, send_answer);
 }
 
 bool
@@ -613,9 +633,6 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
     message.setHeaderFlag(Message::HEADERFLAG_AA);
     message.setRcode(Rcode::NOERROR());
 
-    // Increment query counter.
-    incCounter(io_message.getSocket().getProtocol());
-
     if (remote_edns) {
         EDNSPtr local_edns = EDNSPtr(new EDNS());
         local_edns->setDNSSECAwareness(dnssec_ok);
@@ -630,6 +647,7 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
         if (list) {
             const RRType& qtype = question->getType();
             const Name& qname = question->getName();
+            // TODO: statistics: zone origin
             query_.process(*list, qname, qtype, message, dnssec_ok);
         } else {
             makeErrorMessage(renderer_, message, buffer, Rcode::REFUSED());
@@ -660,9 +678,6 @@ AuthSrvImpl::processXfrQuery(const IOMessage& io_message, Message& message,
                              OutputBuffer& buffer,
                              auto_ptr<TSIGContext> tsig_context)
 {
-    // Increment query counter.
-    incCounter(io_message.getSocket().getProtocol());
-
     if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
         LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_AXFR_UDP);
         makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
@@ -795,19 +810,6 @@ AuthSrvImpl::processUpdate(const IOMessage& io_message) {
 }
 
 void
-AuthSrvImpl::incCounter(const int protocol) {
-    // Increment query counter.
-    if (protocol == IPPROTO_UDP) {
-        counters_.inc(AuthCounters::SERVER_UDP_QUERY);
-    } else if (protocol == IPPROTO_TCP) {
-        counters_.inc(AuthCounters::SERVER_TCP_QUERY);
-    } else {
-        // unknown protocol
-        isc_throw(Unexpected, "Unknown protocol: " << protocol);
-    }
-}
-
-void
 AuthSrvImpl::registerStatisticsValidator() {
     counters_.registerStatisticsValidator(
         boost::bind(&AuthSrvImpl::validateStatistics, this, _1));
@@ -824,10 +826,16 @@ AuthSrvImpl::validateStatistics(isc::data::ConstElementPtr data) const {
 }
 
 void
-AuthSrvImpl::resumeServer(DNSServer* server, Message& message, bool done) {
+AuthSrvImpl::resumeServer(DNSServer* server, Message& message,
+                          statistics::QRAttributes& stats_attrs,
+                          const bool done)
+{
     if (done) {
-        counters_.inc(message.getRcode());
+        stats_attrs.answerHasSent();
+        // isTruncated from MessageRenderer
+        stats_attrs.setResponseTruncated(renderer_.isTruncated());
     }
+    counters_.inc(stats_attrs, message);
     server->resume(done);
 }
 
@@ -846,23 +854,14 @@ AuthSrv::updateConfig(ConstElementPtr new_config) {
     }
 }
 
-ElementPtr AuthSrv::getStatistics() const {
-    return (impl_->counters_.getStatistics());
-}
-
-uint64_t
-AuthSrv::getCounter(const AuthCounters::ServerCounterType type) const {
-    return (impl_->counters_.getCounter(type));
-}
-
-uint64_t
-AuthSrv::getCounter(const Opcode opcode) const {
-    return (impl_->counters_.getCounter(opcode));
+const Counters::item_tree_type
+AuthSrv::get(const Counters::item_node_name_set_type& trees) const {
+    return (impl_->counters_.get(trees));
 }
 
-uint64_t
-AuthSrv::getCounter(const Rcode rcode) const {
-    return (impl_->counters_.getCounter(rcode));
+const Counters::item_tree_type
+AuthSrv::dump() const {
+    return (impl_->counters_.dump());
 }
 
 const AddressList&
diff --git a/src/bin/auth/auth_srv.h b/src/bin/auth/auth_srv.h
index 1fca8e1..24139b4 100644
--- a/src/bin/auth/auth_srv.h
+++ b/src/bin/auth/auth_srv.h
@@ -20,7 +20,6 @@
 #include <config/ccsession.h>
 #include <datasrc/factory.h>
 #include <dns/message.h>
-#include <dns/opcode.h>
 #include <util/buffer.h>
 
 #include <asiodns/dns_server.h>
@@ -202,57 +201,25 @@ public:
     ///
     void setXfrinSession(isc::cc::AbstractSession* xfrin_session);
 
-    /// \brief Returns statistics data
+    /// \brief Get the values of specified counters.
     ///
-    /// This function can throw an exception from
-    /// AuthCounters::getStatistics().
+    /// This function returns names and values of counter.
     ///
-    /// \return JSON format statistics data.
-    isc::data::ElementPtr getStatistics() const;
-
-    /// \brief Get the value of counter in the AuthCounters.
-    ///
-    /// This function calls AuthCounters::getStatistics() and
-    /// returns its return value.
-    ///
-    /// This function never throws an exception as far as
-    /// AuthCounters::getStatistics() doesn't throw.
+    /// \throw bad_alloc
     ///
-    /// Note: Currently this function is for testing purpose only.
-    ///
-    /// \param type Type of a counter to get the value of
-    ///
-    /// \return the value of the counter.
-
-    uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
-
-    /// \brief Get the value of per Opcode counter in the Auth Counters.
-    ///
-    /// This function calls AuthCounters::getCounter(isc::dns::Opcode) and
-    /// returns its return value.
-    ///
-    /// \note This is a tentative interface as an attempt of experimentally
-    /// supporting more statistics counters.  This should eventually be more
-    /// generalized.  In any case, this method is mainly for testing.
-    ///
-    /// \throw None
-    /// \param opcode The opcode of the counter to get the value of
-    /// \return the value of the counter.
-    uint64_t getCounter(const isc::dns::Opcode opcode) const;
+    /// \return a tree of statistics items.
+    const isc::auth::statistics::Counters::item_tree_type get(
+        const isc::auth::statistics::Counters::item_node_name_set_type &items)
+        const;
 
-    /// \brief Get the value of per Rcode counter in the Auth Counters.
+    /// \brief Dump the values of counters.
     ///
-    /// This function calls AuthCounters::getCounter(isc::dns::Rcode) and
-    /// returns its return value.
+    /// This function returns names and values of counter.
     ///
-    /// \note This is a tentative interface as an attempt of experimentally
-    /// supporting more statistics counters.  This should eventually be more
-    /// generalized.  In any case, this method is mainly for testing.
+    /// \throw bad_alloc
     ///
-    /// \throw None
-    /// \param rcode The rcode of the counter to get the value of
-    /// \return the value of the counter.
-    uint64_t getCounter(const isc::dns::Rcode rcode) const;
+    /// \return a tree of statistics items.
+    const isc::auth::statistics::Counters::item_tree_type dump() const;
 
     /**
      * \brief Set and get the addresses we listen on.
diff --git a/src/bin/auth/b10-auth.xml b/src/bin/auth/b10-auth.xml
index 37843e3..39e5483 100644
--- a/src/bin/auth/b10-auth.xml
+++ b/src/bin/auth/b10-auth.xml
@@ -143,15 +143,6 @@
       on the IPv6 (::) and IPv4 (0.0.0.0) wildcard addresses.
     </para>
 
-    <para>
-      <varname>statistics-interval</varname> is the timer interval
-      in seconds for <command>b10-auth</command> to share its
-      statistics information to
-      <citerefentry><refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
-      Statistics updates can be disabled by setting this to 0.
-      The default is 60.
-    </para>
-
 <!-- TODO: formating -->
     <para>
       The configuration commands are:
@@ -174,10 +165,8 @@
     </para>
 
     <para>
-      <command>sendstats</command> tells <command>b10-auth</command>
-      to send its statistics data to
-      <citerefentry><refentrytitle>b10-stats</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-      immediately.
+      <command>getstats</command> tells <command>b10-auth</command>
+      to return its statistics data.
     </para>
 
     <para>
@@ -201,14 +190,14 @@
     <variablelist>
 
       <varlistentry>
-        <term>queries.tcp</term>
+        <term>auth.server.qr.queries.tcp</term>
         <listitem><simpara>Total count of queries received by the
           <command>b10-auth</command> server over TCP since startup.
         </simpara></listitem>
       </varlistentry>
 
       <varlistentry>
-        <term>queries.udp</term>
+        <term>auth.server.qr.queries.udp</term>
         <listitem><simpara>Total count of queries received by the
           <command>b10-auth</command> server over UDP since startup.
         </simpara></listitem>
@@ -216,7 +205,7 @@
 
     </variablelist>
 
-<!-- TODO: missing stats docs. See ticket #1721 -->
+<!-- TODO: missing stats docs. See wiki:StatisticsItems -->
 
   </refsect1>
 
diff --git a/src/bin/auth/command.cc b/src/bin/auth/command.cc
index bc9027d..b1fc034 100644
--- a/src/bin/auth/command.cc
+++ b/src/bin/auth/command.cc
@@ -137,7 +137,9 @@ class GetStatsCommand : public AuthCommand {
 public:
     virtual ConstElementPtr exec(AuthSrv& server, isc::data::ConstElementPtr) {
         LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_RECEIVED_GETSTATS);
-        return (createAnswer(0, server.getStatistics()));
+        statistics::Counters::item_node_name_set_type trees;
+        trees.insert("auth.server.qr");
+        return (createAnswer(0, server.get(trees)));
     }
 };
 
diff --git a/src/bin/auth/statistics.cc b/src/bin/auth/statistics.cc
index aaa4b4f..dc4692f 100644
--- a/src/bin/auth/statistics.cc
+++ b/src/bin/auth/statistics.cc
@@ -13,9 +13,11 @@
 // PERFORMANCE OF THIS SOFTWARE.
 
 #include <auth/statistics.h>
+#include <auth/statistics_items.h>
 #include <auth/auth_log.h>
 
 #include <dns/opcode.h>
+#include <dns/rcode.h>
 
 #include <cc/data.h>
 #include <cc/session.h>
@@ -31,182 +33,391 @@
 #include <iostream>
 
 #include <boost/noncopyable.hpp>
+#include <boost/foreach.hpp>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
 
 using namespace isc::dns;
 using namespace isc::auth;
 using namespace isc::statistics;
 
-// TODO: We need a namespace ("auth_server"?) to hold
-// AuthSrv and AuthCounters.
+namespace {
+using namespace isc::data;
+using isc::statistics::Counter;
+using isc::auth::statistics::Counters;
+void
+fillNodes(const Counter &counter, const char *nodename[], const size_t size,
+          const std::string &prefix, Counters::item_tree_type &trees)
+{
+    for (size_t i = 0; i < size; ++i) {
+        trees->set (prefix + nodename[i],
+                    Element::create( static_cast<long int>( counter.get(i) ) )
+                    );
+    }
+}
+} // anonymous namespace
 
-// TODO: Make use of wrappers like isc::dns::Opcode
-// for counter item type.
+namespace isc {
+namespace auth {
+namespace statistics {
 
-class AuthCountersImpl : boost::noncopyable {
+class CountersImpl : boost::noncopyable {
 public:
-    AuthCountersImpl();
-    ~AuthCountersImpl();
-    void inc(const AuthCounters::ServerCounterType type);
-    void inc(const Opcode opcode) {
-        opcode_counter_.inc(opcode.getCode());
-    }
-    void inc(const Rcode rcode) {
-        rcode_counter_.inc(rcode.getCode());
-    }
-    void inc(const std::string& zone,
-             const AuthCounters::PerZoneCounterType type);
-    isc::data::ElementPtr getStatistics() const;
-    void registerStatisticsValidator
-    (AuthCounters::validator_type validator);
+    CountersImpl();
+    ~CountersImpl();
+    void inc(const QRAttributes& qrattrs, const Message& response);
+    const Counters::item_tree_type
+        get(const Counters::item_node_name_set_type& trees) const;
+    // Currently for testing purpose only
+    const Counters::item_tree_type dump() const;
+    bool submitStatistics() const;
+    void registerStatisticsValidator (Counters::validator_type validator);
     // Currently for testing purpose only
-    uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
-    uint64_t getCounter(const Opcode opcode) const {
-        return (opcode_counter_.get(opcode.getCode()));
-    }
-    uint64_t getCounter(const Rcode rcode) const {
-        return (rcode_counter_.get(rcode.getCode()));
-    }
 private:
-    Counter server_counter_;
-    Counter opcode_counter_;
-    static const size_t NUM_OPCODES = 16;
-    Counter rcode_counter_;
-    static const size_t NUM_RCODES = 17;
-    CounterDictionary per_zone_counter_;
-    AuthCounters::validator_type validator_;
+    // counter for server
+    Counter server_qr_counter_;
+    Counter server_socket_counter_;
+    // set of counters for zones
+    CounterDictionary zone_qr_counters_;
+    // validator
+    Counters::validator_type validator_;
 };
 
-AuthCountersImpl::AuthCountersImpl() :
+CountersImpl::CountersImpl() :
     // initialize counter
-    // size of server_counter_: AuthCounters::SERVER_COUNTER_TYPES
-    // size of per_zone_counter_: AuthCounters::PER_ZONE_COUNTER_TYPES
-    server_counter_(AuthCounters::SERVER_COUNTER_TYPES),
-    opcode_counter_(NUM_OPCODES), rcode_counter_(NUM_RCODES),
-    per_zone_counter_(AuthCounters::PER_ZONE_COUNTER_TYPES)
-{
-    per_zone_counter_.addElement("_SERVER_");
-}
+    // size of server_qr_counter_, zone_qr_counters_: QR_COUNTER_TYPES
+    // size of server_socket_counter_: SOCKET_COUNTER_TYPES
+    server_qr_counter_(QR_COUNTER_TYPES),
+    server_socket_counter_(SOCKET_COUNTER_TYPES),
+    zone_qr_counters_(QR_COUNTER_TYPES),
+    validator_()
+{}
 
-AuthCountersImpl::~AuthCountersImpl()
+CountersImpl::~CountersImpl()
 {}
 
 void
-AuthCountersImpl::inc(const AuthCounters::ServerCounterType type) {
-    server_counter_.inc(type);
-}
+CountersImpl::inc(const QRAttributes& qrattrs, const Message& response) {
+    // protocols carrying request
+    if (qrattrs.req_ip_version_ == AF_INET) {
+        server_qr_counter_.inc(QR_REQUEST_IPV4);
+    } else if (qrattrs.req_ip_version_ == AF_INET6) {
+        server_qr_counter_.inc(QR_REQUEST_IPV6);
+    }
+    if (qrattrs.req_transport_protocol_ == IPPROTO_UDP) {
+        server_qr_counter_.inc(QR_REQUEST_UDP);
+    } else if (qrattrs.req_transport_protocol_ == IPPROTO_TCP) {
+        server_qr_counter_.inc(QR_REQUEST_TCP);
+    }
 
-void
-AuthCountersImpl::inc(const std::string& zone,
-                      const AuthCounters::PerZoneCounterType type)
-{
-    per_zone_counter_[zone].inc(type);
-}
-
-isc::data::ElementPtr
-AuthCountersImpl::getStatistics() const {
-    std::stringstream statistics_string;
-    statistics_string 
-                      <<     "{ \"queries.udp\": "
-                      <<     server_counter_.get(AuthCounters::SERVER_UDP_QUERY)
-                      <<     ", \"queries.tcp\": "
-                      <<     server_counter_.get(
-                          AuthCounters::SERVER_TCP_QUERY);
-    // Insert non 0 Opcode counters.
-    for (int i = 0; i < NUM_OPCODES; ++i) {
-        const Counter::Type counter = opcode_counter_.get(i);
-        if (counter != 0) {
-            // The counter item name should be derived lower-cased textual
-            // representation of the code.
-            std::string opcode_txt = Opcode(i).toText();
-            std::transform(opcode_txt.begin(), opcode_txt.end(),
-                           opcode_txt.begin(), ::tolower);
-            statistics_string << ", \"opcode." << opcode_txt << "\": "
-                              << counter;
-        }
+    // query TSIG
+    if (qrattrs.req_is_tsig_) {
+        server_qr_counter_.inc(QR_REQUEST_TSIG);
+    }
+    if (qrattrs.req_is_sig0_) {
+        server_qr_counter_.inc(QR_REQUEST_SIG0);
     }
-    // Insert non 0 Rcode counters.
-    for (int i = 0; i < NUM_RCODES; ++i) {
-        const Counter::Type counter = rcode_counter_.get(i);
-        if (counter != 0) {
-            // The counter item name should be derived lower-cased textual
-            // representation of the code.
-            std::string rcode_txt = Rcode(i).toText();
-            std::transform(rcode_txt.begin(), rcode_txt.end(),
-                           rcode_txt.begin(), ::tolower);
-            statistics_string << ", \"rcode." << rcode_txt << "\": "
-                              << counter;
+    if (qrattrs.req_is_badsig_) {
+        server_qr_counter_.inc(QR_REQUEST_BADSIG);
+    }
+
+    // query EDNS
+    if (qrattrs.req_is_edns_0_) {
+        server_qr_counter_.inc(QR_REQUEST_EDNS0);
+    }
+    if (qrattrs.req_is_edns_badver_) {
+        server_qr_counter_.inc(QR_REQUEST_BADEDNSVER);
+    }
+
+    // query DNSSEC
+    if (qrattrs.req_is_dnssec_ok_) {
+        server_qr_counter_.inc(QR_REQUEST_DNSSEC_OK);
+    }
+
+    // QTYPE
+    unsigned int qtype_type = QR_QTYPE_OTHER;
+    const QuestionIterator qiter = response.beginQuestion();
+    if (qiter != response.endQuestion()) {
+        // get the first and only question section
+        const QuestionPtr qptr = *qiter;
+        if (qptr != NULL) {
+            // get the qtype code
+            const unsigned int qtype = qptr->getType().getCode();
+            if (qtype == 0) {
+                // qtype 0
+                qtype_type = QR_QTYPE_OTHER;
+            } else if (qtype < 52) {
+                // qtype 1..51
+                qtype_type = QR_QTYPE_A + (qtype - 1);
+            } else if (qtype < 55) {
+                // qtype 52..54
+                qtype_type = QR_QTYPE_OTHER;
+            } else if (qtype < 59) {
+                // qtype 55..58
+                qtype_type = QR_QTYPE_HIP + (qtype - 55);
+            } else if (qtype < 99) {
+                // qtype 59..98
+                qtype_type = QR_QTYPE_OTHER;
+            } else if (qtype < 104) {
+                // qtype 99..103
+                qtype_type = QR_QTYPE_SPF + (qtype - 99);
+            } else if (qtype < 249) {
+                // qtype 104..248
+                qtype_type = QR_QTYPE_OTHER;
+            } else if (qtype < 255) {
+                // qtype 249..254
+                qtype_type = QR_QTYPE_TKEY + (qtype - 249);
+            } else if (qtype == 255) {
+                // qtype 255: all records
+                qtype_type = QR_QTYPE_OTHER;
+            } else if (qtype < 258) {
+                // qtype 256..257
+                qtype_type = QR_QTYPE_URI + (qtype - 256);
+            } else if (qtype < 32768) {
+                // qtype 258..32767
+                qtype_type = QR_QTYPE_OTHER;
+            } else if (qtype < 32770) {
+                // qtype 32768..32769
+                qtype_type = QR_QTYPE_TA + (qtype - 32768);
+            } else {
+                // qtype 32770..65535
+                qtype_type = QR_QTYPE_OTHER;
+            }
         }
     }
-    statistics_string <<   "}";
-
-    isc::data::ElementPtr statistics_element =
-        isc::data::Element::fromJSON(statistics_string);
-    // validate the statistics data before send
-    if (validator_) {
-        if (!validator_(statistics_element)) {
-            LOG_ERROR(auth_logger, AUTH_INVALID_STATISTICS_DATA);
-            return (isc::data::ElementPtr());
+    server_qr_counter_.inc(qtype_type);
+    // OPCODE
+    unsigned int opcode_type = QR_OPCODE_OTHER;
+    if (qrattrs.req_opcode_ < 3) {
+        // opcode 0..2
+        opcode_type = QR_OPCODE_QUERY + qrattrs.req_opcode_;
+    } else if (qrattrs.req_opcode_ == 3) {
+        // opcode 3 is reserved
+        opcode_type = QR_OPCODE_OTHER;
+    } else if (qrattrs.req_opcode_ < 6) {
+        // opcode 4..5
+        opcode_type = QR_OPCODE_NOTIFY + (qrattrs.req_opcode_ - 4);
+    } else {
+        // opcode larger than 6 is reserved
+        opcode_type = QR_OPCODE_OTHER;
+    }
+    server_qr_counter_.inc(opcode_type);
+
+    // response
+    if (qrattrs.answer_sent_) {
+        // responded
+        server_qr_counter_.inc(QR_RESPONSE);
+
+        // response truncated
+        if (qrattrs.res_is_truncated_) {
+            server_qr_counter_.inc(QR_RESPONSE_TRUNCATED);
+        }
+
+        // response EDNS
+        ConstEDNSPtr response_edns = response.getEDNS();
+        if (response_edns != NULL && response_edns->getVersion() == 0) {
+            server_qr_counter_.inc(QR_RESPONSE_EDNS0);
+        }
+
+        // response TSIG
+        if (qrattrs.req_is_tsig_) {
+            // assume response is TSIG signed if request is TSIG signed
+            server_qr_counter_.inc(QR_RESPONSE_TSIG);
+        }
+
+        // response SIG(0) is currently not implemented
+
+        // RCODE
+        const unsigned int rcode = response.getRcode().getCode();
+        unsigned int rcode_type = QR_RCODE_OTHER;
+        if (rcode < 11) {
+            // rcode 0..10
+            rcode_type = QR_RCODE_NOERROR + rcode;
+        } else if (rcode < 16) {
+            // rcode 11..15 is reserved
+            rcode_type = QR_RCODE_OTHER;
+        } else if (rcode == 16) {
+            // rcode 16
+            rcode_type = QR_RCODE_BADSIGVERS;
+        } else if (rcode < 23) {
+            // rcode 17..22
+            rcode_type = QR_RCODE_BADKEY + (rcode - 17);
+        } else {
+            // opcode larger than 22 is reserved or unassigned
+            rcode_type = QR_RCODE_OTHER;
+        }
+        server_qr_counter_.inc(rcode_type);
+
+        // compound attributes
+        const unsigned int answer_rrs =
+            response.getRRCount(Message::SECTION_ANSWER);
+        const bool is_aa_set = response.getHeaderFlag(Message::HEADERFLAG_AA);
+
+        if (is_aa_set) {
+            // QryAuthAns
+            server_qr_counter_.inc(QR_QRYAUTHANS);
+        } else {
+            // QryNoAuthAns
+            server_qr_counter_.inc(QR_QRYNOAUTHANS);
+        }
+
+        if (rcode == Rcode::NOERROR_CODE) {
+            if (answer_rrs > 0) {
+                // QrySuccess
+                server_qr_counter_.inc(QR_QRYSUCCESS);
+            } else {
+                if (is_aa_set) {
+                    // QryNxrrset
+                    server_qr_counter_.inc(QR_QRYNXRRSET);
+                } else {
+                    // QryReferral
+                    server_qr_counter_.inc(QR_QRYREFERRAL);
+                }
+            }
         }
     }
-    return (statistics_element);
 }
 
+
 void
-AuthCountersImpl::registerStatisticsValidator
-    (AuthCounters::validator_type validator)
+CountersImpl::registerStatisticsValidator
+    (Counters::validator_type validator)
 {
     validator_ = validator;
 }
 
+const Counters::item_tree_type
+CountersImpl::get(const Counters::item_node_name_set_type &trees) const {
+    using namespace isc::data;
+
+    Counters::item_tree_type item_tree = Element::createMap();
+
+    BOOST_FOREACH(const Counters::item_node_name_type& node, trees) {
+        if (node == "auth.server.qr") {
+            fillNodes(server_qr_counter_, QRCounterItemName, QR_COUNTER_TYPES,
+                      "auth.server.qr.", item_tree);
+        } else if (node == "auth.server.socket") {
+            // currently not implemented
+            fillNodes(server_socket_counter_, SocketCounterItemName,
+                      SOCKET_COUNTER_TYPES, "auth.server.socket.", item_tree);
+        } else if (node == "auth.zones") {
+            // currently not implemented
+        } else {
+            // unknown tree
+        }
+    }
+
+    return (item_tree);
+}
+
 // Currently for testing purpose only
-uint64_t
-AuthCountersImpl::getCounter(const AuthCounters::ServerCounterType type) const {
-    return (server_counter_.get(type));
+const Counters::item_tree_type
+CountersImpl::dump() const {
+    using namespace isc::data;
+
+    Counters::item_tree_type item_tree = Element::createMap();
+
+    fillNodes(server_qr_counter_, QRCounterItemName, QR_COUNTER_TYPES,
+              "auth.server.qr.", item_tree);
+
+    return (item_tree);
 }
 
-AuthCounters::AuthCounters() : impl_(new AuthCountersImpl())
+Counters::Counters() : impl_(new CountersImpl())
 {}
 
-AuthCounters::~AuthCounters() {}
+Counters::~Counters() {}
 
 void
-AuthCounters::inc(const AuthCounters::ServerCounterType type) {
-    impl_->inc(type);
+Counters::inc(const QRAttributes& qrattrs, const Message& response) {
+    impl_->inc(qrattrs, response);
+}
+
+const Counters::item_tree_type
+Counters::get(const Counters::item_node_name_set_type &trees) const {
+    return (impl_->get(trees));
+}
+
+const Counters::item_tree_type
+Counters::dump() const {
+    return (impl_->dump());
 }
 
 void
-AuthCounters::inc(const Opcode opcode) {
-    impl_->inc(opcode);
+Counters::registerStatisticsValidator
+    (Counters::validator_type validator) const
+{
+    return (impl_->registerStatisticsValidator(validator));
 }
 
+QRAttributes::QRAttributes() :
+    req_ip_version_(0), req_transport_protocol_(0),
+    req_opcode_(0),
+    req_is_edns_0_(false), req_is_edns_badver_(false),
+    req_is_dnssec_ok_(false),
+    req_is_tsig_(false), req_is_sig0_(false), req_is_badsig_(false),
+    zone_origin_(),
+    answer_sent_(false),
+    res_is_truncated_(false)
+{}
+
+QRAttributes::~QRAttributes()
+{}
+
 void
-AuthCounters::inc(const Rcode rcode) {
-    impl_->inc(rcode);
+QRAttributes::setQueryIPVersion(const int ip_version) {
+    req_ip_version_ = ip_version;
 }
 
-isc::data::ElementPtr
-AuthCounters::getStatistics() const {
-    return (impl_->getStatistics());
+void
+QRAttributes::setQueryTransportProtocol(const int transport_protocol) {
+    req_transport_protocol_ = transport_protocol;
 }
 
-uint64_t
-AuthCounters::getCounter(const AuthCounters::ServerCounterType type) const {
-    return (impl_->getCounter(type));
+void
+QRAttributes::setQueryOpCode(const int opcode) {
+    req_opcode_ = opcode;
 }
 
-uint64_t
-AuthCounters::getCounter(const Opcode opcode) const {
-    return (impl_->getCounter(opcode));
+void
+QRAttributes::setQueryEDNS(const bool is_edns_0, const bool is_edns_badver) {
+    req_is_edns_0_ = is_edns_0;
+    req_is_edns_badver_ = is_edns_badver;
 }
 
-uint64_t
-AuthCounters::getCounter(const Rcode rcode) const {
-    return (impl_->getCounter(rcode));
+void
+QRAttributes::setQueryDO(const bool is_dnssec_ok) {
+    req_is_dnssec_ok_ = is_dnssec_ok;
 }
 
 void
-AuthCounters::registerStatisticsValidator
-    (AuthCounters::validator_type validator) const
+QRAttributes::setQuerySig(const bool is_tsig, const bool is_sig0,
+                          const bool is_badsig)
 {
-    return (impl_->registerStatisticsValidator(validator));
+    req_is_tsig_ = is_tsig;
+    req_is_sig0_ = is_sig0;
+    req_is_badsig_ = is_badsig;
 }
+
+void
+QRAttributes::setOrigin(const std::string& origin) {
+    zone_origin_ = origin;
+}
+
+void
+QRAttributes::answerHasSent() {
+    answer_sent_ = true;
+}
+
+void
+QRAttributes::setResponseTruncated(const bool is_truncated) {
+    res_is_truncated_ = is_truncated;
+}
+
+} // namespace statistics
+} // namespace auth
+} // namespace isc
diff --git a/src/bin/auth/statistics.h b/src/bin/auth/statistics.h
index 4b0eae2..cb996e1 100644
--- a/src/bin/auth/statistics.h
+++ b/src/bin/auth/statistics.h
@@ -15,19 +15,92 @@
 #ifndef __STATISTICS_H
 #define __STATISTICS_H 1
 
-#include <dns/opcode.h>
-#include <dns/rcode.h>
 #include <cc/session.h>
-#include <cc/data.h>
+
+#include <dns/message.h>
+
+#include <string>
+#include <set>
 
 #include <stdint.h>
 #include <boost/scoped_ptr.hpp>
 
-class AuthCountersImpl;
+namespace isc {
+namespace auth {
+namespace statistics {
+
+class CountersImpl;
+
+class QRAttributes {
+/// \brief Query/Response attributes for statistics.
+///
+/// This class holds some attributes related to a query/response
+/// for statistics data collection.
+///
+/// This class does not have getter methods since it exposes private members
+/// to \c CountersImpl directly.
+friend class CountersImpl;
+private:
+    // request attributes
+    int req_ip_version_;            // IP version
+    int req_transport_protocol_;    // Transport layer protocol
+    int req_opcode_;                // OpCode
+    bool req_is_edns_0_;            // EDNS ver.0
+    bool req_is_edns_badver_;       // other EDNS version
+    bool req_is_dnssec_ok_;         // DO bit
+    bool req_is_tsig_;              // signed with valid TSIG
+    bool req_is_sig0_;              // signed with valid SIG(0)
+    bool req_is_badsig_;            // signed but bad signature
+    // zone origin
+    std::string zone_origin_;       // zone origin
+    // response attributes
+    bool answer_sent_;              // DNS message has sent
+    bool res_is_truncated_;         // DNS message is truncated
+public:
+    /// The constructor.
+    ///
+    /// This constructor is mostly exception free. But it may still throw
+    /// a standard exception if memory allocation fails inside the method.
+    ///
+    QRAttributes();
+    /// The destructor.
+    ///
+    /// This method never throws an exception.
+    ///
+    ~QRAttributes();
+    /// \brief Set query opcode.
+    /// \throw None
+    void setQueryOpCode(const int opcode);
+    /// \brief Set IP version carrying a query.
+    /// \throw None
+    void setQueryIPVersion(const int ip_version);
+    /// \brief Set transport protocol carrying a query.
+    /// \throw None
+    void setQueryTransportProtocol(const int transport_protocol);
+    /// \brief Set query EDNS attributes.
+    /// \throw None
+    void setQueryEDNS(const bool is_edns_0, const bool is_edns_badver);
+    /// \brief Set query DO bit.
+    /// \throw None
+    void setQueryDO(const bool is_dnssec_ok);
+    /// \brief Set query TSIG attributes.
+    /// \throw None
+    void setQuerySig(const bool is_tsig, const bool is_sig0,
+                     const bool is_badsig);
+    /// \brief Set zone origin.
+    /// \throw None
+    void setOrigin(const std::string& origin);
+    /// \brief Set if the answer has sent.
+    /// \throw None
+    void answerHasSent();
+    /// \brief Set if the response is truncated.
+    /// \throw None
+    void setResponseTruncated(const bool is_truncated);
+};
 
 /// \brief Set of query counters.
 ///
-/// \c AuthCounters is set of query counters class. It holds query counters
+/// \c Counters is set of query counters class. It holds query counters
 /// and provides an interface to increment the counter of specified type
 /// (e.g. UDP query, TCP query).
 ///
@@ -35,11 +108,9 @@ class AuthCountersImpl;
 /// statistics module.
 ///
 /// This class is designed to be a part of \c AuthSrv.
-/// Call \c inc() to increment a counter for specific type of query in
-/// the query processing function. use \c enum \c CounterType to specify
-/// the type of query.
-/// Call \c getStatistics() to answer statistics information to statistics
-/// module with statistics_session, when the command \c getstats is received.
+/// Call \c inc() to increment a counter for the query.
+/// Call \c get() to get statistics information to send to statistics module
+/// when the command \c getstats is received.
 ///
 /// We may eventually want to change the structure to hold values that are
 /// not counters (such as concurrent TCP connections), or seperate generic
@@ -50,134 +121,90 @@ class AuthCountersImpl;
 /// construction overhead of this approach should be acceptable.
 ///
 /// \todo Hold counters for each query types (Notify, Axfr, Ixfr, Normal)
-/// \todo Consider overhead of \c AuthCounters::inc()
-class AuthCounters {
+/// \todo Consider overhead of \c Counters::inc()
+class Counters {
 private:
-    boost::scoped_ptr<AuthCountersImpl> impl_;
+    boost::scoped_ptr<CountersImpl> impl_;
 public:
-    // Enum for the type of counter
-    enum ServerCounterType {
-        SERVER_UDP_QUERY,       ///< SERVER_UDP_QUERY: counter for UDP queries
-        SERVER_TCP_QUERY,       ///< SERVER_TCP_QUERY: counter for TCP queries
-        SERVER_COUNTER_TYPES    ///< The number of defined counters
-    };
-    enum PerZoneCounterType {
-        ZONE_UDP_QUERY,         ///< ZONE_UDP_QUERY: counter for UDP queries
-        ZONE_TCP_QUERY,         ///< ZONE_TCP_QUERY: counter for TCP queries
-        PER_ZONE_COUNTER_TYPES  ///< The number of defined counters
-    };
     /// The constructor.
     ///
     /// This constructor is mostly exception free. But it may still throw
     /// a standard exception if memory allocation fails inside the method.
     ///
-    AuthCounters();
+    Counters();
     /// The destructor.
     ///
     /// This method never throws an exception.
     ///
-    ~AuthCounters();
-
-    /// \brief Increment the counter specified by the parameter.
-    ///
-    /// \param type Type of a counter to increment.
-    ///
-    /// \throw std::out_of_range \a type is unknown.
-    ///
-    /// usage: counter.inc(AuthCounters::SERVER_UDP_QUERY);
-    /// 
-    void inc(const ServerCounterType type);
+    ~Counters();
 
-    /// \brief Increment the counter of a per opcode counter.
-    ///
-    /// \note This is a tentative interface.  See \c getCounter().
+    /// \brief Increment counters according to the parameters.
     ///
-    /// \param opcode The opcode of the counter to increment.
+    /// \param qrattrs Query/Response attributes.
+    /// \param response DNS response message.
     ///
     /// \throw None
-    void inc(const isc::dns::Opcode opcode);
-
-    /// \brief Increment the counter of a per rcode counter.
     ///
-    /// \note This is a tentative interface.  See \c getCounter().
-    ///
-    /// \param rcode The rcode of the counter to increment.
-    ///
-    /// \throw None
-    void inc(const isc::dns::Rcode rcode);
+    void inc(const QRAttributes& qrattrs, const isc::dns::Message& response);
 
-    /// \brief Answers statistics counters to statistics module.
+    /// \brief item node name
     ///
-    /// This method is mostly exception free (error conditions are
-    /// represented via the return value). But it may still throw
-    /// a standard exception if memory allocation fails inside the method.
-    ///
-    /// \return statistics data
-    ///
-    isc::data::ElementPtr getStatistics() const;
+    typedef std::string item_node_name_type;
 
-    /// \brief Get the value of a counter in the AuthCounters.
-    ///
-    /// This function returns a value of the counter specified by \a type.
-    /// This method never throws an exception.
-    ///
-    /// Note: Currently this function is for testing purpose only.
+    /// \brief item node set
     ///
-    /// \param type Type of a counter to get the value of
-    ///
-    /// \return the value of the counter specified by \a type.
-    uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
+    typedef std::set<item_node_name_type> item_node_name_set_type;
+
+    /// \brief A type of statistics item tree in isc::data::MapElement.
+    ///        { item_name => item_value, item_name => item_value, ... }
+    ///        item_name is a string seperated by '.'.
+    ///        item_value is an integer.
+    typedef isc::data::ElementPtr item_tree_type;
 
-    /// \brief Get the value of a per opcode counter.
+    /// \brief Get the values of specified counters.
     ///
-    /// This method returns the value of the per opcode counter for the
-    /// specified \c opcode.
+    /// This function returns names and values of counter.
     ///
-    /// \note This is a tentative interface as an attempt of experimentally
-    /// supporting more statistics counters.  This should eventually be more
-    /// generalized.  In any case, this method is mainly for testing.
+    /// \throw bad_alloc
     ///
-    /// \throw None
-    /// \param opcode The opcode of the counter to get the value of
-    /// \return the value of the counter.
-    uint64_t getCounter(const isc::dns::Opcode opcode) const;
+    /// \return a tree of statistics items.
+    const item_tree_type get(const item_node_name_set_type &items) const;
 
-    /// \brief Get the value of a per rcode counter.
+    /// \brief Dump all of the counters.
     ///
-    /// This method returns the value of the per rcode counter for the
-    /// specified \c rcode.
+    /// This function returns names and values of counter.
     ///
-    /// \note As mentioned in getCounter(const isc::dns::Opcode opcode),
-    /// This is a tentative interface as an attempt of experimentally
-    /// supporting more statistics counters.  This should eventually be more
-    /// generalized.  In any case, this method is mainly for testing.
+    /// \throw bad_alloc
     ///
-    /// \throw None
-    /// \param rcode The rcode of the counter to get the value of
-    /// \return the value of the counter.
-    uint64_t getCounter(const isc::dns::Rcode rcode) const;
+    /// \return a tree of statistics items.
+    const item_tree_type dump() const;
 
     /// \brief A type of validation function for the specification in
     /// isc::config::ModuleSpec.
     ///
     /// This type might be useful for not only statistics
     /// specificatoin but also for config_data specification and for
-    /// commnad.
+    /// command.
     ///
     typedef boost::function<bool(const isc::data::ConstElementPtr&)>
     validator_type;
 
     /// \brief Register a function type of the statistics validation
-    /// function for AuthCounters.
+    /// function for Counters.
     ///
     /// This method never throws an exception.
     ///
     /// \param validator A function type of the validation of
     /// statistics specification.
     ///
-    void registerStatisticsValidator(AuthCounters::validator_type validator) const;
+    void registerStatisticsValidator(Counters::validator_type validator) const;
 };
 
+} // namespace statistics
+} // namespace auth
+} // namespace isc
+
+
 #endif // __STATISTICS_H
 
 // Local Variables:
diff --git a/src/bin/auth/statistics_items.h b/src/bin/auth/statistics_items.h
new file mode 100644
index 0000000..46bce64
--- /dev/null
+++ b/src/bin/auth/statistics_items.h
@@ -0,0 +1,376 @@
+// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __STATISTICS_ITEMS_H
+#define __STATISTICS_ITEMS_H 1
+
+/// This file defines a set of statistics items in Auth module for internal
+/// use. This file is intended to be included in statistics.cc.
+
+namespace {
+
+// enum for socket statistics
+enum SocketCounterType {
+    // Socket statistics
+    SOCKET_IPV4_UDP_BINDFAIL,        ///< IPv4 UDP sockets bind failures
+    SOCKET_IPV4_UDP_CLOSE,           ///< IPv4 UDP sockets closed
+    SOCKET_IPV4_UDP_CONN,            ///< IPv4 UDP connections established successfully
+    SOCKET_IPV4_UDP_CONNFAIL,        ///< IPv4 UDP sockets connection failures
+    SOCKET_IPV4_UDP_OPEN,            ///< IPv4 UDP sockets opened successfully
+    SOCKET_IPV4_UDP_OPENFAIL,        ///< IPv4 UDP sockets open failures
+    SOCKET_IPV4_UDP_RECVERR,         ///< IPv4 UDP sockets receive errors
+    SOCKET_IPV4_UDP_SENDERR,         ///< IPv4 UDP sockets send errors
+    SOCKET_IPV4_TCP_ACCEPT,          ///< IPv4 TCP incoming connections successfully accepted
+    SOCKET_IPV4_TCP_ACCEPTFAIL,      ///< IPv4 TCP incoming accept failures
+    SOCKET_IPV4_TCP_BINDFAIL,        ///< IPv4 TCP sockets bind failures
+    SOCKET_IPV4_TCP_CLOSE,           ///< IPv4 TCP sockets closed
+    SOCKET_IPV4_TCP_CONN,            ///< IPv4 TCP connections established successfully
+    SOCKET_IPV4_TCP_CONNFAIL,        ///< IPv4 TCP sockets connection failures
+    SOCKET_IPV4_TCP_OPEN,            ///< IPv4 TCP sockets opened successfully
+    SOCKET_IPV4_TCP_OPENFAIL,        ///< IPv4 TCP sockets open failures
+    SOCKET_IPV4_TCP_RECVERR,         ///< IPv4 TCP sockets receive errors
+    SOCKET_IPV4_TCP_SENDERR,         ///< IPv4 TCP sockets send errors
+    SOCKET_IPV6_UDP_BINDFAIL,        ///< IPv6 UDP sockets bind failures
+    SOCKET_IPV6_UDP_CLOSE,           ///< IPv6 UDP sockets closed
+    SOCKET_IPV6_UDP_CONN,            ///< IPv6 UDP connections established successfully
+    SOCKET_IPV6_UDP_CONNFAIL,        ///< IPv6 UDP sockets connection failures
+    SOCKET_IPV6_UDP_OPEN,            ///< IPv6 UDP sockets opened successfully
+    SOCKET_IPV6_UDP_OPENFAIL,        ///< IPv6 UDP sockets open failures
+    SOCKET_IPV6_UDP_RECVERR,         ///< IPv6 UDP sockets receive errors
+    SOCKET_IPV6_UDP_SENDERR,         ///< IPv6 UDP sockets send errors
+    SOCKET_IPV6_TCP_ACCEPT,          ///< IPv6 TCP incoming connections successfully accepted
+    SOCKET_IPV6_TCP_ACCEPTFAIL,      ///< IPv6 TCP incoming accept failures
+    SOCKET_IPV6_TCP_BINDFAIL,        ///< IPv6 TCP sockets bind failures
+    SOCKET_IPV6_TCP_CLOSE,           ///< IPv6 TCP sockets closed
+    SOCKET_IPV6_TCP_CONN,            ///< IPv6 TCP connections established successfully
+    SOCKET_IPV6_TCP_CONNFAIL,        ///< IPv6 TCP sockets connection failures
+    SOCKET_IPV6_TCP_OPEN,            ///< IPv6 TCP sockets opened successfully
+    SOCKET_IPV6_TCP_OPENFAIL,        ///< IPv6 TCP sockets open failures
+    SOCKET_IPV6_TCP_RECVERR,         ///< IPv6 TCP sockets receive errors
+    SOCKET_IPV6_TCP_SENDERR,         ///< IPv6 TCP sockets send errors
+    SOCKET_UNIXDOMAIN_ACCEPT,        ///< Unix Domain sockets incoming connections successfully accepted
+    SOCKET_UNIXDOMAIN_ACCEPTFAIL,    ///< Unix Domain sockets incoming accept failures
+    SOCKET_UNIXDOMAIN_BINDFAIL,      ///< Unix Domain sockets bind failures
+    SOCKET_UNIXDOMAIN_CLOSE,         ///< Unix Domain sockets closed
+    SOCKET_UNIXDOMAIN_CONN,          ///< Unix Domain connections established successfully
+    SOCKET_UNIXDOMAIN_CONNFAIL,      ///< Unix Domain sockets connection failures
+    SOCKET_UNIXDOMAIN_OPEN,          ///< Unix Domain sockets opened successfully
+    SOCKET_UNIXDOMAIN_OPENFAIL,      ///< Unix Domain sockets open failures
+    SOCKET_UNIXDOMAIN_RECVERR,       ///< Unix Domain sockets receive errors
+    SOCKET_UNIXDOMAIN_SENDERR,       ///< Unix Domain sockets send errors
+    SOCKET_COUNTER_TYPES             ///< The number of defined counters
+};
+// item names for socket statistics
+const char *SocketCounterItemName[SOCKET_COUNTER_TYPES] = {
+    "ipv4.udp.bindfail",
+    "ipv4.udp.close",
+    "ipv4.udp.conn",
+    "ipv4.udp.connfail",
+    "ipv4.udp.open",
+    "ipv4.udp.openfail",
+    "ipv4.udp.recverr",
+    "ipv4.udp.senderr",
+    "ipv4.tcp.accept",
+    "ipv4.tcp.acceptfail",
+    "ipv4.tcp.bindfail",
+    "ipv4.tcp.close",
+    "ipv4.tcp.conn",
+    "ipv4.tcp.connfail",
+    "ipv4.tcp.open",
+    "ipv4.tcp.openfail",
+    "ipv4.tcp.recverr",
+    "ipv4.tcp.senderr",
+    "ipv6.udp.bindfail",
+    "ipv6.udp.close",
+    "ipv6.udp.conn",
+    "ipv6.udp.connfail",
+    "ipv6.udp.open",
+    "ipv6.udp.openfail",
+    "ipv6.udp.recverr",
+    "ipv6.udp.senderr",
+    "ipv6.tcp.accept",
+    "ipv6.tcp.acceptfail",
+    "ipv6.tcp.bindfail",
+    "ipv6.tcp.close",
+    "ipv6.tcp.conn",
+    "ipv6.tcp.connfail",
+    "ipv6.tcp.open",
+    "ipv6.tcp.openfail",
+    "ipv6.tcp.recverr",
+    "ipv6.tcp.senderr",
+    "unixdomain.accept",
+    "unixdomain.acceptfail",
+    "unixdomain.bindfail",
+    "unixdomain.close",
+    "unixdomain.conn",
+    "unixdomain.connfail",
+    "unixdomain.open",
+    "unixdomain.openfail",
+    "unixdomain.recverr",
+    "unixdomain.senderr"
+};
+
+// enum for query/response counters
+enum QRCounterType {
+    // Request Attributes
+    QR_REQUEST_IPV4,        ///< Number of IPv4 requests received
+    QR_REQUEST_IPV6,        ///< Number of IPv6 requests received
+    QR_REQUEST_EDNS0,       ///< Number of requests with EDNS(0) received
+    QR_REQUEST_BADEDNSVER,  ///< Number of requests with unsupported EDNS version received
+    QR_REQUEST_TSIG,        ///< Number of requests with TSIG received
+    QR_REQUEST_SIG0,        ///< Number of requests with SIG(0) received; not implemented in BIND 10
+    QR_REQUEST_BADSIG,      ///< Number of requests with invalid TSIG or SIG(0) signature received
+    QR_REQUEST_UDP,         ///< Number of UDP requests received
+    QR_REQUEST_TCP,         ///< Number of TCP requests received
+    QR_REQUEST_DNSSEC_OK,   ///< Number of requests with DO bit
+    // Request Opcodes
+    QR_OPCODE_QUERY,        ///< Number of Opcode=QUERY requests received
+    QR_OPCODE_IQUERY,       ///< Number of Opcode=IQUERY requests received
+    QR_OPCODE_STATUS,       ///< Number of Opcode=STATUS requests received
+    QR_OPCODE_NOTIFY,       ///< Number of Opcode=NOTIFY requests received
+    QR_OPCODE_UPDATE,       ///< Number of Opcode=UPDATE requests received
+    QR_OPCODE_OTHER,        ///< Number of requests in other OpCode received
+    // Query Types
+    QR_QTYPE_A,             ///< Number of QTYPE = A queries received
+    QR_QTYPE_NS,            ///< Number of QTYPE = NS queries received
+    QR_QTYPE_MD,            ///< Number of QTYPE = MD queries received
+    QR_QTYPE_MF,            ///< Number of QTYPE = MF queries received
+    QR_QTYPE_CNAME,         ///< Number of QTYPE = CNAME queries received
+    QR_QTYPE_SOA,           ///< Number of QTYPE = SOA queries received
+    QR_QTYPE_MB,            ///< Number of QTYPE = MB queries received
+    QR_QTYPE_MG,            ///< Number of QTYPE = MG queries received
+    QR_QTYPE_MR,            ///< Number of QTYPE = MR queries received
+    QR_QTYPE_NULL,          ///< Number of QTYPE = NULL queries received
+    QR_QTYPE_WKS,           ///< Number of QTYPE = WKS queries received
+    QR_QTYPE_PTR,           ///< Number of QTYPE = PTR queries received
+    QR_QTYPE_HINFO,         ///< Number of QTYPE = HINFO queries received
+    QR_QTYPE_MINFO,         ///< Number of QTYPE = MINFO queries received
+    QR_QTYPE_MX,            ///< Number of QTYPE = MX queries received
+    QR_QTYPE_TXT,           ///< Number of QTYPE = TXT queries received
+    QR_QTYPE_RP,            ///< Number of QTYPE = RP queries received
+    QR_QTYPE_AFSDB,         ///< Number of QTYPE = AFSDB queries received
+    QR_QTYPE_X25,           ///< Number of QTYPE = X25 queries received
+    QR_QTYPE_ISDN,          ///< Number of QTYPE = ISDN queries received
+    QR_QTYPE_RT,            ///< Number of QTYPE = RT queries received
+    QR_QTYPE_NSAP,          ///< Number of QTYPE = NSAP queries received
+    QR_QTYPE_NSAP_PTR,      ///< Number of QTYPE = NSAP-PTR queries received
+    QR_QTYPE_SIG,           ///< Number of QTYPE = SIG queries received
+    QR_QTYPE_KEY,           ///< Number of QTYPE = KEY queries received
+    QR_QTYPE_PX,            ///< Number of QTYPE = PX queries received
+    QR_QTYPE_GPOS,          ///< Number of QTYPE = GPOS queries received
+    QR_QTYPE_AAAA,          ///< Number of QTYPE = AAAA queries received
+    QR_QTYPE_LOC,           ///< Number of QTYPE = LOC queries received
+    QR_QTYPE_NXT,           ///< Number of QTYPE = NXT queries received
+    QR_QTYPE_EID,           ///< Number of QTYPE = EID queries received
+    QR_QTYPE_NIMLOC,        ///< Number of QTYPE = NIMLOC queries received
+    QR_QTYPE_SRV,           ///< Number of QTYPE = SRV queries received
+    QR_QTYPE_ATMA,          ///< Number of QTYPE = ATMA queries received
+    QR_QTYPE_NAPTR,         ///< Number of QTYPE = NAPTR queries received
+    QR_QTYPE_KX,            ///< Number of QTYPE = KX queries received
+    QR_QTYPE_CERT,          ///< Number of QTYPE = CERT queries received
+    QR_QTYPE_A6,            ///< Number of QTYPE = A6 queries received
+    QR_QTYPE_DNAME,         ///< Number of QTYPE = DNAME queries received
+    QR_QTYPE_SINK,          ///< Number of QTYPE = SINK queries received
+    QR_QTYPE_OPT,           ///< Number of QTYPE = OPT queries received
+    QR_QTYPE_APL,           ///< Number of QTYPE = APL queries received
+    QR_QTYPE_DS,            ///< Number of QTYPE = DS queries received
+    QR_QTYPE_SSHFP,         ///< Number of QTYPE = SSHFP queries received
+    QR_QTYPE_IPSECKEY,      ///< Number of QTYPE = IPSECKEY queries received
+    QR_QTYPE_RRSIG,         ///< Number of QTYPE = RRSIG queries received
+    QR_QTYPE_NSEC,          ///< Number of QTYPE = NSEC queries received
+    QR_QTYPE_DNSKEY,        ///< Number of QTYPE = DNSKEY queries received
+    QR_QTYPE_DHCID,         ///< Number of QTYPE = DHCID queries received
+    QR_QTYPE_NSEC3,         ///< Number of QTYPE = NSEC3 queries received
+    QR_QTYPE_NSEC3PARAM,    ///< Number of QTYPE = NSEC3PARAM queries received
+    QR_QTYPE_HIP,           ///< Number of QTYPE = HIP queries received
+    QR_QTYPE_NINFO,         ///< Number of QTYPE = NINFO queries received
+    QR_QTYPE_RKEY,          ///< Number of QTYPE = RKEY queries received
+    QR_QTYPE_TALINK,        ///< Number of QTYPE = TALINK queries received
+    QR_QTYPE_SPF,           ///< Number of QTYPE = SPF queries received
+    QR_QTYPE_UINFO,         ///< Number of QTYPE = UINFO queries received
+    QR_QTYPE_UID,           ///< Number of QTYPE = UID queries received
+    QR_QTYPE_GID,           ///< Number of QTYPE = GID queries received
+    QR_QTYPE_UNSPEC,        ///< Number of QTYPE = UNSPEC queries received
+    QR_QTYPE_TKEY,          ///< Number of QTYPE = TKEY queries received
+    QR_QTYPE_TSIG,          ///< Number of QTYPE = TSIG queries received
+    QR_QTYPE_IXFR,          ///< Number of QTYPE = IXFR queries received
+    QR_QTYPE_AXFR,          ///< Number of QTYPE = AXFR queries received
+    QR_QTYPE_MAILB,         ///< Number of QTYPE = MAILB queries received
+    QR_QTYPE_MAILA,         ///< Number of QTYPE = MAILA queries received
+    QR_QTYPE_URI,           ///< Number of QTYPE = URI queries received
+    QR_QTYPE_CAA,           ///< Number of QTYPE = CAA queries received
+    QR_QTYPE_TA,            ///< Number of QTYPE = TA queries received
+    QR_QTYPE_DLV,           ///< Number of QTYPE = DLV queries received
+    QR_QTYPE_OTHER,         ///< Number of queries in other QTYPE received
+    // Respose Attributes
+    QR_RESPONSE,            ///< Number of responses sent
+    QR_RESPONSE_TRUNCATED,  ///< Number of truncated responses sent
+    QR_RESPONSE_EDNS0,      ///< Number of responses with EDNS0; not implemented in BIND 10
+    QR_RESPONSE_TSIG,       ///< Number of responses with TSIG
+    QR_RESPONSE_SIG0,       ///< Number of responses with SIG(0); not implemented in BIND 10
+    QR_QRYSUCCESS,          ///< Number of queries resulted in rcode = NOERROR and answer RR >= 1
+    QR_QRYAUTHANS,          ///< Number of queries resulted in authoritative answer
+    QR_QRYNOAUTHANS,        ///< Number of queries resulted in non-authoritative answer
+    QR_QRYREFERRAL,         ///< Number of queries resulted in referral answer
+    QR_QRYNXRRSET,          ///< Number of queries resulted in NOERROR but answer RR == 0
+    // Response Rcodes
+    QR_RCODE_NOERROR,       ///< Number of queries resulted in RCODE = 0 (NoError)
+    QR_RCODE_FORMERR,       ///< Number of queries resulted in RCODE = 1 (FormErr)
+    QR_RCODE_SERVFAIL,      ///< Number of queries resulted in RCODE = 2 (ServFail)
+    QR_RCODE_NXDOMAIN,      ///< Number of queries resulted in RCODE = 3 (NXDomain)
+    QR_RCODE_NOTIMP,        ///< Number of queries resulted in RCODE = 4 (NotImp)
+    QR_RCODE_REFUSED,       ///< Number of queries resulted in RCODE = 5 (Refused)
+    QR_RCODE_YXDOMAIN,      ///< Number of queries resulted in RCODE = 6 (YXDomain)
+    QR_RCODE_YXRRSET,       ///< Number of queries resulted in RCODE = 7 (YXRRSet)
+    QR_RCODE_NXRRSET,       ///< Number of queries resulted in RCODE = 8 (NXRRSet)
+    QR_RCODE_NOTAUTH,       ///< Number of queries resulted in RCODE = 9 (NotAuth)
+    QR_RCODE_NOTZONE,       ///< Number of queries resulted in RCODE = 10 (NotZone)
+    QR_RCODE_BADSIGVERS,    ///< Number of queries resulted in RCODE = 16 (BADVERS, BADSIG)
+    QR_RCODE_BADKEY,        ///< Number of queries resulted in RCODE = 17 (BADKEY)
+    QR_RCODE_BADTIME,       ///< Number of queries resulted in RCODE = 18 (BADTIME)
+    QR_RCODE_BADMODE,       ///< Number of queries resulted in RCODE = 19 (BADMODE)
+    QR_RCODE_BADNAME,       ///< Number of queries resulted in RCODE = 20 (BADNAME)
+    QR_RCODE_BADALG,        ///< Number of queries resulted in RCODE = 21 (BADALG)
+    QR_RCODE_BADTRUNC,      ///< Number of queries resulted in RCODE = 22 (BADTRUNC)
+    QR_RCODE_OTHER,         ///< Number of queries resulted in other RCODEs
+    // End of counter types
+    QR_COUNTER_TYPES  ///< The number of defined counters
+};
+// item names for query/response counters
+const char *QRCounterItemName[QR_COUNTER_TYPES] = {
+    "request.v4",
+    "request.v6",
+    "request.edns0",
+    "request.badednsver",
+    "request.tsig",
+    "request.sig0",
+    "request.badsig",
+    "request.udp",
+    "request.tcp",
+    "request.dnssec_ok",
+    "opcode.query",
+    "opcode.iquery",
+    "opcode.status",
+    "opcode.notify",
+    "opcode.update",
+    "opcode.other",
+    "qtype.a",
+    "qtype.ns",
+    "qtype.md",
+    "qtype.mf",
+    "qtype.cname",
+    "qtype.soa",
+    "qtype.mb",
+    "qtype.mg",
+    "qtype.mr",
+    "qtype.null",
+    "qtype.wks",
+    "qtype.ptr",
+    "qtype.hinfo",
+    "qtype.minfo",
+    "qtype.mx",
+    "qtype.txt",
+    "qtype.rp",
+    "qtype.afsdb",
+    "qtype.x25",
+    "qtype.isdn",
+    "qtype.rt",
+    "qtype.nsap",
+    "qtype.nsap-ptr",
+    "qtype.sig",
+    "qtype.key",
+    "qtype.px",
+    "qtype.gpos",
+    "qtype.aaaa",
+    "qtype.loc",
+    "qtype.nxt",
+    "qtype.eid",
+    "qtype.nimloc",
+    "qtype.srv",
+    "qtype.atma",
+    "qtype.naptr",
+    "qtype.kx",
+    "qtype.cert",
+    "qtype.a6",
+    "qtype.dname",
+    "qtype.sink",
+    "qtype.opt",
+    "qtype.apl",
+    "qtype.ds",
+    "qtype.sshfp",
+    "qtype.ipseckey",
+    "qtype.rrsig",
+    "qtype.nsec",
+    "qtype.dnskey",
+    "qtype.dhcid",
+    "qtype.nsec3",
+    "qtype.nsec3param",
+    "qtype.hip",
+    "qtype.ninfo",
+    "qtype.rkey",
+    "qtype.talink",
+    "qtype.spf",
+    "qtype.uinfo",
+    "qtype.uid",
+    "qtype.gid",
+    "qtype.unspec",
+    "qtype.tkey",
+    "qtype.tsig",
+    "qtype.ixfr",
+    "qtype.axfr",
+    "qtype.mailb",
+    "qtype.maila",
+    "qtype.uri",
+    "qtype.caa",
+    "qtype.ta",
+    "qtype.dlv",
+    "qtype.other",
+    "response",
+    "response.truncated",
+    "response.edns0",
+    "response.tsig",
+    "response.sig0",
+    "qrysuccess",
+    "qryauthans",
+    "qrynoauthans",
+    "qryreferral",
+    "qrynxrrset",
+    "rcode.noerror",
+    "rcode.formerr",
+    "rcode.servfail",
+    "rcode.nxdomain",
+    "rcode.notimp",
+    "rcode.refused",
+    "rcode.yxdomain",
+    "rcode.yxrrset",
+    "rcode.nxrrset",
+    "rcode.notauth",
+    "rcode.notzone",
+    "rcode.badsigvers",
+    "rcode.badkey",
+    "rcode.badtime",
+    "rcode.badmode",
+    "rcode.badname",
+    "rcode.badalg",
+    "rcode.badtrunc",
+    "rcode.other"
+};
+
+} // anonymous namespace
+
+#endif // __STATISTICS_ITEMS_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/bin/auth/tests/auth_srv_unittest.cc b/src/bin/auth/tests/auth_srv_unittest.cc
index ca42473..5f954a4 100644
--- a/src/bin/auth/tests/auth_srv_unittest.cc
+++ b/src/bin/auth/tests/auth_srv_unittest.cc
@@ -71,6 +71,7 @@ using namespace isc::asiodns;
 using namespace isc::asiolink;
 using namespace isc::testutils;
 using namespace isc::server_common::portconfig;
+using isc::auth::statistics::Counters;
 using isc::UnitTestUtil;
 using boost::scoped_ptr;
 
@@ -121,33 +122,90 @@ protected:
 
     // Helper for checking Rcode statistic counters;
     // Checks for one specific Rcode statistics counter value
-    void checkRcodeCounter(const Rcode& rcode, int expected_value) const {
-        EXPECT_EQ(expected_value, server.getCounter(rcode)) <<
-                  "Expected Rcode count for " << rcode.toText() <<
-                  " " << expected_value << ", was: " <<
-                  server.getCounter(rcode);
+    void checkRcodeCounter(const std::string& rcode_name, const int rcode_value,
+                           const int expected_value) const
+    {
+            EXPECT_EQ(expected_value, rcode_value) <<
+                      "Expected Rcode count for " << rcode_name <<
+                      " " << expected_value << ", was: " <<
+                      rcode_value;
     }
 
     // Checks whether all Rcode counters are set to zero
     void checkAllRcodeCountersZero() const {
-        for (int i = 0; i < 17; i++) {
-            checkRcodeCounter(Rcode(i), 0);
+        std::map<std::string, ConstElementPtr> stats_map;
+        server.dump()->getValue(stats_map);
+
+        const std::string rcode_prefix("auth.server.qr.rcode.");
+        for (std::map<std::string, ConstElementPtr>::const_iterator
+                 i = stats_map.begin(), e = stats_map.end();
+             i != e;
+             ++i)
+        {
+            if (i->first.compare(0, rcode_prefix.size(), rcode_prefix) == 0) {
+                checkRcodeCounter(i->first, i->second->intValue(), 0);
+            }
         }
     }
 
     // Checks whether all Rcode counters are set to zero except the given
     // rcode (it is checked to be set to 'value')
     void checkAllRcodeCountersZeroExcept(const Rcode& rcode, int value) const {
-        for (int i = 0; i < 17; i++) {
-            const Rcode rc(i);
-            if (rc == rcode) {
-                checkRcodeCounter(Rcode(i), value);
-            } else {
-                checkRcodeCounter(Rcode(i), 0);
+        std::string target_rcode_name = rcode.toText();
+        std::transform(target_rcode_name.begin(), target_rcode_name.end(),
+                       target_rcode_name.begin(), ::tolower);
+        // rcode 16 is registered as both BADVERS and BADSIG
+        if (target_rcode_name == "badvers") {
+            target_rcode_name = "badsigvers";
+        }
+
+        std::map<std::string, ConstElementPtr> stats_map;
+        server.dump()->getValue(stats_map);
+
+        const std::string rcode_prefix("auth.server.qr.rcode.");
+        for (std::map<std::string, ConstElementPtr>::const_iterator
+                 i = stats_map.begin(), e = stats_map.end();
+             i != e;
+             ++i)
+        {
+            if (i->first.compare(0, rcode_prefix.size(), rcode_prefix) == 0) {
+                if (i->first.compare(rcode_prefix + target_rcode_name) == 0) {
+                    checkRcodeCounter(i->first, i->second->intValue(), value);
+                } else {
+                    checkRcodeCounter(i->first, i->second->intValue(), 0);
+                }
             }
         }
     }
 
+    uint64_t getOpcodeCounter(const Opcode& opcode) {
+        std::string target_opcode_name = opcode.toText();
+        std::transform(target_opcode_name.begin(), target_opcode_name.end(),
+                       target_opcode_name.begin(), ::tolower);
+        const unsigned int opcode_code = opcode.getCode();
+        if (opcode_code == 3 || (opcode_code > 5 && opcode_code < 16)) {
+            target_opcode_name = "other";
+        }
+
+        std::map<std::string, ConstElementPtr> stats_map;
+        server.dump()->getValue(stats_map);
+
+        const std::string opcode_prefix("auth.server.qr.opcode.");
+        for (std::map<std::string, ConstElementPtr>::const_iterator
+                 i = stats_map.begin(), e = stats_map.end();
+             i != e;
+             ++i)
+        {
+            if (i->first.compare(0, opcode_prefix.size(), opcode_prefix) == 0) {
+                if (i->first.compare(opcode_prefix + target_opcode_name) == 0) {
+                    return (i->second->intValue());
+                }
+            }
+        }
+
+        return (0);
+    }
+
     // Convenience method for tests that expect to return SERVFAIL
     // It calls processMessage, checks if there is an answer, and
     // check the header for default SERVFAIL data
@@ -403,7 +461,8 @@ TEST_F(AuthSrvTest, TSIGCheckFirst) {
         "It should be unsigned with this error";
     // TSIG should have failed, and so the per opcode counter shouldn't be
     // incremented.
-    EXPECT_EQ(0, server.getCounter(Opcode::RESERVED14()));
+    ConstElementPtr stats = server.dump();
+    EXPECT_EQ(0, stats->get("auth.server.qr.opcode.other")->intValue());
 
     checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
 }
@@ -1029,7 +1088,13 @@ TEST_F(AuthSrvTest,
 // Submit UDP normal query and check query counter
 TEST_F(AuthSrvTest, queryCounterUDPNormal) {
     // The counter should be initialized to 0.
-    EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_UDP_QUERY));
+    ConstElementPtr stats_init = server.dump();
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.qtype.ns")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.rcode.refused")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.response")->intValue());
     // Create UDP message and process.
     UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
                                        default_qid, Name("example.com"),
@@ -1037,18 +1102,29 @@ TEST_F(AuthSrvTest, queryCounterUDPNormal) {
     createRequestPacket(request_message, IPPROTO_UDP);
     server.processMessage(*io_message, *parse_message, *response_obuffer,
                           &dnsserv);
-    // After processing UDP query, the counter should be 1.
-    EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_UDP_QUERY));
-    // The counter for opcode Query should also be one
-    EXPECT_EQ(1, server.getCounter(Opcode::QUERY()));
-    // The counter for REFUSED responses should also be one, the rest zero
-    checkAllRcodeCountersZeroExcept(Rcode::REFUSED(), 1);
+    // After processing the UDP query, these counters should be incremented:
+    //   request.tcp, opcode.query, qtype.ns, rcode.refused, response
+    // and these counters should not be incremented:
+    //   request.tcp
+    ConstElementPtr stats_after = server.dump();
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(0, stats_after->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.qtype.ns")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.rcode.refused")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.response")->intValue());
 }
 
 // Submit TCP normal query and check query counter
 TEST_F(AuthSrvTest, queryCounterTCPNormal) {
     // The counter should be initialized to 0.
-    EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
+    ConstElementPtr stats_init = server.dump();
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.qtype.ns")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.rcode.refused")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.response")->intValue());
     // Create TCP message and process.
     UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
                                        default_qid, Name("example.com"),
@@ -1056,18 +1132,28 @@ TEST_F(AuthSrvTest, queryCounterTCPNormal) {
     createRequestPacket(request_message, IPPROTO_TCP);
     server.processMessage(*io_message, *parse_message, *response_obuffer,
                           &dnsserv);
-    // After processing TCP query, the counter should be 1.
-    EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
-    // The counter for SUCCESS responses should also be one
-    EXPECT_EQ(1, server.getCounter(Opcode::QUERY()));
-    // The counter for REFUSED responses should also be one, the rest zero
-    checkAllRcodeCountersZeroExcept(Rcode::REFUSED(), 1);
+    // After processing the TCP query, these counters should be incremented:
+    //   request.tcp, opcode.query, qtype.ns, rcode.refused, response
+    // and these counters should not be incremented:
+    //   request.udp
+    ConstElementPtr stats_after = server.dump();
+    EXPECT_EQ(0, stats_after->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.qtype.ns")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.rcode.refused")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.response")->intValue());
 }
 
 // Submit TCP AXFR query and check query counter
 TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
     // The counter should be initialized to 0.
-    EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
+    ConstElementPtr stats_init = server.dump();
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.qtype.axfr")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.response")->intValue());
     UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
                          Name("example.com"), RRClass::IN(), RRType::AXFR());
     createRequestPacket(request_message, IPPROTO_TCP);
@@ -1076,16 +1162,28 @@ TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
     server.processMessage(*io_message, *parse_message, *response_obuffer,
                           &dnsserv);
     EXPECT_FALSE(dnsserv.hasAnswer());
-    // After processing TCP AXFR query, the counter should be 1.
-    EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
-    // No rcodes should be incremented
-    checkAllRcodeCountersZero();
+    // After processing the TCP AXFR query, these counters should be
+    // incremented:
+    //   request.tcp, opcode.query, qtype.axfr
+    // and these counters should not be incremented:
+    //   request.udp, response
+    ConstElementPtr stats_after = server.dump();
+    EXPECT_EQ(0, stats_after->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.qtype.axfr")->intValue());
+    EXPECT_EQ(0, stats_after->get("auth.server.qr.response")->intValue());
 }
 
 // Submit TCP IXFR query and check query counter
 TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
     // The counter should be initialized to 0.
-    EXPECT_EQ(0, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
+    ConstElementPtr stats_init = server.dump();
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.qtype.ixfr")->intValue());
+    EXPECT_EQ(0, stats_init->get("auth.server.qr.response")->intValue());
     UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
                          Name("example.com"), RRClass::IN(), RRType::IXFR());
     createRequestPacket(request_message, IPPROTO_TCP);
@@ -1094,14 +1192,49 @@ TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
     server.processMessage(*io_message, *parse_message, *response_obuffer,
                           &dnsserv);
     EXPECT_FALSE(dnsserv.hasAnswer());
-    // After processing TCP IXFR query, the counter should be 1.
-    EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
+    // After processing the TCP IXFR query, these counters should be
+    // incremented:
+    //   request.tcp, opcode.query, qtype.ixfr
+    // and these counters should not be incremented:
+    //   request.udp, response
+    ConstElementPtr stats_after = server.dump();
+    EXPECT_EQ(0, stats_after->get("auth.server.qr.request.udp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.request.tcp")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.opcode.query")->intValue());
+    EXPECT_EQ(1, stats_after->get("auth.server.qr.qtype.ixfr")->intValue());
+    EXPECT_EQ(0, stats_after->get("auth.server.qr.response")->intValue());
 }
 
 TEST_F(AuthSrvTest, queryCounterOpcodes) {
-    for (int i = 0; i < 16; ++i) {
+    // Check for 0..2, 3 (other), 4..5
+    // The counter should be initialized to 0.
+    for (int i = 0; i < 6; ++i) {
         // The counter should be initialized to 0.
-        EXPECT_EQ(0, server.getCounter(Opcode(i)));
+        EXPECT_EQ(0, getOpcodeCounter(Opcode(i)));
+
+        // For each possible opcode, create a request message and send it
+        UnitTestUtil::createRequestMessage(request_message, Opcode(i),
+                                           default_qid, Name("example.com"),
+                                           RRClass::IN(), RRType::NS());
+        createRequestPacket(request_message, IPPROTO_UDP);
+
+        // "send" the request N-th times where N is i + 1 for i-th code.
+        // we intentionally use different values for each code
+        for (int j = 0; j <= i; ++j) {
+            parse_message->clear(Message::PARSE);
+            server.processMessage(*io_message, *parse_message,
+                                  *response_obuffer,
+                                  &dnsserv);
+        }
+
+        // Confirm the counter.
+        EXPECT_EQ(i + 1, getOpcodeCounter(Opcode(i)));
+    }
+
+    // Check for 6..15
+    // they are treated as the 'other' opcodes
+    for (int i = 6; i < 16; ++i) {
+        uint64_t before = getOpcodeCounter(Opcode(i));
 
         // For each possible opcode, create a request message and send it
         UnitTestUtil::createRequestMessage(request_message, Opcode(i),
@@ -1119,7 +1252,7 @@ TEST_F(AuthSrvTest, queryCounterOpcodes) {
         }
 
         // Confirm the counter.
-        EXPECT_EQ(i + 1, server.getCounter(Opcode(i)));
+        EXPECT_EQ(before + i + 1, getOpcodeCounter(Opcode(i)));
     }
 }
 
diff --git a/src/bin/auth/tests/statistics_unittest.cc b/src/bin/auth/tests/statistics_unittest.cc
index d2f5a5a..15acf55 100644
--- a/src/bin/auth/tests/statistics_unittest.cc
+++ b/src/bin/auth/tests/statistics_unittest.cc
@@ -24,62 +24,33 @@
 #include <dns/rcode.h>
 
 #include <cc/data.h>
-#include <cc/session.h>
 
 #include <auth/statistics.h>
+#include <auth/statistics_items.h>
 
 #include <dns/tests/unittest_util.h>
 
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
 using namespace std;
 using namespace isc::cc;
 using namespace isc::dns;
 using namespace isc::data;
+using isc::auth::statistics::Counters;
+using isc::auth::statistics::QRAttributes;
 
 namespace {
 
-class AuthCountersTest : public ::testing::Test {
-private:
-    class MockSession : public AbstractSession {
-    public:
-        MockSession() :
-            // by default we return a simple "success" message.
-            msg_(Element::fromJSON("{\"result\": [0, \"SUCCESS\"]}")),
-            throw_session_error_(false), throw_session_timeout_(false)
-        {}
-        virtual void establish(const char* socket_file);
-        virtual void disconnect();
-        virtual int group_sendmsg(ConstElementPtr msg, string group,
-                                  string instance, string to);
-        virtual bool group_recvmsg(ConstElementPtr& envelope,
-                                   ConstElementPtr& msg,
-                                   bool nonblock, int seq);
-        virtual void subscribe(string group, string instance);
-        virtual void unsubscribe(string group, string instance);
-        virtual void startRead(boost::function<void()> read_callback);
-        virtual int reply(ConstElementPtr envelope, ConstElementPtr newmsg);
-        virtual bool hasQueuedMsgs() const;
-        virtual void setTimeout(size_t) {}
-        virtual size_t getTimeout() const { return (0); };
-
-        void setThrowSessionError(bool flag);
-        void setThrowSessionTimeout(bool flag);
-
-        void setMessage(ConstElementPtr msg) { msg_ = msg; }
-
-        ConstElementPtr sent_msg;
-        string msg_destination;
-    private:
-        ConstElementPtr msg_;
-        bool throw_session_error_;
-        bool throw_session_timeout_;
-    };
-
+class CountersTest : public ::testing::Test {
 protected:
-    AuthCountersTest() : counters() {
+    CountersTest() : counters() {}
+    ~CountersTest() {
     }
-    ~AuthCountersTest() {
-    }
-    AuthCounters counters;
+    Counters counters;
     // no need to be inherited from the original class here.
     class MockModuleSpec {
     public:
@@ -89,283 +60,136 @@ protected:
     MockModuleSpec module_spec_;
 };
 
-void
-AuthCountersTest::MockSession::establish(const char*) {}
-
-void
-AuthCountersTest::MockSession::disconnect() {}
-
-void
-AuthCountersTest::MockSession::subscribe(string, string)
-{}
-
-void
-AuthCountersTest::MockSession::unsubscribe(string, string)
-{}
-
-void
-AuthCountersTest::MockSession::startRead(boost::function<void()>)
-{}
-
-int
-AuthCountersTest::MockSession::reply(ConstElementPtr, ConstElementPtr) {
-    return (-1);
-}
-
-bool
-AuthCountersTest::MockSession::hasQueuedMsgs() const {
-    return (false);
-}
-
-int
-AuthCountersTest::MockSession::group_sendmsg(ConstElementPtr msg,
-                                              string group, string, string)
-{
-    if (throw_session_error_) {
-        isc_throw(SessionError, "Session Error");
-    }
-    sent_msg = msg;
-    msg_destination = group;
-    return (0);
-}
-
-bool
-AuthCountersTest::MockSession::group_recvmsg(ConstElementPtr&,
-                                              ConstElementPtr& msg, bool, int)
-{
-    if (throw_session_timeout_) {
-        isc_throw(SessionTimeout, "Session Timeout");
-    }
-    msg = msg_;
-    return (true);
-}
-
-void
-AuthCountersTest::MockSession::setThrowSessionError(bool flag) {
-    throw_session_error_ = flag;
-}
-
-void
-AuthCountersTest::MockSession::setThrowSessionTimeout(bool flag) {
-    throw_session_timeout_ = flag;
-}
-
-TEST_F(AuthCountersTest, incrementUDPCounter) {
-    // The counter should be initialized to 0.
-    EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
-    EXPECT_NO_THROW(counters.inc(AuthCounters::SERVER_UDP_QUERY));
-    // After increment, the counter should be 1.
-    EXPECT_EQ(1, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
-}
-
-TEST_F(AuthCountersTest, incrementTCPCounter) {
-    // The counter should be initialized to 0.
-    EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
-    EXPECT_NO_THROW(counters.inc(AuthCounters::SERVER_TCP_QUERY));
-    // After increment, the counter should be 1.
-    EXPECT_EQ(1, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
-}
-
-TEST_F(AuthCountersTest, incrementInvalidCounter) {
-    // Expect to throw an isc::OutOfRange
-    EXPECT_THROW(counters.inc(AuthCounters::SERVER_COUNTER_TYPES),
-                 isc::OutOfRange);
-}
-
-TEST_F(AuthCountersTest, incrementOpcodeCounter) {
-    // The counter should be initialized to 0.  If we increment it by 1
-    // the counter should be 1.
-    for (int i = 0; i < 16; ++i) {
-        EXPECT_EQ(0, counters.getCounter(Opcode(i)));
-        counters.inc(Opcode(i));
-        EXPECT_EQ(1, counters.getCounter(Opcode(i)));
-    }
-}
-
-TEST_F(AuthCountersTest, incrementRcodeCounter) {
-    // The counter should be initialized to 0.  If we increment it by 1
-    // the counter should be 1.
-    for (int i = 0; i < 17; ++i) {
-        EXPECT_EQ(0, counters.getCounter(Rcode(i)));
-        counters.inc(Rcode(i));
-        EXPECT_EQ(1, counters.getCounter(Rcode(i)));
-    }
-}
-
-void
-opcodeDataCheck(ConstElementPtr data, const int expected[16]) {
-    const char* item_names[] = {
-        "query", "iquery", "status", "reserved3", "notify", "update",
-        "reserved6", "reserved7", "reserved8", "reserved9", "reserved10",
-        "reserved11", "reserved12", "reserved13", "reserved14", "reserved15",
-        NULL
-    };
-    int i;
-    for (i = 0; i < 16; ++i) {
-        ASSERT_NE(static_cast<const char*>(NULL), item_names[i]);
-        const string item_name = "opcode." + string(item_names[i]);
-        if (expected[i] == 0) {
-            EXPECT_FALSE(data->get(item_name));
-        } else {
-            EXPECT_EQ(expected[i], data->get(item_name)->intValue());
+bool checkCountersAllZeroExcept(const Counters::item_tree_type counters,
+                                const std::set<std::string>& except_for) {
+    std::map<std::string, ConstElementPtr> stats_map;
+    counters->getValue(stats_map);
+
+    for (std::map<std::string, ConstElementPtr>::const_iterator
+            i = stats_map.begin(), e = stats_map.end();
+            i != e;
+            ++i)
+    {
+        int expect = 0;
+        if (except_for.count(i->first) != 0) {
+            expect = 1;
         }
+        EXPECT_EQ(expect, i->second->intValue()) << "Expected counter "
+            << i->first << " = " << expect << ", actual: "
+            << i->second->intValue();
     }
-    // We should have examined all names
-    ASSERT_EQ(static_cast<const char*>(NULL), item_names[i]);
-}
 
-void
-rcodeDataCheck(ConstElementPtr data, const int expected[17]) {
-    const char* item_names[] = {
-        "noerror", "formerr", "servfail", "nxdomain", "notimp", "refused",
-        "yxdomain", "yxrrset", "nxrrset", "notauth", "notzone", "reserved11",
-        "reserved12", "reserved13", "reserved14", "reserved15", "badvers",
-        NULL
-    };
-    int i;
-    for (i = 0; i < 17; ++i) {
-        ASSERT_NE(static_cast<const char*>(NULL), item_names[i]);
-        const string item_name = "rcode." + string(item_names[i]);
-        if (expected[i] == 0) {
-            EXPECT_FALSE(data->get(item_name));
-        } else {
-            EXPECT_EQ(expected[i], data->get(item_name)->intValue());
-        }
+    return false;
+}
+
+TEST_F(CountersTest, incrementNormalQuery) {
+    Message response(Message::RENDER);
+    QRAttributes qrattrs;
+    std::set<std::string> expect_nonzero;
+
+    expect_nonzero.clear();
+    checkCountersAllZeroExcept(counters.dump(), expect_nonzero);
+
+    qrattrs.setQueryIPVersion(AF_INET6);
+    qrattrs.setQueryTransportProtocol(IPPROTO_UDP);
+    qrattrs.setQueryOpCode(Opcode::QUERY_CODE);
+    qrattrs.setQueryEDNS(true, false);
+    qrattrs.setQueryDO(true);
+    qrattrs.answerHasSent();
+
+    response.setRcode(Rcode::REFUSED());
+    response.addQuestion(Question(Name("example.com"), RRClass::IN(), RRType::AAAA()));
+
+    counters.inc(qrattrs, response);
+
+    expect_nonzero.clear();
+    expect_nonzero.insert("auth.server.qr.opcode.query");
+    expect_nonzero.insert("auth.server.qr.qtype.aaaa");
+    expect_nonzero.insert("auth.server.qr.request.v6");
+    expect_nonzero.insert("auth.server.qr.request.udp");
+    expect_nonzero.insert("auth.server.qr.request.edns0");
+    expect_nonzero.insert("auth.server.qr.request.dnssec_ok");
+    expect_nonzero.insert("auth.server.qr.response");
+    expect_nonzero.insert("auth.server.qr.qrynoauthans");
+    expect_nonzero.insert("auth.server.qr.rcode.refused");
+    checkCountersAllZeroExcept(counters.dump(), expect_nonzero);
+}
+
+TEST_F(CountersTest, checkDumpItems) {
+    std::map<std::string, ConstElementPtr> stats_map;
+    counters.dump()->getValue(stats_map);
+    for (std::map<std::string, ConstElementPtr>::const_iterator
+            i = stats_map.begin(), e = stats_map.end();
+            i != e;
+            ++i)
+    {
+        // item name check
+        const std::string stats_prefix("auth.server.");
+        EXPECT_EQ(0, i->first.compare(0, stats_prefix.size(), stats_prefix))
+            << "Item name " << i->first << " does not begin with "
+            << stats_prefix;
+
+        // item type check
+        EXPECT_NO_THROW(i->second->intValue())
+            << "Item " << i->first << " is not IntElement";
     }
-    // We should have examined all names
-    ASSERT_EQ(static_cast<const char*>(NULL), item_names[i]);
-}
-
-TEST_F(AuthCountersTest, getStatisticsWithoutValidator) {
-    // Get statistics data.
-    // Validate if it answers correct data.
-
-    // Counters should be initialized to 0.
-    EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
-    EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
-
-    // UDP query counter is set to 2.
-    counters.inc(AuthCounters::SERVER_UDP_QUERY);
-    counters.inc(AuthCounters::SERVER_UDP_QUERY);
-    // TCP query counter is set to 1.
-    counters.inc(AuthCounters::SERVER_TCP_QUERY);
-    ConstElementPtr statistics_data = counters.getStatistics();
-
-    // UDP query counter is 2 and TCP query counter is 1.
-    EXPECT_EQ(2, statistics_data->get("queries.udp")->intValue());
-    EXPECT_EQ(1, statistics_data->get("queries.tcp")->intValue());
-
-    // By default opcode counters are all 0 and omitted
-    const int opcode_results[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
-                                     0, 0, 0, 0, 0, 0, 0, 0 };
-    opcodeDataCheck(statistics_data, opcode_results);
-    // By default rcode counters are all 0 and omitted
-    const int rcode_results[17] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                    0, 0, 0, 0, 0, 0, 0, 0 };
-    rcodeDataCheck(statistics_data, rcode_results);
 }
 
-void
-updateOpcodeCounters(AuthCounters &counters, const int expected[16]) {
-    for (int i = 0; i < 16; ++i) {
-        for (int j = 0; j < expected[i]; ++j) {
-            counters.inc(Opcode(i));
-        }
+TEST_F(CountersTest, checkGetItems) {
+    std::map<std::string, ConstElementPtr> stats_map;
+
+    Counters::item_node_name_set_type names;
+
+    // get "auth.server.qr"
+    names.insert("auth.server.qr");
+    counters.get(names)->getValue(stats_map);
+    EXPECT_EQ(QR_COUNTER_TYPES, stats_map.size());
+    for (std::map<std::string, ConstElementPtr>::const_iterator
+            i = stats_map.begin(), e = stats_map.end();
+            i != e;
+            ++i)
+    {
+        // item name check
+        const std::string stats_prefix("auth.server.qr.");
+        EXPECT_EQ(0, i->first.compare(0, stats_prefix.size(), stats_prefix))
+            << "Item name " << i->first << " does not begin with "
+            << stats_prefix;
+
+        // item type check
+        EXPECT_NO_THROW(i->second->intValue())
+            << "Item " << i->first << " is not IntElement";
     }
-}
 
-void
-updateRcodeCounters(AuthCounters &counters, const int expected[17]) {
-    for (int i = 0; i < 17; ++i) {
-        for (int j = 0; j < expected[i]; ++j) {
-            counters.inc(Rcode(i));
-        }
-    }
-}
+    // get undefined tree
+    names.clear();
+    stats_map.clear();
+    names.insert("auth.server.UNDEFINED_TREE");
+    counters.get(names)->getValue(stats_map);
+    EXPECT_EQ(0, stats_map.size());
 
-TEST_F(AuthCountersTest, getStatisticsWithOpcodeCounters) {
-    // Increment some of the opcode counters.  Then they should appear in the
-    // submitted data; others shouldn't
-    const int opcode_results[16] = { 1, 2, 3, 0, 4, 5, 0, 0,
-                                     0, 0, 0, 0, 0, 0, 0, 0 };
-    updateOpcodeCounters(counters, opcode_results);
-    ConstElementPtr statistics_data = counters.getStatistics();
-    opcodeDataCheck(statistics_data, opcode_results);
+    // get empty list
+    names.clear();
+    stats_map.clear();
+    counters.get(names)->getValue(stats_map);
+    EXPECT_EQ(0, stats_map.size());
 }
 
-TEST_F(AuthCountersTest, getStatisticsWithAllOpcodeCounters) {
-    // Increment all opcode counters.  Then they should appear in the
-    // submitted data.
-    const int opcode_results[16] = { 1, 1, 1, 1, 1, 1, 1, 1,
-                                     1, 1, 1, 1, 1, 1, 1, 1 };
-    updateOpcodeCounters(counters, opcode_results);
-    ConstElementPtr statistics_data = counters.getStatistics();
-    opcodeDataCheck(statistics_data, opcode_results);
+TEST(StatisticsItemsTest, QRItemNamesCheck) {
+    // check the number of elements in the array
+    EXPECT_EQ(sizeof(QRCounterItemName) / sizeof(QRCounterItemName[0]), QR_COUNTER_TYPES);
+    // check the name of the first enum element
+    EXPECT_EQ(QRCounterItemName[QR_REQUEST_IPV4], "request.v4");
+    // check the name of the last enum element
+    EXPECT_EQ(QRCounterItemName[QR_RCODE_OTHER], "rcode.other");
 }
 
-TEST_F(AuthCountersTest, getStatisticsWithRcodeCounters) {
-    // Increment some of the rcode counters.  Then they should appear in the
-    // submitted data; others shouldn't
-    const int rcode_results[17] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
-                                    10, 0, 0, 0, 0, 0, 0, 11 };
-    updateRcodeCounters(counters, rcode_results);
-    ConstElementPtr statistics_data = counters.getStatistics();
-    rcodeDataCheck(statistics_data, rcode_results);
+TEST(StatisticsItemsTest, SocketItemNamesCheck) {
+    // check the number of elements in the array
+    EXPECT_EQ(sizeof(SocketCounterItemName) / sizeof(SocketCounterItemName[0]), SOCKET_COUNTER_TYPES);
+    // check the name of the first enum element
+    EXPECT_EQ(SocketCounterItemName[SOCKET_IPV4_UDP_BINDFAIL], "ipv4.udp.bindfail");
+    // check the name of the last enum element
+    EXPECT_EQ(SocketCounterItemName[SOCKET_UNIXDOMAIN_SENDERR], "unixdomain.senderr");
 }
 
-TEST_F(AuthCountersTest, getStatisticsWithAllRcodeCounters) {
-    // Increment all rcode counters.  Then they should appear in the
-    // submitted data.
-    const int rcode_results[17] = { 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                                     1, 1, 1, 1, 1, 1, 1, 1 };
-    updateOpcodeCounters(counters, rcode_results);
-    ConstElementPtr statistics_data = counters.getStatistics();
-    opcodeDataCheck(statistics_data, rcode_results);
-}
-
-TEST_F(AuthCountersTest, getStatisticsWithValidator) {
-
-    //a validator for the unittest
-    AuthCounters::validator_type validator;
-    ConstElementPtr el;
-
-    // Get statistics data with correct statistics validator.
-    validator = boost::bind(
-        &AuthCountersTest::MockModuleSpec::validateStatistics,
-        &module_spec_, _1, true);
-
-    EXPECT_TRUE(validator(el));
-
-    // register validator to AuthCounters
-    counters.registerStatisticsValidator(validator);
-
-    // Counters should be initialized to 0.
-    EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_UDP_QUERY));
-    EXPECT_EQ(0, counters.getCounter(AuthCounters::SERVER_TCP_QUERY));
-
-    // UDP query counter is set to 2.
-    counters.inc(AuthCounters::SERVER_UDP_QUERY);
-    counters.inc(AuthCounters::SERVER_UDP_QUERY);
-    // TCP query counter is set to 1.
-    counters.inc(AuthCounters::SERVER_TCP_QUERY);
-
-    // checks the value returned by getStatistics
-    ConstElementPtr statistics_data = counters.getStatistics();
-
-    // UDP query counter is 2 and TCP query counter is 1.
-    EXPECT_EQ(2, statistics_data->get("queries.udp")->intValue());
-    EXPECT_EQ(1, statistics_data->get("queries.tcp")->intValue());
-
-    // Get statistics data with incorrect statistics validator.
-    validator = boost::bind(
-        &AuthCountersTest::MockModuleSpec::validateStatistics,
-        &module_spec_, _1, false);
-
-    EXPECT_FALSE(validator(el));
-
-    counters.registerStatisticsValidator(validator);
-
-    // checks the value returned by getStatistics
-    EXPECT_FALSE(counters.getStatistics());
-}
 }



More information about the bind10-changes mailing list