Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(665)

Unified Diff: net/dns/dns_config_service_posix.cc

Issue 10543168: [net/dns] Instrument DnsConfigService to measure performance and failures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Provide stub service for Android. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/dns/dns_config_service_posix.cc
diff --git a/net/dns/dns_config_service_posix.cc b/net/dns/dns_config_service_posix.cc
index 5daaf69aac7b1c1357d08ce7b099a83eac75c56f..4428c97abfda226eb3400bfd7f57390b1e91b092 100644
--- a/net/dns/dns_config_service_posix.cc
+++ b/net/dns/dns_config_service_posix.cc
@@ -11,6 +11,8 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram.h"
+#include "base/time.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_util.h"
#include "net/dns/dns_hosts.h"
@@ -19,6 +21,7 @@
namespace net {
+#if !defined(OS_ANDROID)
namespace {
#ifndef _PATH_RESCONF // Normally defined in <resolv.h>
@@ -27,6 +30,24 @@ namespace {
const FilePath::CharType* kFilePathHosts = FILE_PATH_LITERAL("/etc/hosts");
+enum ConfigParsePosixResult {
+ CONFIG_PARSE_POSIX_OK = 0,
+ CONFIG_PARSE_POSIX_RES_INIT_FAILED,
+ CONFIG_PARSE_POSIX_RES_INIT_UNSET,
+ CONFIG_PARSE_POSIX_BAD_ADDRESS,
+ CONFIG_PARSE_POSIX_BAD_EXT_STRUCT,
+ CONFIG_PARSE_POSIX_NULL_ADDRESS,
+ CONFIG_PARSE_POSIX_NO_NAMESERVERS,
+ CONFIG_PARSE_POSIX_MISSING_OPTIONS,
+ CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS,
+ CONFIG_PARSE_POSIX_MAX // Bounding values for enumeration.
+};
+
+static void RecordConfigParseResult(ConfigParsePosixResult result) {
+ UMA_HISTOGRAM_ENUMERATION("AsyncDNS.ConfigParsePosix",
+ result, CONFIG_PARSE_POSIX_MAX);
+}
+
// A SerialWorker that uses libresolv to initialize res_state and converts
// it to DnsConfig.
class ConfigReader : public SerialWorker {
@@ -36,21 +57,25 @@ class ConfigReader : public SerialWorker {
: callback_(callback), success_(false) {}
void DoWork() OVERRIDE {
+ base::TimeTicks start_time = base::TimeTicks::Now();
success_ = false;
-#if defined(OS_ANDROID)
- NOTIMPLEMENTED();
-#elif defined(OS_OPENBSD)
+#if defined(OS_OPENBSD)
// Note: res_ninit in glibc always returns 0 and sets RES_INIT.
// res_init behaves the same way.
memset(&_res, 0, sizeof(_res));
- if ((res_init() == 0) && (_res.options & RES_INIT))
+ if (res_init() == 0) {
success_ = internal::ConvertResStateToDnsConfig(_res, &dns_config_);
+ } else {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_RES_INIT_FAILED);
+ }
#else // all other OS_POSIX
struct __res_state res;
memset(&res, 0, sizeof(res));
- if ((res_ninit(&res) == 0) && (res.options & RES_INIT))
+ if (res_ninit(&res) == 0) {
success_ = internal::ConvertResStateToDnsConfig(res, &dns_config_);
-
+ } else {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_RES_INIT_FAILED);
+ }
// Prefer res_ndestroy where available.
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
res_ndestroy(&res);
@@ -58,6 +83,9 @@ class ConfigReader : public SerialWorker {
res_nclose(&res);
#endif
#endif
+ UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigParseResult", success_);
mmenke 2012/06/18 17:19:50 Do these give us anything that AsyncDNS.ConfigPars
szym 2012/06/18 20:53:08 They would share the name across platforms. Not su
mmenke 2012/06/18 20:55:56 They wouldn't, though, since the windows one is ca
szym 2012/06/18 20:59:55 That was my mistake. Notice that initially both re
+ UMA_HISTOGRAM_TIMES("AsyncDNS.ConfigParseDuration",
+ base::TimeTicks::Now() - start_time);
}
void OnWorkFinished() OVERRIDE {
@@ -91,7 +119,11 @@ class HostsReader : public SerialWorker {
virtual ~HostsReader() {}
virtual void DoWork() OVERRIDE {
+ base::TimeTicks start_time = base::TimeTicks::Now();
success_ = ParseHostsFile(path_, &hosts_);
+ UMA_HISTOGRAM_BOOLEAN("AsyncDNS.HostParseResult", success_);
+ UMA_HISTOGRAM_TIMES("AsyncDNS.HostsParseDuration",
+ base::TimeTicks::Now() - start_time);
}
virtual void OnWorkFinished() OVERRIDE {
@@ -150,11 +182,13 @@ void DnsConfigServicePosix::OnDNSChanged(unsigned detail) {
}
}
-#if !defined(OS_ANDROID)
bool ConvertResStateToDnsConfig(const struct __res_state& res,
DnsConfig* dns_config) {
mmenke 2012/06/18 17:19:50 Optional: I'd suggest making this return a Config
CHECK(dns_config != NULL);
- DCHECK(res.options & RES_INIT);
+ if (!(res.options & RES_INIT)) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_RES_INIT_UNSET);
+ return false;
+ }
dns_config->nameservers.clear();
@@ -168,6 +202,7 @@ bool ConvertResStateToDnsConfig(const struct __res_state& res,
if (!ipe.FromSockAddr(
reinterpret_cast<const struct sockaddr*>(&addresses[i]),
sizeof addresses[i])) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_BAD_ADDRESS);
return false;
}
dns_config->nameservers.push_back(ipe);
@@ -191,10 +226,13 @@ bool ConvertResStateToDnsConfig(const struct __res_state& res,
addr = reinterpret_cast<const struct sockaddr*>(res._u._ext.nsaddrs[i]);
addr_len = sizeof *res._u._ext.nsaddrs[i];
} else {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_BAD_EXT_STRUCT);
return false;
}
- if (!ipe.FromSockAddr(addr, addr_len))
+ if (!ipe.FromSockAddr(addr, addr_len)) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_BAD_ADDRESS);
return false;
+ }
dns_config->nameservers.push_back(ipe);
}
#else // !(defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_FREEBSD))
@@ -204,6 +242,7 @@ bool ConvertResStateToDnsConfig(const struct __res_state& res,
if (!ipe.FromSockAddr(
reinterpret_cast<const struct sockaddr*>(&res.nsaddr_list[i]),
sizeof res.nsaddr_list[i])) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_BAD_ADDRESS);
return false;
}
dns_config->nameservers.push_back(ipe);
@@ -223,15 +262,37 @@ bool ConvertResStateToDnsConfig(const struct __res_state& res,
#endif
dns_config->edns0 = res.options & RES_USE_EDNS0;
+ // The current implementation assumes these options are set. They normally
+ // cannot be overwritten by /etc/resolv.conf
+ unsigned kRequiredOptions = RES_RECURSE | RES_DEFNAMES | RES_DNSRCH;
+ if ((res.options & kRequiredOptions) != kRequiredOptions) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_MISSING_OPTIONS);
+ return false;
+ }
+
+ unsigned kUnhandledOptions = RES_USEVC | RES_IGNTC | RES_USE_DNSSEC;
+ if (res.options & kUnhandledOptions) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS);
+ return false;
+ }
+
+ if (dns_config->nameservers.empty()) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_NO_NAMESERVERS);
+ return false;
+ }
+
// If any name server is 0.0.0.0, assume the configuration is invalid.
// TODO(szym): Measure how often this happens. http://crbug.com/125599
const IPAddressNumber kEmptyAddress(kIPv4AddressSize);
- for (unsigned i = 0; i < dns_config->nameservers.size(); ++i)
- if (dns_config->nameservers[i].address() == kEmptyAddress)
+ for (unsigned i = 0; i < dns_config->nameservers.size(); ++i) {
+ if (dns_config->nameservers[i].address() == kEmptyAddress) {
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_NULL_ADDRESS);
return false;
+ }
+ }
+ RecordConfigParseResult(CONFIG_PARSE_POSIX_OK);
return true;
}
-#endif // !defined(OS_ANDROID)
} // namespace internal
@@ -240,4 +301,18 @@ scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
return scoped_ptr<DnsConfigService>(new internal::DnsConfigServicePosix());
}
+#else // defined(OS_ANDROID)
+// Android NDK provides only a stub <resolv.h> header.
+class StubDnsConfigService : public DnsConfigService {
+ public:
+ StubDnsConfigService() {}
+ virtual ~StubDnsConfigService() {}
+ virtual void OnDNSChanged(unsigned detail) OVERRIDE {}
+};
+// static
+scoped_ptr<DnsConfigService> DnsConfigService::CreateSystemService() {
+ return scoped_ptr<DnsConfigService>(new StubDnsConfigService());
+}
+#endif
+
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698