)]}'
{"gnocchi/aggregates/__init__.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":5,"context_line":"    cfg.StrOpt(\u0027driver\u0027,"},{"line_number":6,"context_line":"               default\u003d\u0027moving-average\u0027)"},{"line_number":7,"context_line":"]"},{"line_number":8,"context_line":"cfg.CONF.register_opts(OPTS, group\u003d\u0027aggregates\u0027)"},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"def __get_driver(name, conf):"},{"line_number":11,"context_line":"    d \u003d driver.DriverManager(\u0027gnocchi.aggregates\u0027,"}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_0aa1b993","line":8,"updated":"2014-07-13 23:38:24.000000000","message":"I wonder could we avoid introducing another config variable for this?\n\nIt would be great to just load the custom-aggregation extensions in a similar way to for example how we load pollsters etc. in ceilometer i.e. just list out a bunch of extensions under a certain namespace, then *all* of these extensions are loaded (with no need for them to be also selectively enabled in config).\n\nFor example, the entry points might look like:\n\n  gnocchi.aggregates \u003d\n    moving-average \u003d gnocchi.aggregates.rolling_statistics:RollingMean\n    ewma \u003d gnocchi.aggregates.rolling_statistics:ExponentiallyWeightedRollingMean  \n\nThen the code to load the extensions might look somewhat like the code used in the ceilometer agent base class to load pollsters:\n\n  https://github.com/openstack/ceilometer/blob/master/ceilometer/agent.py#L106\n  https://github.com/openstack/ceilometer/blob/master/ceilometer/agent.py#L127","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":19,"context_line":"def get_name(conf):"},{"line_number":20,"context_line":"    return conf.aggregates"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"class StatisticsDriver(object):"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    @staticmethod"},{"line_number":25,"context_line":"    def __init__(conf):"}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_6a5f95e5","line":22,"updated":"2014-07-13 23:38:24.000000000","message":"So calling this a driver may be a little confusing for users, as we usually use the term \"driver\" to mean a layer over storage backend or a messaging bus or some-such, whereas this is more of a small intermediary layer.\n\nMaybe \"StatisticsExtension\" or \"CustomAggregator\" or something of that ilk might work better?","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":1,"context_line":"from stevedore import extension"},{"line_number":2,"context_line":""},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"def extensions():"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_b32644cc","line":1,"updated":"2014-07-15 14:18:49.000000000","message":"Don\u0027t forget headers here.","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":12,"context_line":""},{"line_number":13,"context_line":"    @staticmethod"},{"line_number":14,"context_line":"    def __init__():"},{"line_number":15,"context_line":"        pass"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"    @staticmethod"},{"line_number":18,"context_line":"    def compute(data, **params):"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_1328d095","line":15,"updated":"2014-07-15 14:18:49.000000000","message":"This isn\u0027t needed at all actually :)","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":16,"context_line":"# under the License."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"import abc"},{"line_number":19,"context_line":"import six"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"@six.add_metaclass(abc.ABCMeta)"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_b0188c20","line":19,"updated":"2014-07-31 07:25:48.000000000","message":"Wrong import order, need to transpose these statements.","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"}],"gnocchi/aggregates/rolling_statistics.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":50,"context_line":"            idx \u003d pd.Series(data.index, index\u003ddata.index)"},{"line_number":51,"context_line":"            result \u003d idx.apply(rolling_window).dropna()"},{"line_number":52,"context_line":"        return dict((timeutils.strtime(id), val) for id, val in"},{"line_number":53,"context_line":"                    zip(result.index, result))"}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_aaad2d86","line":53,"updated":"2014-07-13 23:38:24.000000000","message":"If window is not a basestring, will we get an explosion on this line?","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":1,"context_line":"import numpy as np"},{"line_number":2,"context_line":"import pandas as pd"},{"line_number":3,"context_line":""},{"line_number":4,"context_line":"from gnocchi import aggregates"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_93130064","line":1,"updated":"2014-07-15 14:18:49.000000000","message":"Headers ^^^","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":7,"context_line":""},{"line_number":8,"context_line":"class RollingMean(aggregates.CustomAggregator):"},{"line_number":9,"context_line":""},{"line_number":10,"context_line":"    def compute(self, data, **params):"},{"line_number":11,"context_line":"        \u0027\u0027\u0027Function that computes a rolling mean"},{"line_number":12,"context_line":"        Parameters"},{"line_number":13,"context_line":"        ----------"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_be1c4814","line":10,"updated":"2014-07-15 14:18:49.000000000","message":"I\u0027d suggest to use real args here, that is:\n\nwindow, center\u003dFalse","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":24,"context_line":"        if \u0027center\u0027 in params:"},{"line_number":25,"context_line":"            center \u003d (params[\u0027center\u0027][0].upper() \u003d\u003d \u0027T\u0027)"},{"line_number":26,"context_line":"        else:"},{"line_number":27,"context_line":"            center \u003d False"},{"line_number":28,"context_line":"        if \u0027window\u0027 in params:"},{"line_number":29,"context_line":"            window \u003d params[\u0027window\u0027]"},{"line_number":30,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_3ed83852","line":27,"updated":"2014-07-15 14:18:49.000000000","message":"Using real args would allow to drop that ugly thing :)","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":47,"context_line":"                else:"},{"line_number":48,"context_line":"                    return dslice.mean()"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"        if isinstance(window, basestring):"},{"line_number":51,"context_line":"            data \u003d pd.Series(data)"},{"line_number":52,"context_line":"            idx \u003d pd.DatetimeIndex(data.index)"},{"line_number":53,"context_line":"            data \u003d pd.Series(data, index\u003didx).sort_index()"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_bee36803","line":50,"updated":"2014-07-15 14:18:49.000000000","message":"basestring not really py3 compatible, use six.text_types or something like that\n\nalso it\u0027s suspicious to check for window to be a string after you used it to define rolling_window above. I\u0027d check that just at the beginning before doing anything else.","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"        else:"},{"line_number":115,"context_line":"            raise TypeError(\u0027window must be basestring\u0027)"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"class EWMA(aggregates.CustomAggregator):"},{"line_number":119,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_fec0804b","line":116,"updated":"2014-07-15 14:18:49.000000000","message":"I wonder if you can\u0027t factorize some things with the class above since it looks a bit the same.","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":145,"context_line":"            result \u003d pd.Series(result, index\u003ddata.index).dropna()"},{"line_number":146,"context_line":"            return dict((timeutils.strtime(id), val) for id, val in"},{"line_number":147,"context_line":"                    zip(result.index, result))"},{"line_number":148,"context_line":"        except KeyError:"},{"line_number":149,"context_line":"            raise KeyError(\u0027window must be specified for aggregate\u0027)"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_de9c9c6c","line":148,"updated":"2014-07-15 14:18:49.000000000","message":"The try/except is very large, that means any keyerror in all your lines will raise these exception, it\u0027s not really helpful. Keep that try/except where you expect the potential keyerror to be raised.","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"e46f269087dfe917c79d5c1bcc4b3ee7f7943089","unresolved":false,"context_lines":[{"line_number":72,"context_line":"        idx \u003d pd.Series(data.index, index\u003ddata.index)"},{"line_number":73,"context_line":"        result \u003d idx.apply(rolling_window).dropna()"},{"line_number":74,"context_line":"        return dict((timeutils.strtime(id), val) for id, val in"},{"line_number":75,"context_line":"                zip(result.index, result))"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"class RollingVariance(aggregates.CustomAggregator):"}],"source_content_type":"text/x-python","patch_set":11,"id":"baada198_2325435c","line":75,"updated":"2014-07-16 19:39:07.000000000","message":"Creation of the dict wouldn\u0027t we required if you follow the approach suggested in gnocchi/rest/__init__.py","commit_id":"e265faa3f965c0a1e4ecb3d6548d670732bf35fa"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"ccf963d259787021e7a7caf6fa3595519b76294c","unresolved":false,"context_lines":[{"line_number":47,"context_line":"        return result.to_dict()"},{"line_number":48,"context_line":"    except:"},{"line_number":49,"context_line":"        raise AttributeError("},{"line_number":50,"context_line":"            \u0027Granularity must be specified and a freq string.\u0027)"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"class RollingMean(aggregates.CustomAggregator):"}],"source_content_type":"text/x-python","patch_set":13,"id":"baada198_350c35ec","line":50,"updated":"2014-07-18 21:03:59.000000000","message":"Does this exception type and string match the possible failure modes in the try block?","commit_id":"07818e434dcec188224bf0d9c8b53eda8d3999e7"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"ccf963d259787021e7a7caf6fa3595519b76294c","unresolved":false,"context_lines":[{"line_number":92,"context_line":"                granularity).delta.total_seconds()"},{"line_number":93,"context_line":"        except:"},{"line_number":94,"context_line":"            raise AttributeError("},{"line_number":95,"context_line":"                \u0027granularity must be specified and a frequency string\u0027)"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"        data \u003d pd.Series(data)"},{"line_number":98,"context_line":"        idx \u003d pd.DatetimeIndex(data.index)"}],"source_content_type":"text/x-python","patch_set":13,"id":"baada198_95f6e1d5","line":95,"updated":"2014-07-18 21:03:59.000000000","message":"Similarly to the previous comment.","commit_id":"07818e434dcec188224bf0d9c8b53eda8d3999e7"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":21,"context_line":"import pandas as pd"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"from gnocchi import aggregates"},{"line_number":24,"context_line":"from gnocchi.openstack.common import timeutils"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"class AggregationFailure(aggregates.AggregationFailure):"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_30d47c1e","line":24,"updated":"2014-07-31 07:25:48.000000000","message":"Unused import.","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        else:"},{"line_number":38,"context_line":"            dslice \u003d data[x - datetime.timedelta(seconds\u003dwindow):x]"},{"line_number":39,"context_line":"        if dslice.size \u003c min_periods:"},{"line_number":40,"context_line":"            return np.nan"},{"line_number":41,"context_line":"        else:"},{"line_number":42,"context_line":"            return func(dslice)"},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_d046e0bf","line":40,"updated":"2014-07-31 07:25:48.000000000","message":"What\u0027s the purpose of returning NaN here, when we later exlcude NaNs with dropna()?","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":10683,"name":"Ana Malagon","email":"atmalagon@gmail.com","username":"atmalagon"},"change_message_id":"00289b0407c9fafa73eaf46f97a0fd42888af338","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        else:"},{"line_number":38,"context_line":"            dslice \u003d data[x - datetime.timedelta(seconds\u003dwindow):x]"},{"line_number":39,"context_line":"        if dslice.size \u003c min_periods:"},{"line_number":40,"context_line":"            return np.nan"},{"line_number":41,"context_line":"        else:"},{"line_number":42,"context_line":"            return func(dslice)"},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_66bf49fe","line":40,"in_reply_to":"baada198_d046e0bf","updated":"2014-08-06 15:22:57.000000000","message":"I was thinking that for aggregation\u003d\u0027std\u0027, it would handle the case when there is only 1 entry in the time window by having min_periods \u003d 2 (L68).","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    try:"},{"line_number":49,"context_line":"        result \u003d idx.apply(rolling_window).dropna()"},{"line_number":50,"context_line":"        return result.to_dict()"},{"line_number":51,"context_line":"    except:"},{"line_number":52,"context_line":"        raise AggregationFailure"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_10b858e7","line":51,"updated":"2014-07-31 07:25:48.000000000","message":"s/except:/except Exception:/","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":49,"context_line":"        result \u003d idx.apply(rolling_window).dropna()"},{"line_number":50,"context_line":"        return result.to_dict()"},{"line_number":51,"context_line":"    except:"},{"line_number":52,"context_line":"        raise AggregationFailure"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"class RollingMean(aggregates.CustomAggregator):"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_70ac34a0","line":52,"updated":"2014-07-31 07:25:48.000000000","message":"This is raising the class AggregationFailure, as opposed to an instance of that class.\n\nAlso, does it make sense to record the context of the failure, in a log and/or the AggregationFailure exception message?\n\nOtherwise, how would the issue be debugged?","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":112,"context_line":"        beta \u003d float(beta)"},{"line_number":113,"context_line":"        alpha \u003d float(alpha)"},{"line_number":114,"context_line":"        if (beta \u003c 0 or beta \u003e 1) or (alpha \u003c 0 or alpha \u003e 1):"},{"line_number":115,"context_line":"            raise AggregationFailure"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":"        data \u003d storage_object.get_measures(entity_id, start, stop,"},{"line_number":118,"context_line":"                                           granularity\u003d1)"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_b0c24c33","line":115,"updated":"2014-07-31 07:25:48.000000000","message":"Similar comment to above.","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":147,"context_line":"        beta_rec \u003d 1 - np.power(1 - beta, q)"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":"        for j in range(1, len(data)):"},{"line_number":150,"context_line":"            d \u003d delta[j-1]"},{"line_number":151,"context_line":"            alpha_rec \u003d alpha_rec / (np.power(1 - alpha, d) + alpha_rec)"},{"line_number":152,"context_line":"            beta_rec \u003d beta_rec / (np.power(1 - beta, d) + beta_rec)"},{"line_number":153,"context_line":"            result.append((result[-1] + d * slope_rec) * (1 - alpha_rec) +"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_90e4680f","line":150,"updated":"2014-07-31 07:25:48.000000000","message":"s/j-1/j - 1/","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":155,"context_line":"            a \u003d beta_rec * (result[-1] + result[-2]) / d"},{"line_number":156,"context_line":"            b \u003d (1 - beta_rec) * slope_rec"},{"line_number":157,"context_line":"            slope_rec \u003d a + b"},{"line_number":158,"context_line":"        result \u003d pd.Series(result, index\u003ddata.index).dropna()"},{"line_number":159,"context_line":"        return result.to_dict()"},{"line_number":160,"context_line":""},{"line_number":161,"context_line":"        # NOTE(atmalagon): there is another method to do this smoothing"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_90f54886","line":158,"updated":"2014-07-31 07:25:48.000000000","message":"Rather than re-using the result identifier, which is a little confusing given that it previously referenced a list and now references a timeseries, how about just:\n\n  return pd.Series(result, index\u003ddata.index).dropna().to_dict()","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"8d76c94fad5033b2446910264d2c2fa3930708ec","unresolved":false,"context_lines":[{"line_number":59,"context_line":""},{"line_number":60,"context_line":"        data \u003d storage_object.get_measures(entity_id, start, stop,"},{"line_number":61,"context_line":"                                           aggregation\u003d\u0027mean\u0027,"},{"line_number":62,"context_line":"                                           granularity\u003d1)"},{"line_number":63,"context_line":"        if center:"},{"line_number":64,"context_line":"            center \u003d (center.upper() \u003d\u003d \u0027T\u0027)"},{"line_number":65,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_4436e3e8","line":62,"updated":"2014-09-08 18:51:18.000000000","message":"How would the lack of 1s granularity in the entity archive be handled here?","commit_id":"a550839a88da999ed671dc82a545ada158942512"}],"gnocchi/rest/__init__.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":106,"context_line":""},{"line_number":107,"context_line":"        try:"},{"line_number":108,"context_line":"            # Replace timestamp keys by their string versions"},{"line_number":109,"context_line":"            if aggregation !\u003d \u0027moving-average\u0027:"},{"line_number":110,"context_line":"                return dict((timeutils.strtime(k), v)"},{"line_number":111,"context_line":"                        for k, v"},{"line_number":112,"context_line":"                        in six.iteritems(pecan.request.storage.get_measures("}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_ea964593","line":109,"updated":"2014-07-13 23:38:24.000000000","message":"Rather than encoding knowledge of \u0027moving-average\u0027, specifically, into the API layer, would it be better to maintain a dict of custom aggregate extensions and then simply use the aggregation parameter to lookup that dict and call out to the extension if necessary?","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":113,"context_line":"                            self.entity_id, start, stop, aggregation,"},{"line_number":114,"context_line":"                            granularity)))"},{"line_number":115,"context_line":"            else:"},{"line_number":116,"context_line":"                b\u003dpecan.request.storage.get_measures(self.entity_id,"},{"line_number":117,"context_line":"                  start, stop, aggregation, 1)"},{"line_number":118,"context_line":"                return pecan.request.aggregates.compute(b, **agg_params)"},{"line_number":119,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_0a38d9d1","line":116,"updated":"2014-07-13 23:38:24.000000000","message":"s/b\u003dpecan/b \u003d pecan/","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":100,"context_line":"    @pecan.expose(\u0027json\u0027)"},{"line_number":101,"context_line":"    def get_measures(self, start\u003dNone, stop\u003dNone, aggregation\u003d\u0027mean\u0027,"},{"line_number":102,"context_line":"                     granularity\u003dNone, **agg_params):"},{"line_number":103,"context_line":"        def make_dict(ext):"},{"line_number":104,"context_line":"            return (ext.name, ext.obj)"},{"line_number":105,"context_line":"        CUSTOM_AGGREGATES \u003d dict((name, obj) for name, obj in"},{"line_number":106,"context_line":"                                 pecan.request.aggregates.map(make_dict))"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_9ed224fe","line":103,"updated":"2014-07-15 14:18:49.000000000","message":"Having a def inside a def make the def make_dict to be re-evaluated each time uselessly. Either define that as a staticmethod elsewhere, or use a lambda it\u0027d be nicer.","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":116,"context_line":"                                                       start, stop,"},{"line_number":117,"context_line":"                                                       aggregation\u003d\u0027mean\u0027,"},{"line_number":118,"context_line":"                                                       granularity\u003d1)"},{"line_number":119,"context_line":"                return CUSTOM_AGGREGATES[aggregation].compute(b, **agg_params)"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"            # Replace timestamp keys by their string versions"},{"line_number":122,"context_line":"            else:"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_3e1758a4","line":119,"updated":"2014-07-15 14:18:49.000000000","message":"So that means that all custom aggregates are based on mean?\nI\u0027m not saying that it\u0027s wrong, I have no idea, I just want to be sure that\u0027s what expected :)","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":118,"context_line":"                                                       granularity\u003d1)"},{"line_number":119,"context_line":"                return CUSTOM_AGGREGATES[aggregation].compute(b, **agg_params)"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"            # Replace timestamp keys by their string versions"},{"line_number":122,"context_line":"            else:"},{"line_number":123,"context_line":"                return dict((timeutils.strtime(k), v)"},{"line_number":124,"context_line":"                            for k, v"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_bef44887","line":121,"updated":"2014-07-15 14:18:49.000000000","message":"The commit is now misplaced.","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"e46f269087dfe917c79d5c1bcc4b3ee7f7943089","unresolved":false,"context_lines":[{"line_number":82,"context_line":"        namespace\u003d\u0027gnocchi.aggregates\u0027,"},{"line_number":83,"context_line":"        invoke_on_load\u003dTrue)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    CUSTOM_AGGREGATES \u003d dict((x.name, x.obj) for x in mgr)"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    def __init__(self, entity_id):"},{"line_number":88,"context_line":"        self.entity_id \u003d entity_id"}],"source_content_type":"text/x-python","patch_set":11,"id":"baada198_230e23e6","line":85,"updated":"2014-07-16 19:39:07.000000000","message":"Maybe neater to put lines 81-85 into the controller __init__ method (assuming the controller is always a singleton).","commit_id":"e265faa3f965c0a1e4ecb3d6548d670732bf35fa"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"e46f269087dfe917c79d5c1bcc4b3ee7f7943089","unresolved":false,"context_lines":[{"line_number":110,"context_line":"    def get_measures(self, start\u003dNone, stop\u003dNone, aggregation\u003d\u0027mean\u0027,"},{"line_number":111,"context_line":"                     granularity\u003dNone, **agg_params):"},{"line_number":112,"context_line":"        if (aggregation not in storage.AGGREGATION_TYPES and"},{"line_number":113,"context_line":"            aggregation not in self.CUSTOM_AGGREGATES):"},{"line_number":114,"context_line":"            pecan.abort(400, \"Invalid aggregation value %s, must be one of %s\""},{"line_number":115,"context_line":"                        % (aggregation, str(storage.AGGREGATION_TYPES),"},{"line_number":116,"context_line":"                           str(self.CUSTOM_AGGREGATES)))"}],"source_content_type":"text/x-python","patch_set":11,"id":"baada198_03511f0e","line":113,"updated":"2014-07-16 19:39:07.000000000","message":"You can simplify with de Morgan\u0027s Law:\n\n  if not (aggregation in storage.AGGREGATION_TYPES or\n          aggregation in self.CUSTOM_AGGREGATES):","commit_id":"e265faa3f965c0a1e4ecb3d6548d670732bf35fa"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"e46f269087dfe917c79d5c1bcc4b3ee7f7943089","unresolved":false,"context_lines":[{"line_number":128,"context_line":"                                             get_measures(self.entity_id,"},{"line_number":129,"context_line":"                                                          start, stop,"},{"line_number":130,"context_line":"                                                          aggregation,"},{"line_number":131,"context_line":"                                                          granularity)))"},{"line_number":132,"context_line":"        except storage.EntityDoesNotExist as e:"},{"line_number":133,"context_line":"            pecan.abort(400, str(e))"},{"line_number":134,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"baada198_43ceb7b5","line":131,"updated":"2014-07-16 19:39:07.000000000","message":"I\u0027m not a big fan of the way a dict is returned from get_measures, as ordering is lost. (But that\u0027s something orthogonal to your patch).\n\nHowever I\u0027m wondering why the dict is created by the API layer in the standard-aggregate case but not in the custom-aggregate case?\n\nWould it make more sense to do:\n\n      if aggregation in self.CUSTOM_AGGREGATES:\n          measures \u003d self.CUSTOM_AGGREGATES[aggregation].compute(...)\n      else \n          get_measures(self.entity_id, ...)\n\n      return dict((timeutils.strtime(k), v) for k, v in six.iteritems(measures))","commit_id":"e265faa3f965c0a1e4ecb3d6548d670732bf35fa"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":117,"context_line":"        try:"},{"line_number":118,"context_line":"            if granularity:"},{"line_number":119,"context_line":"                granularity \u003d pandas.datetools.to_offset("},{"line_number":120,"context_line":"                    granularity).delta.total_seconds()"},{"line_number":121,"context_line":"            if aggregation in self.custom_aggregates:"},{"line_number":122,"context_line":"                measures \u003d self.custom_aggregates[aggregation].compute("},{"line_number":123,"context_line":"                    pecan.request.storage, self.entity_id, start, stop,"}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_d01d00c0","line":120,"updated":"2014-07-31 07:25:48.000000000","message":"Line 118 to 120 seem like they belong in the preceding granularity patch.","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":131,"context_line":"            return dict((timeutils.strtime(k), v) for k, v"},{"line_number":132,"context_line":"                        in six.iteritems(measures))"},{"line_number":133,"context_line":"        except storage.EntityDoesNotExist as e:"},{"line_number":134,"context_line":"            pecan.abort(400, str(e))"},{"line_number":135,"context_line":"        except aggregates.AggregationFailure as e:"},{"line_number":136,"context_line":"            pecan.abort(400, str(e))"},{"line_number":137,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_105e9879","line":134,"updated":"2014-07-31 07:25:48.000000000","message":"I think you need a rebase, as this has now changed to a 404:\n\n  https://github.com/stackforge/gnocchi/commit/b1cd755c","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"95e35b2e335382c33c889f531f8d31fd611f6347","unresolved":false,"context_lines":[{"line_number":35,"context_line":"from gnocchi import indexer"},{"line_number":36,"context_line":"from gnocchi import storage"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"from stevedore import extension"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"def get_user_and_project():"}],"source_content_type":"text/x-python","patch_set":30,"id":"7a8c0949_c9a0e045","line":38,"updated":"2014-11-07 12:37:33.000000000","message":"This should be in the second import group","commit_id":"4403ddfa75769ea9172c4721576b7f9d7af81290"}],"gnocchi/rest/app.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":81,"context_line":"        i \u003d indexer.get_driver(conf)"},{"line_number":82,"context_line":"    a \u003d pecan_config.get(\u0027aggregates\u0027)"},{"line_number":83,"context_line":"    if not a:"},{"line_number":84,"context_line":"        a \u003d aggregates.get_driver(conf)"},{"line_number":85,"context_line":"    return pecan.make_app("},{"line_number":86,"context_line":"        pecan_config[\u0027app\u0027][\u0027root\u0027],"},{"line_number":87,"context_line":"        debug\u003dconf.debug,"}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_8abce9bc","line":84,"updated":"2014-07-13 23:38:24.000000000","message":"I don\u0027t think this would be required if we shift from using a driver-type approach to a extension-type approach as suggested in another comment.","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"}],"gnocchi/rolling_statistics.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":3,"context_line":"#originally from stackoverflow.com/questions/15771472/pandas-rolling-\\"},{"line_number":4,"context_line":"#mean-by-time-interval solution by user2689410"},{"line_number":5,"context_line":"#see also this post: stackoverflow.com/questions/14300768/pandas-rolling-\\"},{"line_number":6,"context_line":"#computation-with-window-based-on-values-instead-of-counts"},{"line_number":7,"context_line":""},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"def rolling_mean(data, window, min_periods\u003d1, center\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_beb1fd90","line":6,"updated":"2014-07-04 06:51:09.000000000","message":"You can probably drop these comments from the final version.","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":13,"context_line":"    ----------"},{"line_number":14,"context_line":"    :param data : DataFrame or Series"},{"line_number":15,"context_line":"           If a DataFrame is passed, the rolling_mean is computed for all"},{"line_number":16,"context_line":"           columns."},{"line_number":17,"context_line":"    :param window : int or string"},{"line_number":18,"context_line":"             If int is passed, window is the number of observations used for"},{"line_number":19,"context_line":"             calculating the statistic, as defined by the function"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_9e70b9dd","line":16,"updated":"2014-07-04 06:51:09.000000000","message":"Do we really need the flxibility to handle either dataframes or timeseries?\n\nWould restricting to TimeSeries-only simplify the code?","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":29,"context_line":"    -------"},{"line_number":30,"context_line":"    Series or DataFrame, if more than one column"},{"line_number":31,"context_line":"    \u0027\u0027\u0027"},{"line_number":32,"context_line":"    def f(x):"},{"line_number":33,"context_line":"        \u0027\u0027\u0027Function to apply that actually computes the rolling mean.\u0027\u0027\u0027"},{"line_number":34,"context_line":"        if center is False:"},{"line_number":35,"context_line":"            dslice \u003d col[x - pd.datetools.to_offset(window).delta:x]"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_3ef08d66","line":32,"updated":"2014-07-04 06:51:09.000000000","message":"Need to provide a more meaingful name for f()","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    \u0027\u0027\u0027"},{"line_number":32,"context_line":"    def f(x):"},{"line_number":33,"context_line":"        \u0027\u0027\u0027Function to apply that actually computes the rolling mean.\u0027\u0027\u0027"},{"line_number":34,"context_line":"        if center is False:"},{"line_number":35,"context_line":"            dslice \u003d col[x - pd.datetools.to_offset(window).delta:x]"},{"line_number":36,"context_line":"                # adding a microsecond because when slicing with labels"},{"line_number":37,"context_line":"                # start and endpoint are inclusive \u003c-- taken out (atmalagon)"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_1e4909b7","line":34,"updated":"2014-07-04 06:51:09.000000000","message":"Can you transpose the order of the id and else blocks and make the condition:\n\n    if center:\n\nas opposed to the negation? (for readability)","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":43,"context_line":"        else:"},{"line_number":44,"context_line":"            return dslice.mean()"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"    data \u003d pd.DataFrame(data.copy())"},{"line_number":47,"context_line":"    dfout \u003d pd.DataFrame()"},{"line_number":48,"context_line":"    if isinstance(window, int):"},{"line_number":49,"context_line":"        dfout \u003d pd.rolling_mean(data, window, min_periods\u003dmin_periods,"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_7e420569","line":46,"updated":"2014-07-04 06:51:09.000000000","message":"Why do we need the copy here?","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        for colname, col in data.iterkv():"},{"line_number":54,"context_line":"            result \u003d idx.apply(f)"},{"line_number":55,"context_line":"            result.name \u003d colname"},{"line_number":56,"context_line":"            dfout \u003d dfout.join(result, how\u003d\u0027outer\u0027)"},{"line_number":57,"context_line":"    if dfout.columns.size \u003d\u003d 1:"},{"line_number":58,"context_line":"        dfout \u003d dfout.ix[:, 0]"},{"line_number":59,"context_line":"    return dfout"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_7e3925f1","line":56,"updated":"2014-07-04 06:51:09.000000000","message":"This joining approach smells needlessly heavyweight. Why is it needed?","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"f67439beef55f9409789fe116f32372a1ea967f2","unresolved":false,"context_lines":[{"line_number":34,"context_line":"            return dslice.mean()"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    if isinstance(window, int):"},{"line_number":37,"context_line":"        dfout \u003d pd.rolling_mean(data, window, center\u003dcenter)"},{"line_number":38,"context_line":"    elif isinstance(window, basestring):"},{"line_number":39,"context_line":"        idx \u003d pd.Series(data.index, index\u003ddata.index)"},{"line_number":40,"context_line":"        result \u003d idx.apply(rolling_window)"}],"source_content_type":"text/x-python","patch_set":5,"id":"baada198_337fca67","line":37,"updated":"2014-07-05 21:03:34.000000000","message":"Shouldn\u0027t that be:\n\n  result \u003d pd.rolling_mean(...)\n\notherwise result would never be set in the int case.","commit_id":"30ad6d2bd60dcac0d3df4ba41014aba32f8dcd7a"}],"gnocchi/storage/__init__.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":23,"context_line":"#TODO(eglynn): figure out how to accommodate multi-valued aggregation"},{"line_number":24,"context_line":"#              methods, where there is no longer just a single aggregate"},{"line_number":25,"context_line":"#              value to be stored per-period (e.g. ohlc)"},{"line_number":26,"context_line":"AGGREGATION_TYPES \u003d (\u0027moving-average\u0027, \u0027mean\u0027, \u0027sum\u0027, \u0027last\u0027, \u0027max\u0027, \u0027min\u0027,"},{"line_number":27,"context_line":"                     \u0027std\u0027, \u0027median\u0027, \u0027first\u0027)"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_ca9b4164","line":26,"updated":"2014-07-13 23:38:24.000000000","message":"Should moving-average be hard-coded into this list, given that it may be supported or not depending on which custom-aggregation extensions are currently loaded?","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"4a7797586485cea64a9e191f70b350687055ca22","unresolved":false,"context_lines":[{"line_number":22,"context_line":""},{"line_number":23,"context_line":"# TODO(eglynn): figure out how to accommodate multi-valued aggregation"},{"line_number":24,"context_line":"#              methods, where there is no longer just a single aggregate"},{"line_number":25,"context_line":"#              value to be stored per-period (e.g. ohlc)"},{"line_number":26,"context_line":"AGGREGATION_TYPES \u003d (\u0027mean\u0027, \u0027sum\u0027, \u0027last\u0027, \u0027max\u0027, \u0027min\u0027,"},{"line_number":27,"context_line":"                     \u0027std\u0027, \u0027median\u0027, \u0027first\u0027)"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_9051c865","line":25,"updated":"2014-07-31 07:25:48.000000000","message":"Why the reformatting of the comment?\n\nA pep8 issue?","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"},{"author":{"_account_id":10683,"name":"Ana Malagon","email":"atmalagon@gmail.com","username":"atmalagon"},"change_message_id":"00289b0407c9fafa73eaf46f97a0fd42888af338","unresolved":false,"context_lines":[{"line_number":22,"context_line":""},{"line_number":23,"context_line":"# TODO(eglynn): figure out how to accommodate multi-valued aggregation"},{"line_number":24,"context_line":"#              methods, where there is no longer just a single aggregate"},{"line_number":25,"context_line":"#              value to be stored per-period (e.g. ohlc)"},{"line_number":26,"context_line":"AGGREGATION_TYPES \u003d (\u0027mean\u0027, \u0027sum\u0027, \u0027last\u0027, \u0027max\u0027, \u0027min\u0027,"},{"line_number":27,"context_line":"                     \u0027std\u0027, \u0027median\u0027, \u0027first\u0027)"},{"line_number":28,"context_line":""}],"source_content_type":"text/x-python","patch_set":14,"id":"baada198_86437d10","line":25,"in_reply_to":"baada198_9051c865","updated":"2014-08-06 15:22:57.000000000","message":"Good catch, sorry I think this is an umnecessary change. Will fix.","commit_id":"bb8671fa53fd4a2690564d39155afab194331727"}],"gnocchi/storage/influx.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":55,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"Archive \u003d collections.namedtuple(\u0027Archive\u0027, [\u0027granularity\u0027, \u0027retention\u0027])"},{"line_number":58,"context_line":"Format \u003d collections.namedtuple(\u0027Format\u0027, [\u0027timestamp\u0027, \u0027value\u0027])"},{"line_number":59,"context_line":"Point \u003d collections.namedtuple(\u0027Point\u0027, [\u0027timestamp\u0027, \u0027value\u0027])"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_1e2ae98f","line":58,"updated":"2014-07-04 06:51:09.000000000","message":"Good catch :)","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":285,"context_line":"                               for p in data[0][\u0027points\u0027]])"},{"line_number":286,"context_line":"            if data and aggregation \u003d\u003d \u0027moving-average\u0027:"},{"line_number":287,"context_line":"                vals \u003d [float(p.value) for p in points]"},{"line_number":288,"context_line":"                dates \u003d [p.timestamp for p in points]"},{"line_number":289,"context_line":"                idx \u003d pd.DatetimeIndex([_as_string(date) for date in dates])"},{"line_number":290,"context_line":"                ts \u003d pd.Series(vals,index\u003didx)"},{"line_number":291,"context_line":"                ts \u003d ts.sort_index()"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_f9b62f3d","line":288,"updated":"2014-07-04 06:51:09.000000000","message":"Dates? Maybe clearer as timestamps?","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":290,"context_line":"                ts \u003d pd.Series(vals,index\u003didx)"},{"line_number":291,"context_line":"                ts \u003d ts.sort_index()"},{"line_number":292,"context_line":"                wi \u003d str(archive.granularity)+\u0027s\u0027"},{"line_number":293,"context_line":"                mavg \u003d rolling_statistics.rolling_mean(ts,window\u003dwi)"},{"line_number":294,"context_line":"                points \u003d []"},{"line_number":295,"context_line":"                for i in range(len(mavg)):"},{"line_number":296,"context_line":"                    if mavg[i] \u003d\u003d mavg[i]:"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_de0a3125","line":293,"updated":"2014-07-04 06:51:09.000000000","message":"space after \"ts,\"","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"afb2bea1b16bed5c3bbad319c70ed8e60d273c05","unresolved":false,"context_lines":[{"line_number":296,"context_line":"                    if mavg[i] \u003d\u003d mavg[i]:"},{"line_number":297,"context_line":"                        #tests if not nan"},{"line_number":298,"context_line":"                        points.extend([Point(timestamp\u003dmavg.index[i],"},{"line_number":299,"context_line":"                                             value\u003dmavg[i])])"},{"line_number":300,"context_line":""},{"line_number":301,"context_line":"        # TODO(eglynn): returning a dict keyed by timestamp has two"},{"line_number":302,"context_line":"        # unfortunate side-effects:"}],"source_content_type":"text/x-python","patch_set":4,"id":"baada198_59547bfe","line":299,"updated":"2014-07-04 06:51:09.000000000","message":"lines 294-299 would be simpler and more pythonic as a list comprehension:\n\n  points \u003d [[Point(timestamp\u003dmavg.index[i], value\u003dmavg[i])]\n            for i in range(len(mavg))\n            if mavg[i] \u003d\u003d mavg[i]]\n\nThough TBH I don\u0027t understand the purpose of the equality comparison mavg[i] \u003d\u003d mavg[i] which seems constantly true.\n\nIs there a more intuitive way of testing for NaN?","commit_id":"0248bdf4bc739fd15836f7f482449ad12f324771"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"f67439beef55f9409789fe116f32372a1ea967f2","unresolved":false,"context_lines":[{"line_number":289,"context_line":"                                        points])"},{"line_number":290,"context_line":"                ts \u003d pd.Series(vals, index\u003didx)"},{"line_number":291,"context_line":"                ts \u003d ts.sort_index()"},{"line_number":292,"context_line":"                wi \u003d str(archive.granularity) + \u0027s\u0027"},{"line_number":293,"context_line":"                mavg \u003d rolling_statistics.rolling_mean(ts, window\u003dwi)"},{"line_number":294,"context_line":"                points \u003d []"},{"line_number":295,"context_line":"                points.extend([Point(timestamp\u003dmavg.index[i], value\u003dmavg[i])"}],"source_content_type":"text/x-python","patch_set":5,"id":"baada198_130f26e2","line":292,"updated":"2014-07-05 21:03:34.000000000","message":"I\u0027m confused by the intent of deliberately stringifying the granularity here (e.g. 60--\u003e\u002760s\u0027) and then making the rolling_mean function capable of handling *both* string and integer windows.\n\nAre you creating the need for that flexibility within rolling_mean by your approach in line 292?","commit_id":"30ad6d2bd60dcac0d3df4ba41014aba32f8dcd7a"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"28a128b5d4a3014ec6a36a40fc09da72b64bf52a","unresolved":false,"context_lines":[{"line_number":208,"context_line":"        \"\"\""},{"line_number":209,"context_line":"        if aggregation !\u003d \u0027moving-average\u0027:"},{"line_number":210,"context_line":"            aggregation \u003d InfluxStorage.NATIVE_AGGREGATES.get(aggregation,"},{"line_number":211,"context_line":"                                                              \u0027mean\u0027)"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"        def _select(archive):"},{"line_number":214,"context_line":"            params \u003d dict(name\u003d\u0027%s-data\u0027 % entity,"}],"source_content_type":"text/x-python","patch_set":7,"id":"baada198_0a49b930","line":211,"updated":"2014-07-13 23:38:24.000000000","message":"Would it be possible for *no* knowledge of \u0027moving-average\u0027 to be leaked into the customer aggregation extensions?\n\nFor example, say the API detects that the aggregation method requested in an incoming API call matches the name of a custom aggregation extension. Consider the following potential sequence:\n\n* API layer calls directly into the custom aggregation extension\n* the extension knows what actual raw aggregate it needs the storage driver to provide (e.g. maybe in some parallel universe a moving average comprised of the mean-of-means is considered OK, so the moving-average extension calls into the driver with aggregation\u003d\u0027mean\u0027 ... in another case, it may need the raw datapoints, so it would replace the given granularity with the most finegrained value possible)\n* the extension then takes the raw datapoints returned by the storage driver and uses those as input to it\u0027s own aggregation logic\n\nSo then the API layer only needs to recognize if there a custom-aggregation extension for the method requested, if so call into it and let it handle the onward call into the storage driver. If not, just call the storage driver in the usual way.","commit_id":"6fd17acc244cf80e5c88a2a7bed7ca16e3a6836d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":51,"context_line":"LOG \u003d logging.getLogger(__name__)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"Archive \u003d collections.namedtuple(\u0027Archive\u0027, [\u0027granularity\u0027, \u0027retention\u0027])"},{"line_number":54,"context_line":"Format \u003d collections.namedtuple(\u0027Format\u0027, [\u0027timestamp\u0027, \u0027value\u0027])"},{"line_number":55,"context_line":"Point \u003d collections.namedtuple(\u0027Point\u0027, [\u0027timestamp\u0027, \u0027value\u0027])"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_fe46c0a5","line":54,"updated":"2014-07-15 14:18:49.000000000","message":"Good catch but I\u0027d prefer to have it in another patch actually :)","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":206,"context_line":"        :param aggregation: The type of aggregation to retrieve."},{"line_number":207,"context_line":"        :param granularity: The per-second granularity required."},{"line_number":208,"context_line":"        \"\"\""},{"line_number":209,"context_line":"        aggregation \u003d InfluxStorage.NATIVE_AGGREGATES.get(aggregation,"},{"line_number":210,"context_line":"                                                              \u0027mean\u0027)"},{"line_number":211,"context_line":""},{"line_number":212,"context_line":"        def _select(archive):"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_7e5b9085","line":209,"updated":"2014-07-15 14:18:49.000000000","message":"no need to change this line from what I see","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":224,"context_line":"            if from_timestamp and to_timestamp:"},{"line_number":225,"context_line":"                f \u003d self._as_mircos(timeutils.parse_isotime(from_timestamp))"},{"line_number":226,"context_line":"                t \u003d self._as_mircos(timeutils.parse_isotime(to_timestamp))"},{"line_number":227,"context_line":"                # TODO(eglynn): influx doesn\u0027t support \u0027\u003e\u003d\u0027 for time comparison"},{"line_number":228,"context_line":"                #   \"Cannot use time with \u0027\u003e\u003d\u0027\""},{"line_number":229,"context_line":"                params[\u0027where\u0027] \u003d \u0027where time \u003e %du and time \u003c %du\u0027 % (f, t)"},{"line_number":230,"context_line":"            elif from_timestamp:"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_5ecfac28","line":227,"updated":"2014-07-15 14:18:49.000000000","message":"unrelated change too actually","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":241,"context_line":"            return select % params"},{"line_number":242,"context_line":""},{"line_number":243,"context_line":"        def _format(archive):"},{"line_number":244,"context_line":"            if archive.granularity \u003d\u003d 1:"},{"line_number":245,"context_line":"                value \u003d \u0027value\u0027"},{"line_number":246,"context_line":"            else:"},{"line_number":247,"context_line":"                value \u003d aggregation"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_1ef0d465","line":244,"updated":"2014-07-15 14:18:49.000000000","message":"unrelated change too","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"99b2d5a5f650953963cec8d41419056458b317d7","unresolved":false,"context_lines":[{"line_number":282,"context_line":"        #  * finer-grain datapoints of the same timestamp mask out coarser-"},{"line_number":283,"context_line":"        #    grain datapoints (unless granularity is explicitly selected)"},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"        def _as_string(timestamp):"},{"line_number":286,"context_line":"            return datetime.datetime.utcfromtimestamp(timestamp / 1000000.0)"},{"line_number":287,"context_line":""},{"line_number":288,"context_line":"        return dict((_as_string(p.timestamp), p.value) for p in points)"}],"source_content_type":"text/x-python","patch_set":10,"id":"baada198_7ee9d07d","line":285,"updated":"2014-07-15 14:18:49.000000000","message":"unrelated change","commit_id":"95cda74576fa0e0d50f5ba0a70929dd47385844f"}],"gnocchi/tests/test_aggregation.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"8d76c94fad5033b2446910264d2c2fa3930708ec","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        self.custom_aggregates \u003d dict((x.name, x.obj) for x in mgr)"},{"line_number":42,"context_line":"        self.assertIsInstance(self.custom_aggregates[\u0027moving-average\u0027],"},{"line_number":43,"context_line":"                              rolling_statistics.RollingMean)"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_compute(self):"},{"line_number":46,"context_line":"        mgr \u003d extension.ExtensionManager(namespace\u003d\u0027gnocchi.aggregates\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_29da9ae9","line":43,"updated":"2014-09-08 18:51:18.000000000","message":"This seems to making an assertion about some extension loading that\u0027s local to the test, as opposed to the actual extension loading that occurs at runtime in:\n\n  https://review.openstack.org/#/c/104415/20/gnocchi/rest/__init__.py (line 86)\n\ni.e. there could be a bug in that loading logic in the rest module, that wouldn\u0027t be caught by this test.\n\nAlso shouldn\u0027t the assertion be applied to all of the loaded custom aggregates, not just \u0027moving-average\u0027?","commit_id":"a550839a88da999ed671dc82a545ada158942512"},{"author":{"_account_id":10683,"name":"Ana Malagon","email":"atmalagon@gmail.com","username":"atmalagon"},"change_message_id":"6efa4e9e4d782c1e1dc26903780264974aa96c04","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        self.custom_aggregates \u003d dict((x.name, x.obj) for x in mgr)"},{"line_number":42,"context_line":"        self.assertIsInstance(self.custom_aggregates[\u0027moving-average\u0027],"},{"line_number":43,"context_line":"                              rolling_statistics.RollingMean)"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_compute(self):"},{"line_number":46,"context_line":"        mgr \u003d extension.ExtensionManager(namespace\u003d\u0027gnocchi.aggregates\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_9d2eb941","line":43,"in_reply_to":"fa98f980_29da9ae9","updated":"2014-09-15 15:34:06.000000000","message":"Hi Eoghan, thanks for the comments - just wanted to make sure, is the runtime extension loading implicitly tested in the custom aggregation tests of test_rest.py? \n\nhttps://review.openstack.org/#/c/104415/20/gnocchi/tests/test_rest.py (line 226)\n\nWould it be better to have this test in test_rest.py then?","commit_id":"a550839a88da999ed671dc82a545ada158942512"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"20a8d5ba9da2c3b53ddde6cc958fa8392412ff4b","unresolved":false,"context_lines":[{"line_number":40,"context_line":""},{"line_number":41,"context_line":"        self.custom_aggregates \u003d dict((x.name, x.obj) for x in mgr)"},{"line_number":42,"context_line":"        self.assertIsInstance(self.custom_aggregates[\u0027moving-average\u0027],"},{"line_number":43,"context_line":"                              rolling_statistics.RollingMean)"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    def test_compute(self):"},{"line_number":46,"context_line":"        mgr \u003d extension.ExtensionManager(namespace\u003d\u0027gnocchi.aggregates\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_4166fc2a","line":43,"in_reply_to":"fa98f980_9d2eb941","updated":"2014-09-16 13:32:04.000000000","message":"Yes, it would be implicitly test there as long as there\u0027s a test case per custom aggregation function. So yes, that would suffice.","commit_id":"a550839a88da999ed671dc82a545ada158942512"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"8d76c94fad5033b2446910264d2c2fa3930708ec","unresolved":false,"context_lines":[{"line_number":46,"context_line":"        mgr \u003d extension.ExtensionManager(namespace\u003d\u0027gnocchi.aggregates\u0027,"},{"line_number":47,"context_line":"                                         invoke_on_load\u003dTrue)"},{"line_number":48,"context_line":"        self.custom_aggregates \u003d dict((x.name, x.obj) for x in mgr)"},{"line_number":49,"context_line":"        self.storage.create_entity(\"foo\", [(1, 5)])"},{"line_number":50,"context_line":"        self.storage.add_measures(\u0027foo\u0027, ["},{"line_number":51,"context_line":"            storage.Measure(datetime.datetime(2014, 1, 1, 12, 0, 1), 69),"},{"line_number":52,"context_line":"            storage.Measure(datetime.datetime(2014, 1, 1, 12, 0, 2), 42),"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_69e4a2ac","line":49,"updated":"2014-09-08 18:51:18.000000000","message":"We probably want to test this with a range of granularities and retentions.","commit_id":"a550839a88da999ed671dc82a545ada158942512"}],"gnocchi/tests/test_rest.py":[{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"8d76c94fad5033b2446910264d2c2fa3930708ec","unresolved":false,"context_lines":[{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    def _test_get_measure_aggregation_custom(self, agg_method, expected):"},{"line_number":227,"context_line":"        result \u003d self.app.post_json(\"/v1/entity\","},{"line_number":228,"context_line":"                                    params\u003d{\"archives\": [(1, 50), (2, 10)]})"},{"line_number":229,"context_line":"        entity \u003d json.loads(result.body)"},{"line_number":230,"context_line":"        self.app.post_json(\"/v1/entity/%s/measures\" % entity[\u0027id\u0027],"},{"line_number":231,"context_line":"                           params\u003d[{\"timestamp\": \u00272013-01-01 12:00:01\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_644a0757","line":228,"updated":"2014-09-08 18:51:18.000000000","message":"It would be good to have test coverage of the case where the archives for the entity did not include 1s granularity.","commit_id":"a550839a88da999ed671dc82a545ada158942512"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"8d76c94fad5033b2446910264d2c2fa3930708ec","unresolved":false,"context_lines":[{"line_number":233,"context_line":"                                   {\"timestamp\": \u00272013-01-01 12:00:03\u0027,"},{"line_number":234,"context_line":"                                    \"value\": 12345.2},"},{"line_number":235,"context_line":"                                   {\"timestamp\": \u00272013-01-01 12:00:02\u0027,"},{"line_number":236,"context_line":"                                    \"value\": 1234.2}])"},{"line_number":237,"context_line":"        path \u003d \"/v1/entity/%s/measures?aggregation\u003d%s\u0026granularity\u003d%s\""},{"line_number":238,"context_line":"        ret \u003d self.app.get(path % (entity[\u0027id\u0027], agg_method, \u00272S\u0027))"},{"line_number":239,"context_line":"        self.assertEqual(ret.status_code, 200)"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_0473fbb1","line":236,"updated":"2014-09-08 18:51:18.000000000","message":"It would be good to have tests with a more and fewer datapoints than are implicitly requested in the custom-aggregate query.","commit_id":"a550839a88da999ed671dc82a545ada158942512"},{"author":{"_account_id":2284,"name":"Eoghan Glynn","email":"eglynn@redhat.com","username":"eglynn"},"change_message_id":"8d76c94fad5033b2446910264d2c2fa3930708ec","unresolved":false,"context_lines":[{"line_number":234,"context_line":"                                    \"value\": 12345.2},"},{"line_number":235,"context_line":"                                   {\"timestamp\": \u00272013-01-01 12:00:02\u0027,"},{"line_number":236,"context_line":"                                    \"value\": 1234.2}])"},{"line_number":237,"context_line":"        path \u003d \"/v1/entity/%s/measures?aggregation\u003d%s\u0026granularity\u003d%s\""},{"line_number":238,"context_line":"        ret \u003d self.app.get(path % (entity[\u0027id\u0027], agg_method, \u00272S\u0027))"},{"line_number":239,"context_line":"        self.assertEqual(ret.status_code, 200)"},{"line_number":240,"context_line":"        result \u003d json.loads(ret.body)"}],"source_content_type":"text/x-python","patch_set":20,"id":"fa98f980_e943326a","line":237,"updated":"2014-09-08 18:51:18.000000000","message":"It would be a good idea I think to extend this coverage to include the aggregation-function-specific additional parameters, e.g. window \u0026 cente for moving average (so as to ensure that these are passed through as expected by the API layer).","commit_id":"a550839a88da999ed671dc82a545ada158942512"}]}
