def DisableSlowestSupplementalServers(self, multiplier=TOO_DISTANT_MULTIPLIER, max_servers=None, prefer_asn=None): """Disable servers who's fastest duration is multiplier * average of best 10 servers.""" if not max_servers: max_servers = self.max_servers_to_check supplemental_servers = self.enabled_supplemental fastest = [x for x in self.SortEnabledByFastest()][:10] best_10 = util.CalculateListAverage([x.fastest_check_duration for x in fastest]) cutoff = best_10 * multiplier self.msg("Removing secondary nameservers slower than %0.2fms (max=%s)" % (cutoff, max_servers)) for (idx, ns) in enumerate(self.SortEnabledByFastest()): hide = False if ns not in supplemental_servers: continue if ns.fastest_check_duration > cutoff: hide = True if idx > max_servers: hide = True if hide: matches = ns.MatchesTags(nameserver.PROVIDER_TAGS) if matches: self.msg("%s seems slow, but has tag: %s" % (ns, matches)) else: ns.tags.add('hidden')
def ComputeAverages(self): """Process all runs for all hosts, yielding an average for each host.""" if len(self.results) in self.cached_averages: return self.cached_averages[len(self.results)] records = [] for ns in self.results: if ns.disabled: continue failure_count = 0 nx_count = 0 run_averages = [] for test_run in self.results[ns]: # x: record, req_type, duration, response total_count = len(test_run) failure_count += len([x for x in test_run if not x[3]]) nx_count += len( [x for x in test_run if x[3] and not x[3].answer]) duration = sum([x[2] for x in test_run]) run_averages.append(duration / len(test_run)) # This appears to be a safe use of averaging averages overall_average = util.CalculateListAverage(run_averages) (fastest, slowest) = self.FastestAndSlowestDurationForNameServer(ns) records.append((ns, overall_average, run_averages, fastest, slowest, failure_count, nx_count, total_count)) self.cached_averages[len(self.results)] = records return self.cached_averages[len(self.results)]
def CheckConnectionQuality(self): """Look how healthy our DNS connection quality. Averages check durations.""" is_connection_offline = True durations = [] self.msg('Checking query interception status...') (intercepted, i_duration) = self.GetInterceptionStatus() if i_duration: is_connection_offline = False durations.append(i_duration) try_count = 3 for i in range(try_count): self.msg('Checking connection quality', count=i + 1, total=try_count) if self.primary: (broken, unused_warning, n_duration) = self.GetNegativeResponseDuration() if not broken: is_connection_offline = False durations.append(n_duration) (unused_response, g_duration, error_msg) = self.GetGoogleResponseDuration() durations.append(g_duration) if not error_msg: is_connection_offline = False if is_connection_offline and (i + 1) != try_count: self.msg( 'The internet connection appears to be offline (%s of %s)' % (i + 1, try_count)) time.sleep(0.2) if is_connection_offline: raise OfflineConnection( 'It would appear that your internet connection is offline. ' 'namebench is not gettng a response for DNS queries to ' '%s, %s, or %s.' % (self.primary.ip, GOOGLE_NS, OPENDNS_NS)) duration = util.CalculateListAverage(durations) congestion = duration / EXPECTED_CONGESTION_DURATION self.msg('Congestion level is %2.2fX (check duration: %2.2fms)' % (congestion, duration)) if congestion > 1: # multiplier is multiplier = 1 + ((congestion - 1) * CONGESTION_OFFSET_MULTIPLIER) if multiplier > MAX_CONGESTION_MULTIPLIER: multiplier = MAX_CONGESTION_MULTIPLIER else: multiplier = 1 return (intercepted, congestion, multiplier, duration)
def CheckConnectionQuality(self): """Look how healthy our DNS connection quality. Averages check durations.""" is_connection_offline = True self.msg('Checking query interception status...') odns = providers.OpenDNS() (intercepted, i_duration) = odns.InterceptionStateWithDuration() if i_duration: is_connection_offline = False durations = [] try_count = 3 for i in range(try_count): self.msg('Checking connection quality', count=i + 1, total=try_count) if self.primary: (broken, unused_warning, n_duration) = self.GetNegativeResponseDuration() if not broken: is_connection_offline = False durations.append(n_duration) (unused_response, g_duration, error_msg) = self.GetGoogleResponseDuration() if not error_msg: durations.append(g_duration) is_connection_offline = False if is_connection_offline and (i + 1) != try_count: self.msg( 'The internet connection appears to be offline (%s of %s)' % (i + 1, try_count)) time.sleep(0.2) if is_connection_offline: raise OfflineConnection( 'It would appear that your internet connection is offline.' 'namebench is not gettng a response for DNS queries to ' '%s, %s, or %s.' % (self.primary.ip, providers.GOOGLE_IP, providers.OPENDNS_IP)) avg_latency_s = util.CalculateListAverage(durations) / 1000.0 max_latency_s = max(durations) / 1000.0 self.msg("Average DNS lookup latency: %.2fs Maximum: %.2fs" % (avg_latency_s, max_latency_s)) return (intercepted, avg_latency_s, max_latency_s)
def DisableDistantServers(self, multiplier=TOO_DISTANT_MULTIPLIER, max_servers=MAX_NEARBY_SERVERS): """Disable servers who's fastest duration is multiplier * average of best 10 servers.""" self.RemoveBrokenServers(delete_unwanted=True) secondaries = self.secondaries fastest = [x for x in self.SortByFastest() if not x.disabled][:10] best_10 = util.CalculateListAverage( [x.fastest_check_duration for x in fastest]) cutoff = best_10 * multiplier self.msg( "Removing secondary nameservers slower than %0.2fms (max=%s)" % (cutoff, max_servers)) for idx, ns in enumerate(secondaries): if (ns.fastest_check_duration > cutoff) or idx > max_servers: self.remove(ns)
def _GenerateNameServerSummary(self): if self.cached_summary: return self.cached_summary nsdata = {} sorted_averages = sorted(self.ComputeAverages(), key=operator.itemgetter(1)) placed_at = -1 fastest = {} fastest_nonglobal = {} reference = {} # Fill in basic information for all nameservers, even those without scores. fake_position = 1000 for ns in sorted(self.nameservers, key=operator.attrgetter('check_average')): fake_position += 1 nsdata[ns] = { 'ip': ns.ip, 'name': ns.name, 'hostname': ns.hostname, 'version': ns.version, 'node_ids': list(ns.node_ids), 'sys_position': ns.system_position, 'is_failure_prone': ns.is_failure_prone, 'duration_min': float(ns.fastest_check_duration), 'is_global': ns.is_global, 'is_regional': ns.is_regional, 'is_custom': ns.is_custom, 'is_reference': False, 'is_disabled': bool(ns.disabled), 'check_average': ns.check_average, 'error_count': ns.error_count, 'timeout_count': ns.timeout_count, 'notes': url_map.CreateNoteUrlTuples(ns.notes), 'port_behavior': ns.port_behavior, 'position': fake_position } # Fill the scores in. for (ns, unused_avg, run_averages, fastest, slowest, unused_failures, nx_count, unused_total) in sorted_averages: placed_at += 1 durations = [] for _ in self.results[ns]: durations.append([x[2] for x in self.results[ns][0]]) nsdata[ns].update({ 'position': placed_at, 'overall_average': util.CalculateListAverage(run_averages), 'averages': run_averages, 'duration_min': float(fastest), 'duration_max': slowest, 'nx_count': nx_count, 'durations': durations, 'index': self._GenerateIndexSummary(ns), }) # Determine which nameserver to refer to for improvement scoring if not ns.disabled: if ns.system_position == 0: reference = ns elif not fastest_nonglobal and not ns.is_global: fastest_nonglobal = ns # If no reference was found, use the fastest non-global nameserver record. if not reference: if fastest_nonglobal: reference = fastest_nonglobal else: # The second ns. reference = sorted_averages[1][0] # Update the improvement scores for each nameserver. for ns in nsdata: if nsdata[ns]['ip'] != nsdata[reference]['ip']: if 'overall_average' in nsdata[ns]: nsdata[ns]['diff'] = ( (nsdata[reference]['overall_average'] / nsdata[ns]['overall_average']) - 1) * 100 else: nsdata[ns]['is_reference'] = True # print "--- DEBUG: %s ---" % ns # print nsdata[ns] # if 'index' in nsdata[ns]: # print "index length: %s" % len(nsdata[ns]['index']) # print "" self.cached_summary = sorted(nsdata.values(), key=operator.itemgetter('position')) return self.cached_summary
def testCalculateListAverage(self): self.assertEqual(util.CalculateListAverage([3, 2, 2]), 2.3333333333333335)
def check_average(self): # If we only have a ping result, sort by it. Otherwise, use all non-ping results. if len(self.checks) == 1: return self.checks[0][3] else: return util.CalculateListAverage([x[3] for x in self.checks[1:]])
def check_average(self): return util.CalculateListAverage( [x.check_average for x in self if not x.disabled])