use the 30 hits from find src contrib misc -type f |grep -v pyc |xargs grep '\bget_stats\b'| grep -v 'def get_stats' let's walk through them 6 in stats.py [16:29] (I use \b so we'll match things like callRemote("get_stats") and x=blah.get_stats; x() , not that anyone does the latter) It looks like all the references without dot prefixes are either comments or definitions or string literals containing get_stats [16:30] yeah. the string literal form is what invokes RIStatsProvider.get_stats [16:31] it's in a callRemote() argument I'm not seeing those I'm seeing log.msg("foofooget_stats() -> foo") now, 5 hits are in StatsProvider, which is the internal aggregate-all-the-producers object that provides RIStatsProvider [16:32] oh, my \b probably skipped those the \b matches word boundaries so blahXYZ won't match \bXYZ another hit is in stats.StatsGatherer, which is the service that does callRemote('get_stats') and retrieves stats through the RIStatsProvider.get_stats interface that's the receiving end of the remote protocol er, the initiating end, but it's where the stats wind up from line 211, you can see that the stats get sent to self.got_stats [16:34] which, from the NotImplementedError on line 227, you can tell is meant to be overridden by subclasses, so we need to look for 'def got_stats' in subclasses. Fortunately, all the subclasses are in this same file, right after StatsGatherer, so we don't have to look far [16:35] StdOutStatsGatherer.got_stats just uses pprint() on them and PickleStatsGatherer.got_stats pickles them [16:36] it turns out that misc/operations_helpers/munin/tahoe_stats reads that pickle line 460 is where it extracts an individual statistic [16:38] and on line 461 it does 'if value is not None', so it can probably tolerate None also, the PLUGINS table that makes up most of the file doesn't look at latencies at all [16:39] ok, so that covers stats.py next up: web/check_results.py ERC> another hit is in stats.StatsGatherer, which is the service that does callRemote('get_stats') and retrieves stats through the RIStatsProvider.get_stats interface that's the receiving end of the remote protocol er, the initiating end, but it's where the stats wind up from line 211, you can see that the stats get sent to self.got_stats [16:34] which, from the NotImplementedError on line 227, you can tell is meant to be overridden by subclasses, so we need to look for 'def got_stats' in subclasses. Fortunately, all the subclasses are in this same file, right after StatsGatherer, so we don't have to look far [16:35] StdOutStatsGatherer.got_stats just uses pprint() on them and PickleStatsGatherer.got_stats pickles them [16:36] it turns out that misc/operations_helpers/munin/tahoe_stats reads that pickle line 460 is where it extracts an individual statistic [16:38] and on line 461 it does 'if value is not None', so it can probably tolerate None also, the PLUGINS table that makes up most of the file doesn't look at latencies at all [16:39] ok, so that covers stats.py next up: web/check_results.py that calls the get_stats() that's really ICheckResults.get_stats [16:40] * arc` yanking contents of channel for more leisurely review [16:41] root.py: lines 199 and 212. Both look at a few specific keys and ignore the rest, and don't look at latencies next up: web/status.py four hits [16:42] there's a self.helper.get_stats() in HelperStatus.data_helper_stats.. the helper doesn't have a storage server, so latencies shouldn't be there same for the second hit in HelperStatus.render_JSON third hit is Statistics.renderHTTP (the t=="json" clause): that looks like an external HTTP interface for fetching the data. JSON can handle None, but let's add "find external HTTP callers" to the list of things to investigate [16:43] fourth hit is Statistics.data_get_stats, which is used as input to the series of 'render_*' functions in the rest of that class. Fortunately, none of them look at latency, except render_raw() which just pprints() the whole thing, for which None is fine [16:44] ok, that's all of web/status.py ERC> [16:40] * arc` yanking contents of channel for more leisurely review [16:41] root.py: lines 199 and 212. Both look at a few specific keys and ignore the rest, and don't look at latencies next up: web/status.py four hits [16:42] there's a self.helper.get_stats() in HelperStatus.data_helper_stats.. the helper doesn't have a storage server, so latencies shouldn't be there same for the second hit in HelperStatus.render_JSON third hit is Statistics.renderHTTP (the t=="json" clause): that looks like an external HTTP interface for fetching the data. JSON can handle None, but let's add "find external HTTP callers" to the list of things to investigate [16:43] fourth hit is Statistics.data_get_stats, which is used as input to the series of 'render_*' functions in the rest of that class. Fortunately, none of them look at latency, except render_raw() which just pprints() the whole thing, for which None is fine [16:44] ok, that's all of web/status.py last one is web/storage.py [16:45] three hits first is StorageStatus.render_JSON: the output of self.storage.get_stats() is included in the JSON response so that's another "find external HTTP callers" item second hit is a command [16:46] last hit is in StorageStatus.data_stats, which (looking at the associated storage_status.xhtml template for n:data="stats" attributes) is used by a couple of local render_* functions [16:47] but, none of those touch latency *** kevan_ (~kevan@host-134-71-248-56.allocated.csupomona.edu) has quit: Quit: leaving ERC> OK, that was a bit faster than I could keep up with, . * arc` yanking contents of channel for more leisurely review [16:41] root.py: lines 199 and 212. Both look at a few specific keys and ignore the rest, and don't look at latencies next up: web/status.py four hits [16:42] there's a self.helper.get_stats() in HelperStatus.data_helper_stats.. the helper doesn't have a storage server, so latencies shouldn't be there same for the second hit in HelperStatus.render_JSON third hit is Statistics.renderHTTP (the t=="json" clause): that looks like an external HTTP interface for fetching the data. JSON can handle None, but let's add "find external HTTP callers" to the list of things to investigate [16:43] fourth hit is Statistics.data_get_stats, which is used as input to the series of 'render_*' functions in the rest of that class. Fortunately, none of them look at latency, except render_raw() which just pprints() the whole thing, for which None is fine [16:44] ok, that's all of web/status.py last one is web/storage.py [16:45] three hits first is StorageStatus.render_JSON: the output of self.storage.get_stats() is included in the JSON response so that's another "find external HTTP callers" item second hit is a command [16:46] last hit is in StorageStatus.data_stats, which (looking at the associated storage_status.xhtml template for n:data="stats" attributes) is used by a couple of local render_* functions [16:47] but, none of those touch latency *** kevan_ (~kevan@host-134-71-248-56.allocated.csupomona.edu) has quit: Quit: leaving so, we're down to HTTP callers of /storage?t=json (StorageStatus.render_JSON) and of /statistics?t=json [16:49] where we might be concerned that those callers will mishandle a None (really a null, since it's JSON) [16:50] at that point, I think we can stop, because I'm pretty sure there's no code in tahoe that calls HTTP and parses JSON for stats.. all tahoe's stats-consuming code is either internal, or uses foolscap [16:51] I'm on Skype with Josh. He had a emacs UI error and didn't realize you were still typing. :-) so, in summary: if the tests pass, then yes, changing the storage server latency-reporting code to return None for percentile buckets that are not yet full should be ok [16:52] :-) I was in the buffer I was copying into... * arc` blushind * arc` blushing want me to pastebin anything? I think I have it all, going to review now. Thanks! ERC>