)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":4715,"name":"Angus Salkeld","email":"asalkeld@redhat.com","username":"asalkeld"},"change_message_id":"1e2a2082c0fcf93602bb2f0626837c6ad9ea7778","unresolved":false,"context_lines":[{"line_number":11,"context_line":"grammar than this EventFilter thing."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Change-Id: I3c64e3858df756d93dd5bf3c6c9651be25cd2b55"},{"line_number":14,"context_line":"Blueprint: https://blueprints.launchpad.net/ceilometer/+spec/add-event-table"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"AAAAOn%2F%2FT%2BQ%3D","line":14,"updated":"2013-05-15 00:12:16.000000000","message":"isn\u0027t it just:\n blueprint: add-event-table","commit_id":"5d7fdb3c73bacb18d3802ce025a4a66cfeb1b179"}],"ceilometer/storage/__init__.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":104,"context_line":"class EventFilter(object):"},{"line_number":105,"context_line":"    \"\"\"Properties for building an Event query."},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    :param start: UTC start datetime (mandatory)"},{"line_number":108,"context_line":"    :param end: UTC end datetime (mandatory)"},{"line_number":109,"context_line":"    :param event_name: the name of the event. None for all."},{"line_number":110,"context_line":"    :param traits: the trait filter dict, all of which are optional"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B6g%3D","line":107,"updated":"2013-05-15 16:23:07.000000000","message":"Why are the time values mandatory?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"08ee618d1d0cf3c391d7c681dc9cf8ea00c50429","unresolved":false,"context_lines":[{"line_number":104,"context_line":"class EventFilter(object):"},{"line_number":105,"context_line":"    \"\"\"Properties for building an Event query."},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    :param start: UTC start datetime (mandatory)"},{"line_number":108,"context_line":"    :param end: UTC end datetime (mandatory)"},{"line_number":109,"context_line":"    :param event_name: the name of the event. None for all."},{"line_number":110,"context_line":"    :param traits: the trait filter dict, all of which are optional"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Bvw%3D","line":107,"in_reply_to":"AAAAO3%2F%2F%2B6g%3D","updated":"2013-05-15 17:34:36.000000000","message":"otherwise we\u0027re going to get some monster queries. If that\u0027s the case I would prefer the user know they\u0027re doing something bad.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":117,"context_line":"    \"\"\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def __init__(self, start, end, event_name\u003dNone, traits\u003d[]):"},{"line_number":120,"context_line":"        self.start \u003d start"},{"line_number":121,"context_line":"        self.end \u003d end"},{"line_number":122,"context_line":"        self.event_name \u003d event_name"},{"line_number":123,"context_line":"        self.traits \u003d traits"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B6U%3D","line":120,"updated":"2013-05-15 16:23:07.000000000","message":"Should start and end be converted with _sanitize_timesamp() from SampleFilter (after moving it out of that class, of course)?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"08ee618d1d0cf3c391d7c681dc9cf8ea00c50429","unresolved":false,"context_lines":[{"line_number":117,"context_line":"    \"\"\""},{"line_number":118,"context_line":""},{"line_number":119,"context_line":"    def __init__(self, start, end, event_name\u003dNone, traits\u003d[]):"},{"line_number":120,"context_line":"        self.start \u003d start"},{"line_number":121,"context_line":"        self.end \u003d end"},{"line_number":122,"context_line":"        self.event_name \u003d event_name"},{"line_number":123,"context_line":"        self.traits \u003d traits"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2BwA%3D","line":120,"in_reply_to":"AAAAO3%2F%2F%2B6U%3D","updated":"2013-05-15 17:34:36.000000000","message":"I\u0027ll look at that ... thanks","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"5f19cfd0d8af6f8501bf057521b3af3bb817fe66","unresolved":false,"context_lines":[{"line_number":107,"context_line":"                   currently, only one trait dict is supported."},{"line_number":108,"context_line":"    \"\"\""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    def __init__(self, start, end, event_name\u003dNone, traits\u003d[]):"},{"line_number":111,"context_line":"        self.start \u003d utils.sanitize_timestamp(start)"},{"line_number":112,"context_line":"        self.end \u003d utils.sanitize_timestamp(end)"},{"line_number":113,"context_line":"        self.event_name \u003d event_name"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3RE%3D","line":110,"updated":"2013-05-21 13:53:17.000000000","message":"traits is described as a dict but the default is a list. Should it be a list of dicts? Are the keys for that dictionary \"fixed\" enough that we could define a small class (a namedtuple?) instead of using a raw dictionary? If so, maybe we could do that in a follow-up changeset.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"d275d3e34f2e8e38dd620eeae8a9ce841e54ceb9","unresolved":false,"context_lines":[{"line_number":107,"context_line":"                   currently, only one trait dict is supported."},{"line_number":108,"context_line":"    \"\"\""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    def __init__(self, start, end, event_name\u003dNone, traits\u003d[]):"},{"line_number":111,"context_line":"        self.start \u003d utils.sanitize_timestamp(start)"},{"line_number":112,"context_line":"        self.end \u003d utils.sanitize_timestamp(end)"},{"line_number":113,"context_line":"        self.event_name \u003d event_name"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3Gs%3D","line":110,"in_reply_to":"AAAAPH%2F%2F3RE%3D","updated":"2013-05-21 14:23:41.000000000","message":"Thanks ... I was back and forth on this and missed it.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":882,"name":"shengjie min","email":"minshengjie@chinacloud.com.cn","username":"shengjie-min"},"change_message_id":"ad8391382f43d5075790c49c10ce1712a669f91e","unresolved":false,"context_lines":[{"line_number":95,"context_line":"class EventFilter(object):"},{"line_number":96,"context_line":"    \"\"\"Properties for building an Event query."},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    :param start: UTC start datetime (mandatory)"},{"line_number":99,"context_line":"    :param end: UTC end datetime (mandatory)"},{"line_number":100,"context_line":"    :param event_name: the name of the event. None for all."},{"line_number":101,"context_line":"    :param traits: the trait filter dict, all of which are optional"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxsQ%3D","line":98,"updated":"2013-05-23 10:42:09.000000000","message":"Sandy, should this be aligned to SampleFilter? if start and end is not provided, you just return everything?","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"59c97fbfccc6e69c68e11f361e50172ab42c2564","unresolved":false,"context_lines":[{"line_number":95,"context_line":"class EventFilter(object):"},{"line_number":96,"context_line":"    \"\"\"Properties for building an Event query."},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"    :param start: UTC start datetime (mandatory)"},{"line_number":99,"context_line":"    :param end: UTC end datetime (mandatory)"},{"line_number":100,"context_line":"    :param event_name: the name of the event. None for all."},{"line_number":101,"context_line":"    :param traits: the trait filter dict, all of which are optional"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxPk%3D","line":98,"in_reply_to":"AAAAPH%2F%2FxsQ%3D","updated":"2013-05-23 13:55:43.000000000","message":"heh, this is turning into somewhat of a religious debate :)\n\nWith StackTach, we\u0027ve seen that all the queries/reports that cause the most problems have been related to ill-defined scopes. So I\u0027m a little paranoid about that now. It\u0027s very easy to bring down the system when these queries get out of hand.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a068a35816a21478e2961901aad1c0330042f9cf","unresolved":false,"context_lines":[{"line_number":107,"context_line":"                   currently, only one trait dict is supported."},{"line_number":108,"context_line":"    \"\"\""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    def __init__(self, start, end, event_name\u003dNone, traits\u003d{}):"},{"line_number":111,"context_line":"        self.start \u003d utils.sanitize_timestamp(start)"},{"line_number":112,"context_line":"        self.end \u003d utils.sanitize_timestamp(end)"},{"line_number":113,"context_line":"        self.event_name \u003d event_name"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2Fyis%3D","line":110,"updated":"2013-05-22 23:31:35.000000000","message":"Why are start and end required for a query?","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"36f9aa3820e683b1a1f12fd304f441f813726b56","unresolved":false,"context_lines":[{"line_number":107,"context_line":"                   currently, only one trait dict is supported."},{"line_number":108,"context_line":"    \"\"\""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    def __init__(self, start, end, event_name\u003dNone, traits\u003d{}):"},{"line_number":111,"context_line":"        self.start \u003d utils.sanitize_timestamp(start)"},{"line_number":112,"context_line":"        self.end \u003d utils.sanitize_timestamp(end)"},{"line_number":113,"context_line":"        self.event_name \u003d event_name"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FySk%3D","line":110,"in_reply_to":"AAAAPH%2F%2Fyis%3D","updated":"2013-05-23 02:12:34.000000000","message":"See impl comments.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"}],"ceilometer/storage/impl_hbase.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":513,"context_line":""},{"line_number":514,"context_line":"        :param events: a list of model.Event objects."},{"line_number":515,"context_line":"        \"\"\""},{"line_number":516,"context_line":"        pass"},{"line_number":517,"context_line":""},{"line_number":518,"context_line":"    def get_events(self, event_filter):"},{"line_number":519,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B6M%3D","line":516,"updated":"2013-05-15 16:23:07.000000000","message":"Should probably raise NotImplementedError in these methods so the user doesn\u0027t think they are working.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"cb7623752775e042de67b20f2e9cbd278274c74e","unresolved":false,"context_lines":[{"line_number":509,"context_line":"        raise NotImplementedError(\u0027Alarms not implemented\u0027)"},{"line_number":510,"context_line":""},{"line_number":511,"context_line":"    def record_events(self, events):"},{"line_number":512,"context_line":"        \"\"\"Write the events to SQL database via sqlalchemy."},{"line_number":513,"context_line":""},{"line_number":514,"context_line":"        :param events: a list of model.Event objects."},{"line_number":515,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BVE%3D","line":512,"updated":"2013-05-15 20:11:26.000000000","message":"s/SQL database via sqlalchemy/backend data store :)","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"cb7623752775e042de67b20f2e9cbd278274c74e","unresolved":false,"context_lines":[{"line_number":520,"context_line":""},{"line_number":521,"context_line":"        :param event_filter: EventFilter instance"},{"line_number":522,"context_line":"        \"\"\""},{"line_number":523,"context_line":"        return []"},{"line_number":524,"context_line":""},{"line_number":525,"context_line":""},{"line_number":526,"context_line":"###############"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BUo%3D","line":523,"updated":"2013-05-15 20:11:26.000000000","message":"why not raise NotImplementedError like above methdos?","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"}],"ceilometer/storage/impl_log.py":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":166,"context_line":""},{"line_number":167,"context_line":"        :param events: a list of model.Event objects."},{"line_number":168,"context_line":"        \"\"\""},{"line_number":169,"context_line":"        pass"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    def get_events(self, event_filter):"},{"line_number":172,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Feg%3D","line":169,"updated":"2013-05-15 12:31:44.000000000","message":"You don\u0027t actually need the pass, but that does\u0027t matter:)","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"cb7623752775e042de67b20f2e9cbd278274c74e","unresolved":false,"context_lines":[{"line_number":162,"context_line":"        \"\"\""},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"    def record_events(self, events):"},{"line_number":165,"context_line":"        \"\"\"Write the events to SQL database via sqlalchemy."},{"line_number":166,"context_line":""},{"line_number":167,"context_line":"        :param events: a list of model.Event objects."},{"line_number":168,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BUk%3D","line":165,"updated":"2013-05-15 20:11:26.000000000","message":"See previous comment about SQL -\u003e backend data store","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"}],"ceilometer/storage/impl_mongodb.py":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":556,"context_line":""},{"line_number":557,"context_line":"        :param events: a list of model.Event objects."},{"line_number":558,"context_line":"        \"\"\""},{"line_number":559,"context_line":"        pass"},{"line_number":560,"context_line":""},{"line_number":561,"context_line":"    def get_events(self, event_filter):"},{"line_number":562,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FdQ%3D","line":559,"updated":"2013-05-15 12:31:44.000000000","message":"raise NotImplementedError sounds better.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":556,"context_line":""},{"line_number":557,"context_line":"        :param events: a list of model.Event objects."},{"line_number":558,"context_line":"        \"\"\""},{"line_number":559,"context_line":"        pass"},{"line_number":560,"context_line":""},{"line_number":561,"context_line":"    def get_events(self, event_filter):"},{"line_number":562,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B6A%3D","line":559,"in_reply_to":"AAAAO3%2F%2F%2FcI%3D","updated":"2013-05-15 16:23:07.000000000","message":"Even if its optional we at least want users to know that whatever they\u0027re trying to do through the API isn\u0027t working when it calls the method that isn\u0027t implemented.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"dc6f2bd60d445ac965dab7fd100e0160dd65d1be","unresolved":false,"context_lines":[{"line_number":556,"context_line":""},{"line_number":557,"context_line":"        :param events: a list of model.Event objects."},{"line_number":558,"context_line":"        \"\"\""},{"line_number":559,"context_line":"        pass"},{"line_number":560,"context_line":""},{"line_number":561,"context_line":"    def get_events(self, event_filter):"},{"line_number":562,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FcI%3D","line":559,"in_reply_to":"AAAAO3%2F%2F%2FdQ%3D","updated":"2013-05-15 12:39:33.000000000","message":"I was going with the premise that Events were optional functionality so it shouldn\u0027t bust things. But I can easily raise.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":563,"context_line":""},{"line_number":564,"context_line":"        :param event_filter: EventFilter instance"},{"line_number":565,"context_line":"        \"\"\""},{"line_number":566,"context_line":"        return []"},{"line_number":567,"context_line":""},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"def require_map_reduce(conn):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FdM%3D","line":566,"updated":"2013-05-15 12:31:44.000000000","message":"Same here.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"cb7623752775e042de67b20f2e9cbd278274c74e","unresolved":false,"context_lines":[{"line_number":552,"context_line":"        self.db.alarm.remove({\u0027alarm_id\u0027: alarm_id})"},{"line_number":553,"context_line":""},{"line_number":554,"context_line":"    def record_events(self, events):"},{"line_number":555,"context_line":"        \"\"\"Write the events to SQL database via sqlalchemy."},{"line_number":556,"context_line":""},{"line_number":557,"context_line":"        :param events: a list of model.Event objects."},{"line_number":558,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BUc%3D","line":555,"updated":"2013-05-15 20:11:26.000000000","message":"Previous comment about SQL -\u003e backend data store.","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"}],"ceilometer/storage/impl_sqlalchemy.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5eb8dbc71405890285b3bd83655a8167a46c9058","unresolved":false,"context_lines":[{"line_number":509,"context_line":"        if not unique:"},{"line_number":510,"context_line":"            unique \u003d UniqueName(key\u003dkey)"},{"line_number":511,"context_line":"            self.session.add(unique)"},{"line_number":512,"context_line":"            self.session.flush()"},{"line_number":513,"context_line":"        return unique"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":"    def _dt_to_decimal(self, utc):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2ByE%3D","line":512,"updated":"2013-05-15 16:58:30.000000000","message":"I\u0027m really not sure why the calls to session.flush() are sprinkled all over the place in this file. In the words of the immortal Inigo Montoya, \"You keep using that word. I do not think it means what you think it means.\"\n\nI\u0027m not sure what the call above is attempting to do that would not be better done with a call to session.commit() instead of session.flush(). The only thing the flush would give you is the ability to roll back the addition of the unique name if something went wrong further down the containing transaction, but you would need to manually call session.rollback() because of the possibility of autocommit\u003dFalse (the recommended setting) sessions being used means you need to call rollback() manually to fix nested transaction scopes.\n\nI personally would replace the calls to session.flush() with session.commit(), but that\u0027s just me.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":512,"context_line":"            self.session.flush()"},{"line_number":513,"context_line":"        return unique"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":"    def _dt_to_decimal(self, utc):"},{"line_number":516,"context_line":"        \"\"\"Datetime to Decimal."},{"line_number":517,"context_line":""},{"line_number":518,"context_line":"        Some databases don\u0027t store microseconds in datetime"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FeY%3D","line":515,"updated":"2013-05-15 12:31:44.000000000","message":"This should be a staticmethod","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":512,"context_line":"            self.session.flush()"},{"line_number":513,"context_line":"        return unique"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":"    def _dt_to_decimal(self, utc):"},{"line_number":516,"context_line":"        \"\"\"Datetime to Decimal."},{"line_number":517,"context_line":""},{"line_number":518,"context_line":"        Some databases don\u0027t store microseconds in datetime"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B58%3D","line":515,"in_reply_to":"AAAAO3%2F%2F%2FeY%3D","updated":"2013-05-15 16:23:07.000000000","message":"I wonder if it would be useful to put this in the common timeutils library as a utility function?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5eb8dbc71405890285b3bd83655a8167a46c9058","unresolved":false,"context_lines":[{"line_number":516,"context_line":"        \"\"\"Datetime to Decimal."},{"line_number":517,"context_line":""},{"line_number":518,"context_line":"        Some databases don\u0027t store microseconds in datetime"},{"line_number":519,"context_line":"        so we always store as unixtime."},{"line_number":520,"context_line":"        \"\"\""},{"line_number":521,"context_line":"        decimal.getcontext().prec \u003d 30"},{"line_number":522,"context_line":"        return decimal.Decimal(str(calendar.timegm(utc.utctimetuple()))) + \\"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Bx0%3D","line":519,"updated":"2013-05-15 16:58:30.000000000","message":"s/unixtime/decimal","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":520,"context_line":"        \"\"\""},{"line_number":521,"context_line":"        decimal.getcontext().prec \u003d 30"},{"line_number":522,"context_line":"        return decimal.Decimal(str(calendar.timegm(utc.utctimetuple()))) + \\"},{"line_number":523,"context_line":"            (decimal.Decimal(str(utc.microsecond)) /"},{"line_number":524,"context_line":"             decimal.Decimal(\"1000000.0\"))"},{"line_number":525,"context_line":""},{"line_number":526,"context_line":"    def _decimal_to_dt(self, dec):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B54%3D","line":523,"updated":"2013-05-15 16:23:07.000000000","message":"If utc.microsecond is a number, you shouldn\u0027t have to convert it to a string before passing it to Decimal. If you want to do that to ensure that it doesn\u0027t have some arbitrary precision, the conversion needs to be done with a format string.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"08ee618d1d0cf3c391d7c681dc9cf8ea00c50429","unresolved":false,"context_lines":[{"line_number":520,"context_line":"        \"\"\""},{"line_number":521,"context_line":"        decimal.getcontext().prec \u003d 30"},{"line_number":522,"context_line":"        return decimal.Decimal(str(calendar.timegm(utc.utctimetuple()))) + \\"},{"line_number":523,"context_line":"            (decimal.Decimal(str(utc.microsecond)) /"},{"line_number":524,"context_line":"             decimal.Decimal(\"1000000.0\"))"},{"line_number":525,"context_line":""},{"line_number":526,"context_line":"    def _decimal_to_dt(self, dec):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2BvE%3D","line":523,"in_reply_to":"AAAAO3%2F%2F%2B54%3D","updated":"2013-05-15 17:34:36.000000000","message":"Python 2.6 needs a string ... 2.7 handles it correctly. :(","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":523,"context_line":"            (decimal.Decimal(str(utc.microsecond)) /"},{"line_number":524,"context_line":"             decimal.Decimal(\"1000000.0\"))"},{"line_number":525,"context_line":""},{"line_number":526,"context_line":"    def _decimal_to_dt(self, dec):"},{"line_number":527,"context_line":"        \"\"\"Return a datetime from Decimal unixtime format."},{"line_number":528,"context_line":"        \"\"\""},{"line_number":529,"context_line":"        if dec is None:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B5E%3D","line":526,"updated":"2013-05-15 16:23:07.000000000","message":"Also a candidate for the timeutils module. That can be done later, though.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5eb8dbc71405890285b3bd83655a8167a46c9058","unresolved":false,"context_lines":[{"line_number":530,"context_line":"            return None"},{"line_number":531,"context_line":"        integer \u003d int(dec)"},{"line_number":532,"context_line":"        micro \u003d (dec - decimal.Decimal(integer)) * decimal.Decimal(1000000)"},{"line_number":533,"context_line":"        daittyme \u003d datetime.datetime.utcfromtimestamp(integer)"},{"line_number":534,"context_line":"        return daittyme.replace(microsecond\u003dint(round(micro)))"},{"line_number":535,"context_line":""},{"line_number":536,"context_line":"    def _make_trait(self, trait_model, event):"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2ByA%3D","line":533,"updated":"2013-05-15 16:58:30.000000000","message":"daittyme? :(","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":539,"context_line":"        Doesn\u0027t flush or add to session."},{"line_number":540,"context_line":"        \"\"\""},{"line_number":541,"context_line":"        name \u003d self._get_unique_name(trait_model.name)"},{"line_number":542,"context_line":"        value_map \u003d {api_models.Trait.TEXT_TYPE: \u0027t_string\u0027,"},{"line_number":543,"context_line":"                     api_models.Trait.FLOAT_TYPE: \u0027t_float\u0027,"},{"line_number":544,"context_line":"                     api_models.Trait.INT_TYPE: \u0027t_int\u0027,"},{"line_number":545,"context_line":"                     api_models.Trait.DATETIME_TYPE: \u0027t_datetime\u0027}"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B48%3D","line":542,"updated":"2013-05-15 16:23:07.000000000","message":"This mapping could be a class attribute to avoid instantiating it in every call.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"08ee618d1d0cf3c391d7c681dc9cf8ea00c50429","unresolved":false,"context_lines":[{"line_number":539,"context_line":"        Doesn\u0027t flush or add to session."},{"line_number":540,"context_line":"        \"\"\""},{"line_number":541,"context_line":"        name \u003d self._get_unique_name(trait_model.name)"},{"line_number":542,"context_line":"        value_map \u003d {api_models.Trait.TEXT_TYPE: \u0027t_string\u0027,"},{"line_number":543,"context_line":"                     api_models.Trait.FLOAT_TYPE: \u0027t_float\u0027,"},{"line_number":544,"context_line":"                     api_models.Trait.INT_TYPE: \u0027t_int\u0027,"},{"line_number":545,"context_line":"                     api_models.Trait.DATETIME_TYPE: \u0027t_datetime\u0027}"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2BvA%3D","line":542,"in_reply_to":"AAAAO3%2F%2F%2B48%3D","updated":"2013-05-15 17:34:36.000000000","message":"good point","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":549,"context_line":"        if trait_model.dtype \u003d\u003d api_models.Trait.DATETIME_TYPE:"},{"line_number":550,"context_line":"            value \u003d self._dt_to_decimal(value)"},{"line_number":551,"context_line":"        values[value_map[trait_model.dtype]] \u003d value"},{"line_number":552,"context_line":"        return Trait(name, event, trait_model.dtype, **values)"},{"line_number":553,"context_line":""},{"line_number":554,"context_line":"    def _record_event(self, event_model):"},{"line_number":555,"context_line":"        \"\"\"Store a single Event, including related Traits."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B4Q%3D","line":552,"updated":"2013-05-15 16:23:07.000000000","message":"I wonder if this method should be a classmethod on this Trait class that it\u0027s returning.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":584,"context_line":"            events.append(self._record_event(event_model))"},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"        self.session.flush()"},{"line_number":587,"context_line":"        return events"},{"line_number":588,"context_line":""},{"line_number":589,"context_line":"    def get_events(self, event_filter):"},{"line_number":590,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B3s%3D","line":587,"updated":"2013-05-15 16:23:07.000000000","message":"It looks like this is returning the database objects created by _record_event(). Is that right? We\u0027ve been trying to keep the classes used by the storage drivers inside the driver and only return the generic model objects. That way all of the drivers are returning things with the same properties.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"08ee618d1d0cf3c391d7c681dc9cf8ea00c50429","unresolved":false,"context_lines":[{"line_number":584,"context_line":"            events.append(self._record_event(event_model))"},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"        self.session.flush()"},{"line_number":587,"context_line":"        return events"},{"line_number":588,"context_line":""},{"line_number":589,"context_line":"    def get_events(self, event_filter):"},{"line_number":590,"context_line":"        \"\"\"Return an iterable of model.Event objects."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Bus%3D","line":587,"in_reply_to":"AAAAO3%2F%2F%2B3s%3D","updated":"2013-05-15 17:34:36.000000000","message":"It was just for testing, but I can rejig this to do the right thing.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"2a67a15ef2f322e7f18a9ebe6e338b0f408572c7","unresolved":false,"context_lines":[{"line_number":599,"context_line":"            .filter(Event.when \u003e\u003d start, Event.when \u003c\u003d end)"},{"line_number":600,"context_line":""},{"line_number":601,"context_line":"        if event_filter.event_name:"},{"line_number":602,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"},{"line_number":603,"context_line":"            sub_query \u003d sub_query.filter(Event.unique_name \u003d\u003d event_name)"},{"line_number":604,"context_line":""},{"line_number":605,"context_line":"        if event_filter.traits:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FV8%3D","line":602,"updated":"2013-05-15 13:26:46.000000000","message":"Here you should try to not use _get_unique but build subquery you can use into sub_query.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"2a67a15ef2f322e7f18a9ebe6e338b0f408572c7","unresolved":false,"context_lines":[{"line_number":605,"context_line":"        if event_filter.traits:"},{"line_number":606,"context_line":"            for key, value in event_filter.traits.iteritems():"},{"line_number":607,"context_line":"                if key \u003d\u003d \u0027key\u0027:"},{"line_number":608,"context_line":"                    key \u003d self._get_unique(value)"},{"line_number":609,"context_line":"                    sub_query \u003d sub_query.filter(Trait.name \u003d\u003d key)"},{"line_number":610,"context_line":"                if key \u003d\u003d \u0027t_string\u0027:"},{"line_number":611,"context_line":"                    sub_query \u003d sub_query.filter(Trait.t_string \u003d\u003d value)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FWM%3D","line":608,"updated":"2013-05-15 13:26:46.000000000","message":"Careful about using key here, you\u0027re shadowing a variable.\n\nI think you should not use get_unique here, but rather build a subquery inside the subquery to avoid doing 2 queries","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5eb8dbc71405890285b3bd83655a8167a46c9058","unresolved":false,"context_lines":[{"line_number":620,"context_line":"        sub_query \u003d sub_query.subquery()"},{"line_number":621,"context_line":""},{"line_number":622,"context_line":"        all_data \u003d self.session.query(Trait)\\"},{"line_number":623,"context_line":"            .join(sub_query, Trait.event_id \u003d\u003d sub_query.c.id)\\"},{"line_number":624,"context_line":"            .order_by(sub_query.c.id)"},{"line_number":625,"context_line":""},{"line_number":626,"context_line":"        # Now convert the sqlalchemy objects back into Models ..."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Bxw%3D","line":623,"updated":"2013-05-15 16:58:30.000000000","message":"This is exactly correct. Nice work.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5eb8dbc71405890285b3bd83655a8167a46c9058","unresolved":false,"context_lines":[{"line_number":621,"context_line":""},{"line_number":622,"context_line":"        all_data \u003d self.session.query(Trait)\\"},{"line_number":623,"context_line":"            .join(sub_query, Trait.event_id \u003d\u003d sub_query.c.id)\\"},{"line_number":624,"context_line":"            .order_by(sub_query.c.id)"},{"line_number":625,"context_line":""},{"line_number":626,"context_line":"        # Now convert the sqlalchemy objects back into Models ..."},{"line_number":627,"context_line":"        event_models_dict \u003d {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Bxs%3D","line":624,"updated":"2013-05-15 16:58:30.000000000","message":"Remove the SQL ORDER BY entirely and just continue the sorted() call below.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"d72f61a15e5b2b9db1088452059825fdfa465f49","unresolved":false,"context_lines":[{"line_number":632,"context_line":"                event \u003d api_models.Event(trait.event.unique_name.key, when, [])"},{"line_number":633,"context_line":"                event_models_dict[trait.event_id] \u003d event"},{"line_number":634,"context_line":"            value \u003d None"},{"line_number":635,"context_line":"            if trait.t_type \u003d\u003d api_models.Trait.INT_TYPE:"},{"line_number":636,"context_line":"                value \u003d trait.t_int"},{"line_number":637,"context_line":"            if trait.t_type \u003d\u003d api_models.Trait.FLOAT_TYPE:"},{"line_number":638,"context_line":"                value \u003d trait.t_float"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2B1c%3D","line":635,"updated":"2013-05-15 16:23:07.000000000","message":"This block looks like something that could be hidden inside the Trait class.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"08ee618d1d0cf3c391d7c681dc9cf8ea00c50429","unresolved":false,"context_lines":[{"line_number":632,"context_line":"                event \u003d api_models.Event(trait.event.unique_name.key, when, [])"},{"line_number":633,"context_line":"                event_models_dict[trait.event_id] \u003d event"},{"line_number":634,"context_line":"            value \u003d None"},{"line_number":635,"context_line":"            if trait.t_type \u003d\u003d api_models.Trait.INT_TYPE:"},{"line_number":636,"context_line":"                value \u003d trait.t_int"},{"line_number":637,"context_line":"            if trait.t_type \u003d\u003d api_models.Trait.FLOAT_TYPE:"},{"line_number":638,"context_line":"                value \u003d trait.t_float"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Buk%3D","line":635,"in_reply_to":"AAAAO3%2F%2F%2B1c%3D","updated":"2013-05-15 17:34:36.000000000","message":"yeah, quite likely ... lemme see.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":644,"context_line":"            event.append_trait(trait_model)"},{"line_number":645,"context_line":""},{"line_number":646,"context_line":"        event_models \u003d event_models_dict.values()"},{"line_number":647,"context_line":"        return sorted(event_models, key\u003doperator.attrgetter(\u0027when\u0027))"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fd4%3D","line":647,"updated":"2013-05-15 12:31:44.000000000","message":"What about sorting at SQL time rather than doing it here?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"dc6f2bd60d445ac965dab7fd100e0160dd65d1be","unresolved":false,"context_lines":[{"line_number":644,"context_line":"            event.append_trait(trait_model)"},{"line_number":645,"context_line":""},{"line_number":646,"context_line":"        event_models \u003d event_models_dict.values()"},{"line_number":647,"context_line":"        return sorted(event_models, key\u003doperator.attrgetter(\u0027when\u0027))"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FcA%3D","line":647,"in_reply_to":"AAAAO3%2F%2F%2Fd4%3D","updated":"2013-05-15 12:39:33.000000000","message":"The ordering is lost when it goes in the dict (perhaps I could use an ordereddict) ... let me investigate options","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"cb7623752775e042de67b20f2e9cbd278274c74e","unresolved":false,"context_lines":[{"line_number":563,"context_line":"        for event_model in event_models:"},{"line_number":564,"context_line":"            events.append(self._record_event(event_model))"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":"        self.session.flush()"},{"line_number":567,"context_line":"        return events"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"    def get_events(self, event_filter):"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BTg%3D","line":566,"updated":"2013-05-15 20:11:26.000000000","message":"Recommend reworking the above to:\n \n events \u003d []\n with self.session.start():\n     for event_model in event_models:\n         events.append(self._record_event(event_model))\n return events","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"dfc44316969db9a173eb8aa58015c381c674ef57","unresolved":false,"context_lines":[{"line_number":563,"context_line":"        for event_model in event_models:"},{"line_number":564,"context_line":"            events.append(self._record_event(event_model))"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":"        self.session.flush()"},{"line_number":567,"context_line":"        return events"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"    def get_events(self, event_filter):"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BQc%3D","line":566,"in_reply_to":"AAAAO3%2F%2F%2BRs%3D","updated":"2013-05-15 20:27:47.000000000","message":":( Sorry, I was confusing session with connection.begin()...\n\nhttp://docs.sqlalchemy.org/en/rel_0_8/core/connections.html#using-transactions","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"35b3221c98c276865f7acdcd38703bea5f2d3e09","unresolved":false,"context_lines":[{"line_number":563,"context_line":"        for event_model in event_models:"},{"line_number":564,"context_line":"            events.append(self._record_event(event_model))"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":"        self.session.flush()"},{"line_number":567,"context_line":"        return events"},{"line_number":568,"context_line":""},{"line_number":569,"context_line":"    def get_events(self, event_filter):"}],"source_content_type":"text/x-python","patch_set":5,"id":"AAAAO3%2F%2F%2BRs%3D","line":566,"in_reply_to":"AAAAO3%2F%2F%2BTg%3D","updated":"2013-05-15 20:18:05.000000000","message":"no joy with that ... the start() method is no longer part of session.","commit_id":"22c7b9a451d339a9fa838d048560a164f4fb6ef6"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"fb7feceec018fb2aeb49e7423205fa30f5d53912","unresolved":false,"context_lines":[{"line_number":615,"context_line":"            event.append_trait(trait_model)"},{"line_number":616,"context_line":""},{"line_number":617,"context_line":"        event_models \u003d event_models_dict.values()"},{"line_number":618,"context_line":"        return sorted(event_models, key\u003doperator.attrgetter(\u0027when\u0027))"}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F9CM%3D","line":618,"updated":"2013-05-16 08:29:05.000000000","message":"Whatever you sort with SQL or Python I don\u0027t care, I\u0027d just like you add a test so we\u0027re sure that when we add support for Events in another storage backend we will have to return things sorted in the same way.","commit_id":"fde5cf6de6cf202d1bdcf0015b895245df980840"},{"author":{"_account_id":6537,"name":"gordon chung","email":"gord@live.ca","username":"chungg"},"change_message_id":"5af02ade847684fa22dac7976e6c59b52785b890","unresolved":false,"context_lines":[{"line_number":515,"context_line":"        Doesn\u0027t flush or add to session."},{"line_number":516,"context_line":"        \"\"\""},{"line_number":517,"context_line":"        name \u003d self._get_or_create_unique_name(trait_model.name)"},{"line_number":518,"context_line":"        value_map \u003d {api_models.Trait.TEXT_TYPE: \u0027t_string\u0027,"},{"line_number":519,"context_line":"                     api_models.Trait.FLOAT_TYPE: \u0027t_float\u0027,"},{"line_number":520,"context_line":"                     api_models.Trait.INT_TYPE: \u0027t_int\u0027,"},{"line_number":521,"context_line":"                     api_models.Trait.DATETIME_TYPE: \u0027t_datetime\u0027}"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F%2Bgc%3D","line":518,"updated":"2013-05-17 13:15:31.000000000","message":"did we not want to make this a class attribute?","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":6537,"name":"gordon chung","email":"gord@live.ca","username":"chungg"},"change_message_id":"5af02ade847684fa22dac7976e6c59b52785b890","unresolved":false,"context_lines":[{"line_number":587,"context_line":"                if key \u003d\u003d \u0027key\u0027:"},{"line_number":588,"context_line":"                    key \u003d self._get_unique(value)"},{"line_number":589,"context_line":"                    sub_query \u003d sub_query.filter(Trait.name \u003d\u003d key)"},{"line_number":590,"context_line":"                if key \u003d\u003d \u0027t_string\u0027:"},{"line_number":591,"context_line":"                    sub_query \u003d sub_query.filter(Trait.t_string \u003d\u003d value)"},{"line_number":592,"context_line":"                if key \u003d\u003d \u0027t_int\u0027:"},{"line_number":593,"context_line":"                    sub_query \u003d sub_query.filter(Trait.t_int \u003d\u003d value)"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F%2BeA%3D","line":590,"updated":"2013-05-17 13:15:31.000000000","message":"should these all be elif? doesn\u0027t seem like key would ever satisfy more than one of these conditions.","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"2ffa1f3cab7d7f46391ed7c674e920eec09cac3d","unresolved":false,"context_lines":[{"line_number":553,"context_line":"        self.session.flush()"},{"line_number":554,"context_line":"        return events"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"    def record_events(self, event_models):"},{"line_number":557,"context_line":"        \"\"\"Write the events to SQL database via sqlalchemy."},{"line_number":558,"context_line":""},{"line_number":559,"context_line":"        :param event_models: a list of model.Event objects."}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3ck%3D","line":556,"updated":"2013-05-21 12:14:28.000000000","message":"Do we really need an intermediate function here? You could just rename _record_events to record_events. And it doesn\u0027t seem to care about the value returned.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"d275d3e34f2e8e38dd620eeae8a9ce841e54ceb9","unresolved":false,"context_lines":[{"line_number":553,"context_line":"        self.session.flush()"},{"line_number":554,"context_line":"        return events"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"    def record_events(self, event_models):"},{"line_number":557,"context_line":"        \"\"\"Write the events to SQL database via sqlalchemy."},{"line_number":558,"context_line":""},{"line_number":559,"context_line":"        :param event_models: a list of model.Event objects."}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3Go%3D","line":556,"in_reply_to":"AAAAPH%2F%2F3ck%3D","updated":"2013-05-21 14:23:41.000000000","message":"_record_events is only for testing purposes. We didn\u0027t want to expose sqlalchemy objects to the outside callers.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"5f19cfd0d8af6f8501bf057521b3af3bb817fe66","unresolved":false,"context_lines":[{"line_number":579,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"},{"line_number":580,"context_line":"            sub_query \u003d sub_query.filter(Event.unique_name \u003d\u003d event_name)"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"        if event_filter.traits:"},{"line_number":583,"context_line":"            for key, value in event_filter.traits.iteritems():"},{"line_number":584,"context_line":"                if key \u003d\u003d \u0027key\u0027:"},{"line_number":585,"context_line":"                    key \u003d self._get_unique(value)"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3Po%3D","line":582,"updated":"2013-05-21 13:53:17.000000000","message":"The for loop will skip if traits is empty, so you don\u0027t need this test. This can be cleaned up later, though.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"d275d3e34f2e8e38dd620eeae8a9ce841e54ceb9","unresolved":false,"context_lines":[{"line_number":579,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"},{"line_number":580,"context_line":"            sub_query \u003d sub_query.filter(Event.unique_name \u003d\u003d event_name)"},{"line_number":581,"context_line":""},{"line_number":582,"context_line":"        if event_filter.traits:"},{"line_number":583,"context_line":"            for key, value in event_filter.traits.iteritems():"},{"line_number":584,"context_line":"                if key \u003d\u003d \u0027key\u0027:"},{"line_number":585,"context_line":"                    key \u003d self._get_unique(value)"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3Gg%3D","line":582,"in_reply_to":"AAAAPH%2F%2F3Po%3D","updated":"2013-05-21 14:23:41.000000000","message":"What if someone passes in a None? (paranoid)","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"5f19cfd0d8af6f8501bf057521b3af3bb817fe66","unresolved":false,"context_lines":[{"line_number":600,"context_line":"            .join(sub_query, Trait.event_id \u003d\u003d sub_query.c.id)"},{"line_number":601,"context_line":""},{"line_number":602,"context_line":"        # Now convert the sqlalchemy objects back into Models ..."},{"line_number":603,"context_line":"        event_models_dict \u003d {}"},{"line_number":604,"context_line":"        for trait in all_data.all():"},{"line_number":605,"context_line":"            event \u003d event_models_dict.get(trait.event_id)"},{"line_number":606,"context_line":"            if not event:"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3Og%3D","line":603,"updated":"2013-05-21 13:53:17.000000000","message":"We should look at whether itertools.groupby() can help optimize this some, but that can wait for an update changeset.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a068a35816a21478e2961901aad1c0330042f9cf","unresolved":false,"context_lines":[{"line_number":557,"context_line":""},{"line_number":558,"context_line":"        self.session.flush()"},{"line_number":559,"context_line":""},{"line_number":560,"context_line":"        # Update the models with the underlying DB ID."},{"line_number":561,"context_line":"        for model, actual in zip(event_models, events):"},{"line_number":562,"context_line":"            actual_event, actual_traits \u003d actual"},{"line_number":563,"context_line":"            model.id \u003d actual_event.id"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FyiU%3D","line":560,"updated":"2013-05-22 23:31:35.000000000","message":"Is this extra processing just for the tests? Could the ids be set as the objects are stored, to avoid looping over all of the inputs a second time?","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"36f9aa3820e683b1a1f12fd304f441f813726b56","unresolved":false,"context_lines":[{"line_number":557,"context_line":""},{"line_number":558,"context_line":"        self.session.flush()"},{"line_number":559,"context_line":""},{"line_number":560,"context_line":"        # Update the models with the underlying DB ID."},{"line_number":561,"context_line":"        for model, actual in zip(event_models, events):"},{"line_number":562,"context_line":"            actual_event, actual_traits \u003d actual"},{"line_number":563,"context_line":"            model.id \u003d actual_event.id"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FySw%3D","line":560,"in_reply_to":"AAAAPH%2F%2FyiU%3D","updated":"2013-05-23 02:12:34.000000000","message":"No, we\u0027re going to need these ID\u0027s anyway when we want to go the other direction and make changes to the underlying records (or use them in another query). I was just avoiding this until later.\n\n(which does bring up a whole question about the purpose of hiding the underlying orm model or not, the model could also just be a facade onto the underlying orm object vs something that has to duplicate the effort ... we should talk about this.)","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a068a35816a21478e2961901aad1c0330042f9cf","unresolved":false,"context_lines":[{"line_number":575,"context_line":"        end \u003d utils.dt_to_decimal(event_filter.end)"},{"line_number":576,"context_line":"        sub_query \u003d self.session.query(Event.id)\\"},{"line_number":577,"context_line":"            .join(Trait, Trait.event_id \u003d\u003d Event.id)\\"},{"line_number":578,"context_line":"            .filter(Event.generated \u003e\u003d start, Event.generated \u003c\u003d end)"},{"line_number":579,"context_line":""},{"line_number":580,"context_line":"        if event_filter.event_name:"},{"line_number":581,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2Fyic%3D","line":578,"updated":"2013-05-22 23:31:35.000000000","message":"This is assuming start and end are always provided. In practice that may be true, but do we have to enforce that for some reason?","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"59c97fbfccc6e69c68e11f361e50172ab42c2564","unresolved":false,"context_lines":[{"line_number":575,"context_line":"        end \u003d utils.dt_to_decimal(event_filter.end)"},{"line_number":576,"context_line":"        sub_query \u003d self.session.query(Event.id)\\"},{"line_number":577,"context_line":"            .join(Trait, Trait.event_id \u003d\u003d Event.id)\\"},{"line_number":578,"context_line":"            .filter(Event.generated \u003e\u003d start, Event.generated \u003c\u003d end)"},{"line_number":579,"context_line":""},{"line_number":580,"context_line":"        if event_filter.event_name:"},{"line_number":581,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxQU%3D","line":578,"in_reply_to":"AAAAPH%2F%2FxcE%3D","updated":"2013-05-23 13:55:43.000000000","message":"Perhaps samples should assume data ranges too?\n\n#2 can still be achieved with a bounding date range.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"a74a819d26ea50ff951b3ed5b13a37bed0e4769a","unresolved":false,"context_lines":[{"line_number":575,"context_line":"        end \u003d utils.dt_to_decimal(event_filter.end)"},{"line_number":576,"context_line":"        sub_query \u003d self.session.query(Event.id)\\"},{"line_number":577,"context_line":"            .join(Trait, Trait.event_id \u003d\u003d Event.id)\\"},{"line_number":578,"context_line":"            .filter(Event.generated \u003e\u003d start, Event.generated \u003c\u003d end)"},{"line_number":579,"context_line":""},{"line_number":580,"context_line":"        if event_filter.event_name:"},{"line_number":581,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxcE%3D","line":578,"in_reply_to":"AAAAPH%2F%2FySs%3D","updated":"2013-05-23 12:28:35.000000000","message":"I disagree:\n\n1. for consistency with our samples model\n\n\n2. because you may want to retrieve the N latest events and not specify any timestamp\n\n\nThough I\u0027ve no problem with such changes coming later.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"36f9aa3820e683b1a1f12fd304f441f813726b56","unresolved":false,"context_lines":[{"line_number":575,"context_line":"        end \u003d utils.dt_to_decimal(event_filter.end)"},{"line_number":576,"context_line":"        sub_query \u003d self.session.query(Event.id)\\"},{"line_number":577,"context_line":"            .join(Trait, Trait.event_id \u003d\u003d Event.id)\\"},{"line_number":578,"context_line":"            .filter(Event.generated \u003e\u003d start, Event.generated \u003c\u003d end)"},{"line_number":579,"context_line":""},{"line_number":580,"context_line":"        if event_filter.event_name:"},{"line_number":581,"context_line":"            event_name \u003d self._get_unique(event_filter.event_name)"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FySs%3D","line":578,"in_reply_to":"AAAAPH%2F%2Fyic%3D","updated":"2013-05-23 02:12:34.000000000","message":"Potentially runaway queries should be deliberate actions. Time is the basis for nearly everything wrt monitoring/metering.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"}],"ceilometer/storage/models.py":[{"author":{"_account_id":6537,"name":"gordon chung","email":"gord@live.ca","username":"chungg"},"change_message_id":"5af02ade847684fa22dac7976e6c59b52785b890","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    def __repr__(self):"},{"line_number":83,"context_line":"        return \"\u003cTrait: %s %d %s\u003e\" % (self.name, self.dtype, self.value)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"class Resource(Model):"},{"line_number":87,"context_line":"    \"\"\"Something for which sample data has been collected."},{"line_number":88,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F%2FgA%3D","line":85,"updated":"2013-05-17 13:15:31.000000000","message":"do we need a UniqueName model here","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"4b3b5675a381651f7ac1fb4f51f80ddf0e7c473a","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    def __repr__(self):"},{"line_number":83,"context_line":"        return \"\u003cTrait: %s %d %s\u003e\" % (self.name, self.dtype, self.value)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"class Resource(Model):"},{"line_number":87,"context_line":"    \"\"\"Something for which sample data has been collected."},{"line_number":88,"context_line":"    \"\"\""}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F6k8%3D","line":85,"in_reply_to":"AAAAPH%2F%2F%2FgA%3D","updated":"2013-05-20 13:03:41.000000000","message":"No, UniqueName is an artifact of the sqlalchemy implementation. It wouldn\u0027t be required for other db drivers.","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":882,"name":"shengjie min","email":"minshengjie@chinacloud.com.cn","username":"shengjie-min"},"change_message_id":"ad8391382f43d5075790c49c10ce1712a669f91e","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    \"\"\""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    TEXT_TYPE \u003d 1"},{"line_number":75,"context_line":"    INT_TYPE \u003d 2"},{"line_number":76,"context_line":"    FLOAT_TYPE \u003d 3"},{"line_number":77,"context_line":"    DATETIME_TYPE \u003d 4"},{"line_number":78,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxlM%3D","line":75,"updated":"2013-05-23 10:42:09.000000000","message":"representing types in an integer format, we will always have to translate it somewhere to have them readable. I am just thinking about this from pure API perspective. does it make sense just keep the as Constant string (given counter type is also in string)?","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"59c97fbfccc6e69c68e11f361e50172ab42c2564","unresolved":false,"context_lines":[{"line_number":72,"context_line":"    \"\"\""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    TEXT_TYPE \u003d 1"},{"line_number":75,"context_line":"    INT_TYPE \u003d 2"},{"line_number":76,"context_line":"    FLOAT_TYPE \u003d 3"},{"line_number":77,"context_line":"    DATETIME_TYPE \u003d 4"},{"line_number":78,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxQY%3D","line":75,"in_reply_to":"AAAAPH%2F%2FxlM%3D","updated":"2013-05-23 13:55:43.000000000","message":"The outside world will never see the data type, it\u0027s just an implementation detail for the sql schema. The caller will only see \"value\" in its native format.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"}],"ceilometer/storage/sqlalchemy/migrate_repo/versions/008_add_events.py":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"fb7feceec018fb2aeb49e7423205fa30f5d53912","unresolved":false,"context_lines":[{"line_number":27,"context_line":"event \u003d Table("},{"line_number":28,"context_line":"    \u0027event\u0027, meta,"},{"line_number":29,"context_line":"    Column(\u0027id\u0027, Integer, primary_key\u003dTrue),"},{"line_number":30,"context_line":"    Column(\u0027when\u0027, Float(asdecimal\u003dTrue), index\u003dTrue),"},{"line_number":31,"context_line":"    Column(\u0027unique_name_id\u0027, Integer, ForeignKey(\u0027unique_name.id\u0027))"},{"line_number":32,"context_line":")"},{"line_number":33,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"AAAAO3%2F%2F9Cw%3D","line":30,"updated":"2013-05-16 08:29:05.000000000","message":"This might be a nitpick, but could we use something more explicit than \u0027when\u0027, like \u0027recorded_on\u0027 or something. I\u0027d just like to emphasize that we store the time we received the event at, and not the time the event was generated or sent.","commit_id":"fde5cf6de6cf202d1bdcf0015b895245df980840"}],"ceilometer/storage/sqlalchemy/models.py":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    matching_metadata \u003d Column(JSONEncodedDict)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class UniqueName(Base):"},{"line_number":181,"context_line":"    \"\"\"Key names should only be stored once."},{"line_number":182,"context_line":"    \"\"\""},{"line_number":183,"context_line":"    __tablename__ \u003d \u0027unique_name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fco%3D","line":180,"updated":"2013-05-15 12:31:44.000000000","message":"I don\u0027t get the point of this table. It seems to me you could use a string column directly everywhere. Having Event and Trait backref\u0027ing here seems useless, or I miss something?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"9effe155f54263c1a81651d7ac87f8f3fb9ce1d6","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    matching_metadata \u003d Column(JSONEncodedDict)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class UniqueName(Base):"},{"line_number":181,"context_line":"    \"\"\"Key names should only be stored once."},{"line_number":182,"context_line":"    \"\"\""},{"line_number":183,"context_line":"    __tablename__ \u003d \u0027unique_name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F9CA%3D","line":180,"in_reply_to":"AAAAO3%2F%2F%2BxM%3D","updated":"2013-05-16 08:30:25.000000000","message":"I\u0027m no SQLAlchemy export, but if you look at _get_unique_name in impl_sqlalchemy, it uses .first() and if I read correctly, the documentation says \"Calling first() results in an execution of the underlying query.\"\n\nSo to me there\u0027s two queries running most of the time.\n\nOr do I get something wrong?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"5eb8dbc71405890285b3bd83655a8167a46c9058","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    matching_metadata \u003d Column(JSONEncodedDict)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class UniqueName(Base):"},{"line_number":181,"context_line":"    \"\"\"Key names should only be stored once."},{"line_number":182,"context_line":"    \"\"\""},{"line_number":183,"context_line":"    __tablename__ \u003d \u0027unique_name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2BxM%3D","line":180,"in_reply_to":"AAAAO3%2F%2F%2FVY%3D","updated":"2013-05-15 16:58:30.000000000","message":"It\u0027s not two SQL calls to retrieve the UniqueName.id for a request. It\u0027s a single record in a join table. The performance benefits of reducing the index record size -- and subsequently being able to search orders of magnitude more rows in the index for the same amount of base records -- vastly outweighs the cost of the join to the UniqueName model table.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"2a67a15ef2f322e7f18a9ebe6e338b0f408572c7","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    matching_metadata \u003d Column(JSONEncodedDict)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class UniqueName(Base):"},{"line_number":181,"context_line":"    \"\"\"Key names should only be stored once."},{"line_number":182,"context_line":"    \"\"\""},{"line_number":183,"context_line":"    __tablename__ \u003d \u0027unique_name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FVY%3D","line":180,"in_reply_to":"AAAAO3%2F%2F%2Fbg%3D","updated":"2013-05-15 13:26:46.000000000","message":"Fair enough, but in this case you should also avoids doing 2 SQL queries each time you need to retrieve the UniqueName.id for a request, otherwise that also can be a nice performance killer on its own.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"dc6f2bd60d445ac965dab7fd100e0160dd65d1be","unresolved":false,"context_lines":[{"line_number":177,"context_line":"    matching_metadata \u003d Column(JSONEncodedDict)"},{"line_number":178,"context_line":""},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"class UniqueName(Base):"},{"line_number":181,"context_line":"    \"\"\"Key names should only be stored once."},{"line_number":182,"context_line":"    \"\"\""},{"line_number":183,"context_line":"    __tablename__ \u003d \u0027unique_name\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fbg%3D","line":180,"in_reply_to":"AAAAO3%2F%2F%2Fco%3D","updated":"2013-05-15 12:39:33.000000000","message":"When you\u0027re bringing back lots of rows, duplicating the string is a big performance hit. This way we only bring back the id. The Event names and Trait names are largely invariant, but occur many many times.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":6537,"name":"gordon chung","email":"gord@live.ca","username":"chungg"},"change_message_id":"5af02ade847684fa22dac7976e6c59b52785b890","unresolved":false,"context_lines":[{"line_number":183,"context_line":"    \"\"\"Key names should only be stored once."},{"line_number":184,"context_line":"    \"\"\""},{"line_number":185,"context_line":"    __tablename__ \u003d \u0027unique_name\u0027"},{"line_number":186,"context_line":"    __table_args__ \u003d {\u0027mysql_engine\u0027: \u0027InnoDB\u0027}"},{"line_number":187,"context_line":"    id \u003d Column(Integer, primary_key\u003dTrue)"},{"line_number":188,"context_line":"    key \u003d Column(String(32), index\u003dTrue, unique\u003dTrue)"},{"line_number":189,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F%2Bbg%3D","line":186,"updated":"2013-05-17 13:15:31.000000000","message":"is there a reason we use this and not the table_args() defined above?","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":6537,"name":"gordon chung","email":"gord@live.ca","username":"chungg"},"change_message_id":"5af02ade847684fa22dac7976e6c59b52785b890","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        return None"},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"    def __repr__(self):"},{"line_number":258,"context_line":"        return \"\u003cTrait(%s) %d\u003d%s/%s/%s/%s on %s\u003e\" % (self.name, self.t_type,"},{"line_number":259,"context_line":"               self.t_string, self.t_float, self.t_int, self.t_datetime,"},{"line_number":260,"context_line":"               self.event)"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F%2FTA%3D","line":258,"updated":"2013-05-17 13:15:31.000000000","message":"don\u0027t know if this matters but self.t_int is match to %s here","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"4b3b5675a381651f7ac1fb4f51f80ddf0e7c473a","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        return None"},{"line_number":256,"context_line":""},{"line_number":257,"context_line":"    def __repr__(self):"},{"line_number":258,"context_line":"        return \"\u003cTrait(%s) %d\u003d%s/%s/%s/%s on %s\u003e\" % (self.name, self.t_type,"},{"line_number":259,"context_line":"               self.t_string, self.t_float, self.t_int, self.t_datetime,"},{"line_number":260,"context_line":"               self.event)"}],"source_content_type":"text/x-python","patch_set":8,"id":"AAAAPH%2F%2F6kU%3D","line":258,"in_reply_to":"AAAAPH%2F%2F%2FTA%3D","updated":"2013-05-20 13:03:41.000000000","message":"I wanted it deal with None, which is the majority of the cases.","commit_id":"95bc327b540da5c90ca08c7500d7717c49b6118a"},{"author":{"_account_id":4491,"name":"Lianhao Lu","email":"llh_misc@outlook.com","username":"lianhao-lu"},"change_message_id":"a07ab0b3b161c2eee577bf6748d8a95a3294a254","unresolved":false,"context_lines":[{"line_number":199,"context_line":"    generated \u003d Column(Float(asdecimal\u003dTrue), index\u003dTrue)"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"    unique_name_id \u003d Column(Integer, ForeignKey(\u0027unique_name.id\u0027))"},{"line_number":202,"context_line":"    unique_name \u003d relationship(\"UniqueName\", backref\u003dbackref(\u0027unique_name\u0027,"},{"line_number":203,"context_line":"                               order_by\u003did))"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"    def __init__(self, event, generated):"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FvQI%3D","line":202,"updated":"2013-05-24 02:43:32.000000000","message":"the backref name \u0027unique_name\u0027 is misleading to me. how about:\nbackref\u003dbackref(\u0027events\u0027, order_by\u003did)","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":4491,"name":"Lianhao Lu","email":"llh_misc@outlook.com","username":"lianhao-lu"},"change_message_id":"a07ab0b3b161c2eee577bf6748d8a95a3294a254","unresolved":false,"context_lines":[{"line_number":216,"context_line":"    id \u003d Column(Integer, primary_key\u003dTrue)"},{"line_number":217,"context_line":""},{"line_number":218,"context_line":"    name_id \u003d Column(Integer, ForeignKey(\u0027unique_name.id\u0027))"},{"line_number":219,"context_line":"    name \u003d relationship(\"UniqueName\", backref\u003dbackref(\u0027name\u0027, order_by\u003did))"},{"line_number":220,"context_line":""},{"line_number":221,"context_line":"    t_type \u003d Column(Integer, index\u003dTrue)"},{"line_number":222,"context_line":"    t_string \u003d Column(String(32), nullable\u003dTrue, default\u003dNone, index\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FvP8%3D","line":219,"updated":"2013-05-24 02:43:32.000000000","message":"the same comment as line 202, how about using \u0027traits\u0027 as back reference name","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":4491,"name":"Lianhao Lu","email":"llh_misc@outlook.com","username":"lianhao-lu"},"change_message_id":"a07ab0b3b161c2eee577bf6748d8a95a3294a254","unresolved":false,"context_lines":[{"line_number":226,"context_line":"                        index\u003dTrue)"},{"line_number":227,"context_line":""},{"line_number":228,"context_line":"    event_id \u003d Column(Integer, ForeignKey(\u0027event.id\u0027))"},{"line_number":229,"context_line":"    event \u003d relationship(\"Event\", backref\u003dbackref(\u0027event\u0027, order_by\u003did))"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"    _value_map \u003d {api_models.Trait.TEXT_TYPE: \u0027t_string\u0027,"},{"line_number":232,"context_line":"                  api_models.Trait.FLOAT_TYPE: \u0027t_float\u0027,"}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FvPw%3D","line":229,"updated":"2013-05-24 02:43:32.000000000","message":"same comment as line 202","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"}],"ceilometer/utils.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"5f19cfd0d8af6f8501bf057521b3af3bb817fe66","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    return cache_info[\u0027data\u0027]"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"def dt_to_decimal(utc):"},{"line_number":52,"context_line":"    \"\"\"Datetime to Decimal."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    Some databases don\u0027t store microseconds in datetime"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3QY%3D","line":51,"updated":"2013-05-21 13:53:17.000000000","message":"These helper functions are good here for now, but we should move them to openstack.common.dateutils after this changeset is accepted. If they\u0027re only used for the database, we could also create a new column type class and put that in the openstack.common.db package.","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"d275d3e34f2e8e38dd620eeae8a9ce841e54ceb9","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    return cache_info[\u0027data\u0027]"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"def dt_to_decimal(utc):"},{"line_number":52,"context_line":"    \"\"\"Datetime to Decimal."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"    Some databases don\u0027t store microseconds in datetime"}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3GE%3D","line":51,"in_reply_to":"AAAAPH%2F%2F3QY%3D","updated":"2013-05-21 14:23:41.000000000","message":"Or we could say you need to use a proper version of mysql that supports milliseconds :)","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"}],"tests/storage/base.py":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"2ffa1f3cab7d7f46391ed7c674e920eec09cac3d","unresolved":false,"context_lines":[{"line_number":803,"context_line":"            self.assertEquals(4, len(events[i].traits))"},{"line_number":804,"context_line":"            # Ensure sorted results ..."},{"line_number":805,"context_line":"            if start_time is not None:"},{"line_number":806,"context_line":"                # Python 2.6 has no assertLess :("},{"line_number":807,"context_line":"                self.assertTrue(start_time \u003c events[i].generated)"},{"line_number":808,"context_line":"            start_time \u003d events[i].generated"},{"line_number":809,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"AAAAPH%2F%2F3cA%3D","line":806,"updated":"2013-05-21 12:14:28.000000000","message":"It has if you use unittest2 instead of unittest as the test base class. We already do that in some places. :)","commit_id":"b165a3c57c4188a4b714067863b2a9b70e58ccfb"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"a74a819d26ea50ff951b3ed5b13a37bed0e4769a","unresolved":false,"context_lines":[{"line_number":789,"context_line":"            self.assertEquals(4, len(events[i].traits))"},{"line_number":790,"context_line":"            # Ensure sorted results ..."},{"line_number":791,"context_line":"            if start_time is not None:"},{"line_number":792,"context_line":"                # Python 2.6 has no assertLess :("},{"line_number":793,"context_line":"                self.assertTrue(start_time \u003c events[i].generated)"},{"line_number":794,"context_line":"            start_time \u003d events[i].generated"},{"line_number":795,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxcA%3D","line":792,"updated":"2013-05-23 12:28:35.000000000","message":"Still not true, especially since we use testtools which has it.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"59c97fbfccc6e69c68e11f361e50172ab42c2564","unresolved":false,"context_lines":[{"line_number":789,"context_line":"            self.assertEquals(4, len(events[i].traits))"},{"line_number":790,"context_line":"            # Ensure sorted results ..."},{"line_number":791,"context_line":"            if start_time is not None:"},{"line_number":792,"context_line":"                # Python 2.6 has no assertLess :("},{"line_number":793,"context_line":"                self.assertTrue(start_time \u003c events[i].generated)"},{"line_number":794,"context_line":"            start_time \u003d events[i].generated"},{"line_number":795,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"AAAAPH%2F%2FxQM%3D","line":792,"in_reply_to":"AAAAPH%2F%2FxcA%3D","updated":"2013-05-23 13:55:43.000000000","message":"Sorry, I missed this fix up. Agree completely. I\u0027ll fix this up next time I\u0027m in here.","commit_id":"2b153893177f500e7fc2fe052571468d08521e09"}],"tests/storage/test_impl_sqlalchemy.py":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    pass"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class EventTest(base.EventTestBase, SQLAlchemyEngineTestBase):"},{"line_number":75,"context_line":"    def test_unique_exists(self):"},{"line_number":76,"context_line":"        u1 \u003d self.conn._get_unique_name(\"foo\")"},{"line_number":77,"context_line":"        self.assertTrue(u1.id \u003e\u003d 0)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fdw%3D","line":74,"updated":"2013-05-15 12:31:44.000000000","message":"It seems to me that the content of this should be put into base.EventTestBase, no?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"97afe5fcca970f062eb8bb6f247a15077ce2bfbe","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    pass"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class EventTest(base.EventTestBase, SQLAlchemyEngineTestBase):"},{"line_number":75,"context_line":"    def test_unique_exists(self):"},{"line_number":76,"context_line":"        u1 \u003d self.conn._get_unique_name(\"foo\")"},{"line_number":77,"context_line":"        self.assertTrue(u1.id \u003e\u003d 0)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FUQ%3D","line":74,"in_reply_to":"AAAAO3%2F%2F%2FbI%3D","updated":"2013-05-15 13:37:04.000000000","message":"No. For example, take a look at how we test metadata or alarms. The tests are in base.py, but we only run tests on MongoDB. You can do the same here.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"dc6f2bd60d445ac965dab7fd100e0160dd65d1be","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    pass"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":""},{"line_number":74,"context_line":"class EventTest(base.EventTestBase, SQLAlchemyEngineTestBase):"},{"line_number":75,"context_line":"    def test_unique_exists(self):"},{"line_number":76,"context_line":"        u1 \u003d self.conn._get_unique_name(\"foo\")"},{"line_number":77,"context_line":"        self.assertTrue(u1.id \u003e\u003d 0)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2FbI%3D","line":74,"in_reply_to":"AAAAO3%2F%2F%2Fdw%3D","updated":"2013-05-15 12:39:33.000000000","message":"Events are optional until they are supported by all the other db drivers. If they went into base all the drivers would need to support it, no?","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":170,"context_line":"        self.assertEqual(actual_datetime, expected_datetime)"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":""},{"line_number":173,"context_line":"class GetEventTest(base.EventTestBase):"},{"line_number":174,"context_line":"    \"\"\"Event tests are SQLAlchemy specific only for now. Once there is"},{"line_number":175,"context_line":"    better support in the other drivers, we can move these tests to"},{"line_number":176,"context_line":"    EventTestBase."}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fdo%3D","line":173,"updated":"2013-05-15 12:31:44.000000000","message":"Same as above.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"e2cbd3ff02eda2188e4f06054a2fc67bf39e27cf","unresolved":false,"context_lines":[{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def test_simple_get(self):"},{"line_number":208,"context_line":"        event_filter \u003d storage.EventFilter(self.start, self.end)"},{"line_number":209,"context_line":"        events \u003d self.conn.get_events(event_filter)"},{"line_number":210,"context_line":"        self.assertEquals(3, len(events))"},{"line_number":211,"context_line":"        for i, name in enumerate([\"Foo\", \"Bar\", \"Zoo\"]):"},{"line_number":212,"context_line":"            self.assertEquals(events[i].event_name, name)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fdg%3D","line":209,"updated":"2013-05-15 12:31:44.000000000","message":"You should check that the events are sorted since you expect all events to be stored for all drivers.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"},{"author":{"_account_id":688,"name":"Sandy Walsh","email":"sandy.walsh@rackspace.com","username":"sandy-walsh"},"change_message_id":"dc6f2bd60d445ac965dab7fd100e0160dd65d1be","unresolved":false,"context_lines":[{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def test_simple_get(self):"},{"line_number":208,"context_line":"        event_filter \u003d storage.EventFilter(self.start, self.end)"},{"line_number":209,"context_line":"        events \u003d self.conn.get_events(event_filter)"},{"line_number":210,"context_line":"        self.assertEquals(3, len(events))"},{"line_number":211,"context_line":"        for i, name in enumerate([\"Foo\", \"Bar\", \"Zoo\"]):"},{"line_number":212,"context_line":"            self.assertEquals(events[i].event_name, name)"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAAO3%2F%2F%2Fa8%3D","line":209,"in_reply_to":"AAAAO3%2F%2F%2Fdg%3D","updated":"2013-05-15 12:39:33.000000000","message":"Good point.","commit_id":"23cdf0c3c756dd200c7cb26e38efc97e746c14a7"}]}
