)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Stas Maksimov \u003cStanislav_M@dell.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2013-02-13 14:44:02 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"hbase-storage-backend blueprint, initial commit"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: Id3e7ec01434b1be30cce4f91b39461fc389a000f"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"AAAAM3%2F%2B8ws%3D","line":7,"updated":"2013-02-13 17:02:38.000000000","message":"You\u0027ll need a more descriptive commit message.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Stas Maksimov \u003cStanislav_M@dell.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2013-02-13 14:44:02 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"hbase-storage-backend blueprint, initial commit"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: Id3e7ec01434b1be30cce4f91b39461fc389a000f"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"AAAAM3%2F%2B6e8%3D","line":7,"in_reply_to":"AAAAM3%2F%2B8ws%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"}],"ceilometer/storage/impl_hbase.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":16,"context_line":"# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"line_number":17,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":18,"context_line":"# under the License."},{"line_number":19,"context_line":"\"\"\"HBase storage backend"},{"line_number":20,"context_line":"\"\"\""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"from ceilometer.openstack.common import log"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4JE%3D","line":19,"updated":"2013-02-15 18:53:07.000000000","message":"Which version of hbase is supported by this module?","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"4c236fd81fbae574a9905fa60caefc4317aa0665","unresolved":false,"context_lines":[{"line_number":16,"context_line":"# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"line_number":17,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":18,"context_line":"# under the License."},{"line_number":19,"context_line":"\"\"\"HBase storage backend"},{"line_number":20,"context_line":"\"\"\""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"from ceilometer.openstack.common import log"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4Hg%3D","line":19,"in_reply_to":"AAAAM3%2F%2B4JE%3D","updated":"2013-02-15 19:02:41.000000000","message":"Will provide that along with information on various assumptions we have made in this implementation (client-side aggregations, etc).","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"def reverse_timestamp(dt):"},{"line_number":74,"context_line":"    return 0x7fffffffffffffff - int(dt.strftime(\"%s\"))"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"def make_query(user\u003dNone, project\u003dNone, meter\u003dNone,"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8wo%3D","line":74,"updated":"2013-02-13 17:02:38.000000000","message":"This looks tricky. Could you provide a docstring explaining what it is doing, and what it is for?","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":71,"context_line":""},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"def reverse_timestamp(dt):"},{"line_number":74,"context_line":"    return 0x7fffffffffffffff - int(dt.strftime(\"%s\"))"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"def make_query(user\u003dNone, project\u003dNone, meter\u003dNone,"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6jw%3D","line":74,"in_reply_to":"AAAAM3%2F%2B8wo%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        opts \u003d {}"},{"line_number":197,"context_line":"        result \u003d urlparse(url)"},{"line_number":198,"context_line":"        opts[\u0027dbtype\u0027] \u003d result.scheme"},{"line_number":199,"context_line":"        opts[\u0027dbname\u0027] \u003d result.path.replace(\u0027/\u0027, \u0027\u0027)"},{"line_number":200,"context_line":"        netloc_match \u003d re.match(r\u0027(?:(\\w+:\\w+)@)?(.*)\u0027, result.netloc)"},{"line_number":201,"context_line":"        auth \u003d netloc_match.group(1)"},{"line_number":202,"context_line":"        netloc \u003d netloc_match.group(2)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8wI%3D","line":199,"updated":"2013-02-13 17:02:38.000000000","message":"Stripping the / entirely seems likely to surprise the end user. Are there any other punctuation characters that are allowed in database names? Maybe we could replace \"/\" with \"-\"?","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        opts \u003d {}"},{"line_number":197,"context_line":"        result \u003d urlparse(url)"},{"line_number":198,"context_line":"        opts[\u0027dbtype\u0027] \u003d result.scheme"},{"line_number":199,"context_line":"        opts[\u0027dbname\u0027] \u003d result.path.replace(\u0027/\u0027, \u0027\u0027)"},{"line_number":200,"context_line":"        netloc_match \u003d re.match(r\u0027(?:(\\w+:\\w+)@)?(.*)\u0027, result.netloc)"},{"line_number":201,"context_line":"        auth \u003d netloc_match.group(1)"},{"line_number":202,"context_line":"        netloc \u003d netloc_match.group(2)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6jk%3D","line":199,"in_reply_to":"AAAAM3%2F%2B8wI%3D","updated":"2013-02-14 17:05:21.000000000","message":"This was copied verbatim from the mongodb driver, and looking back at my code now I can see that HBase doesn\u0027t even use the dbname part :-) I\u0027ll remove this and whatever else that isn\u0027t required.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":197,"context_line":"        result \u003d urlparse(url)"},{"line_number":198,"context_line":"        opts[\u0027dbtype\u0027] \u003d result.scheme"},{"line_number":199,"context_line":"        opts[\u0027dbname\u0027] \u003d result.path.replace(\u0027/\u0027, \u0027\u0027)"},{"line_number":200,"context_line":"        netloc_match \u003d re.match(r\u0027(?:(\\w+:\\w+)@)?(.*)\u0027, result.netloc)"},{"line_number":201,"context_line":"        auth \u003d netloc_match.group(1)"},{"line_number":202,"context_line":"        netloc \u003d netloc_match.group(2)"},{"line_number":203,"context_line":"        if auth:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8v4%3D","line":200,"updated":"2013-02-13 17:02:38.000000000","message":"I think you can just get the username and password right from the urlparse() result. http://docs.python.org/2/library/urlparse.html","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":197,"context_line":"        result \u003d urlparse(url)"},{"line_number":198,"context_line":"        opts[\u0027dbtype\u0027] \u003d result.scheme"},{"line_number":199,"context_line":"        opts[\u0027dbname\u0027] \u003d result.path.replace(\u0027/\u0027, \u0027\u0027)"},{"line_number":200,"context_line":"        netloc_match \u003d re.match(r\u0027(?:(\\w+:\\w+)@)?(.*)\u0027, result.netloc)"},{"line_number":201,"context_line":"        auth \u003d netloc_match.group(1)"},{"line_number":202,"context_line":"        netloc \u003d netloc_match.group(2)"},{"line_number":203,"context_line":"        if auth:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4yk%3D","line":200,"in_reply_to":"AAAAM3%2F%2B6jE%3D","updated":"2013-02-15 18:53:07.000000000","message":"Sheesh, I wrote that?! :-)\n\nIt\u0027s likely I was trying to make it backwards compatible for Python 2.6.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":197,"context_line":"        result \u003d urlparse(url)"},{"line_number":198,"context_line":"        opts[\u0027dbtype\u0027] \u003d result.scheme"},{"line_number":199,"context_line":"        opts[\u0027dbname\u0027] \u003d result.path.replace(\u0027/\u0027, \u0027\u0027)"},{"line_number":200,"context_line":"        netloc_match \u003d re.match(r\u0027(?:(\\w+:\\w+)@)?(.*)\u0027, result.netloc)"},{"line_number":201,"context_line":"        auth \u003d netloc_match.group(1)"},{"line_number":202,"context_line":"        netloc \u003d netloc_match.group(2)"},{"line_number":203,"context_line":"        if auth:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6jE%3D","line":200,"in_reply_to":"AAAAM3%2F%2B8v4%3D","updated":"2013-02-14 17:05:21.000000000","message":"Same here, not sure we even need them. Will double-check.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":207,"context_line":"        else:"},{"line_number":208,"context_line":"            opts[\u0027host\u0027] \u003d netloc"},{"line_number":209,"context_line":"            port \u003d 27017"},{"line_number":210,"context_line":"        opts[\u0027port\u0027] \u003d port and int(port) or 27017"},{"line_number":211,"context_line":"        return opts"},{"line_number":212,"context_line":""},{"line_number":213,"context_line":"    def record_metering_data(self, data):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6i8%3D","line":210,"updated":"2013-02-14 17:05:21.000000000","message":"This is wrong. Default port should be 9090 :-)","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":222,"context_line":"            user \u003d self.user.row(data[\u0027user_id\u0027])"},{"line_number":223,"context_line":"            sources \u003d []"},{"line_number":224,"context_line":"            try:"},{"line_number":225,"context_line":"                sources \u003d user[\u0027f:source\u0027].strip(\"|\").split(\"|\")"},{"line_number":226,"context_line":"                if not filter(lambda x: x \u003d\u003d data[\u0027source\u0027], sources):"},{"line_number":227,"context_line":"                    sources.append(data[\u0027source\u0027])"},{"line_number":228,"context_line":"            except KeyError:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8vs%3D","line":225,"updated":"2013-02-13 17:02:38.000000000","message":"If you make sources a set() instance (by wrapping the value you\u0027re setting it to now), you don\u0027t have to do the check on the next line. You can just say sources.add(data[\u0027source\u0027]).","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"fc2f8ecab390236e09614591368a6c429dcdea18","unresolved":false,"context_lines":[{"line_number":222,"context_line":"            user \u003d self.user.row(data[\u0027user_id\u0027])"},{"line_number":223,"context_line":"            sources \u003d []"},{"line_number":224,"context_line":"            try:"},{"line_number":225,"context_line":"                sources \u003d user[\u0027f:source\u0027].strip(\"|\").split(\"|\")"},{"line_number":226,"context_line":"                if not filter(lambda x: x \u003d\u003d data[\u0027source\u0027], sources):"},{"line_number":227,"context_line":"                    sources.append(data[\u0027source\u0027])"},{"line_number":228,"context_line":"            except KeyError:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4Mg%3D","line":225,"in_reply_to":"AAAAM3%2F%2B8vs%3D","updated":"2013-02-15 18:39:20.000000000","message":"I handled it slightly differently, I still check if the value is in the dict, and if it isn\u0027t I don\u0027t even do the HBase put - this is a much bigger saving. Same for project and resource below.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":228,"context_line":"            except KeyError:"},{"line_number":229,"context_line":"                sources \u003d [data[\u0027source\u0027]]"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"            user[\u0027f:source\u0027] \u003d \"|%s|\" % \"|\".join(str(n) for n in sources)"},{"line_number":232,"context_line":"            self.user.put(data[\u0027user_id\u0027], user)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"        project \u003d self.project.row(data[\u0027project_id\u0027])"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8vc%3D","line":231,"updated":"2013-02-13 17:02:38.000000000","message":"Does it make sense to sort sources before building this string, to avoid extraneous updates?\n\nI\u0027m not sure if it safe to assume that names of sources, resources, etc. won\u0027t have the \"|\" in them. Is that an hbase formatting requirement? Would it make sense to use a JSON encoded list here instead?","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"4c236fd81fbae574a9905fa60caefc4317aa0665","unresolved":false,"context_lines":[{"line_number":228,"context_line":"            except KeyError:"},{"line_number":229,"context_line":"                sources \u003d [data[\u0027source\u0027]]"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"            user[\u0027f:source\u0027] \u003d \"|%s|\" % \"|\".join(str(n) for n in sources)"},{"line_number":232,"context_line":"            self.user.put(data[\u0027user_id\u0027], user)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"        project \u003d self.project.row(data[\u0027project_id\u0027])"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4H8%3D","line":231,"in_reply_to":"AAAAM3%2F%2B4x4%3D","updated":"2013-02-15 19:02:41.000000000","message":"HBase is not smart enough for this, it will update regardless, this is why I will handle this myself.\n\nEscaped double quotes won\u0027t work as I tried to demonstrate in my example above. Non-printing characters is a good idea, I\u0027ll investigate. On the other hand, we don\u0027t support metaqueries yet, and I\u0027m still not sure how to do that - this is the same problem of matching a JSON with a substring. If I\u0027ll find a good way, I\u0027ll get back to using JSON everywhere.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":228,"context_line":"            except KeyError:"},{"line_number":229,"context_line":"                sources \u003d [data[\u0027source\u0027]]"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"            user[\u0027f:source\u0027] \u003d \"|%s|\" % \"|\".join(str(n) for n in sources)"},{"line_number":232,"context_line":"            self.user.put(data[\u0027user_id\u0027], user)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"        project \u003d self.project.row(data[\u0027project_id\u0027])"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4x4%3D","line":231,"in_reply_to":"AAAAM3%2F%2B6h0%3D","updated":"2013-02-15 18:53:07.000000000","message":"I thought if the list of sources was always in the same order, hbase might realize that your update to the record wasn\u0027t changing anything. Maybe not.\n\nA JSON encoder will escape an embedded double quote. It\u0027s less likely that you\u0027ll find a name of something with a pipe, but it might come up in a description field that is part of the metadata. Not doing any escaping at all just seems dangerous. Would it work to use a non-printing character as a field separator?","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":228,"context_line":"            except KeyError:"},{"line_number":229,"context_line":"                sources \u003d [data[\u0027source\u0027]]"},{"line_number":230,"context_line":""},{"line_number":231,"context_line":"            user[\u0027f:source\u0027] \u003d \"|%s|\" % \"|\".join(str(n) for n in sources)"},{"line_number":232,"context_line":"            self.user.put(data[\u0027user_id\u0027], user)"},{"line_number":233,"context_line":""},{"line_number":234,"context_line":"        project \u003d self.project.row(data[\u0027project_id\u0027])"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6h0%3D","line":231,"in_reply_to":"AAAAM3%2F%2B8vc%3D","updated":"2013-02-14 17:05:21.000000000","message":"Not sure how sorting will help... On the JSON and pipes, I think here pipes is the same sort of the assumption as it would be in case of double quotes if it were serialised into a JSON. Can various names have double-quotes in them? \nI use pipes because then in HBase I\u0027m using a so-called substring filter that is looking for a substring match in the column value, so with valid sources like: \"test\" and \"\\\"another\\\"test\", if we looked for \"test\" it will get two hits instead of just one. With pipes it feels like a safer assumption, I think.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":252,"context_line":"        resource[\u0027f:resource_id\u0027] \u003d data[\u0027resource_id\u0027]"},{"line_number":253,"context_line":"        resource[\u0027f:project_id\u0027] \u003d data[\u0027project_id\u0027]"},{"line_number":254,"context_line":"        resource[\u0027f:user_id\u0027] \u003d data[\u0027user_id\u0027]"},{"line_number":255,"context_line":"        resource[\u0027f:timestamp\u0027] \u003d str(data[\u0027timestamp\u0027])"},{"line_number":256,"context_line":"        resource[\u0027f:received_timestamp\u0027] \u003d str(received_timestamp)"},{"line_number":257,"context_line":"        resource[\u0027f:metadata\u0027] \u003d json.dumps(data[\u0027resource_metadata\u0027])"},{"line_number":258,"context_line":"        resource[\u0027f:source\u0027] \u003d data[\u0027source\u0027]"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8uU%3D","line":255,"updated":"2013-02-13 17:02:38.000000000","message":"I think you will want to use the .isoformat() method explicitly instead of depending on the default localization format.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"4c236fd81fbae574a9905fa60caefc4317aa0665","unresolved":false,"context_lines":[{"line_number":252,"context_line":"        resource[\u0027f:resource_id\u0027] \u003d data[\u0027resource_id\u0027]"},{"line_number":253,"context_line":"        resource[\u0027f:project_id\u0027] \u003d data[\u0027project_id\u0027]"},{"line_number":254,"context_line":"        resource[\u0027f:user_id\u0027] \u003d data[\u0027user_id\u0027]"},{"line_number":255,"context_line":"        resource[\u0027f:timestamp\u0027] \u003d str(data[\u0027timestamp\u0027])"},{"line_number":256,"context_line":"        resource[\u0027f:received_timestamp\u0027] \u003d str(received_timestamp)"},{"line_number":257,"context_line":"        resource[\u0027f:metadata\u0027] \u003d json.dumps(data[\u0027resource_metadata\u0027])"},{"line_number":258,"context_line":"        resource[\u0027f:source\u0027] \u003d data[\u0027source\u0027]"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4Hs%3D","line":255,"in_reply_to":"AAAAM3%2F%2B4xw%3D","updated":"2013-02-15 19:02:41.000000000","message":"Will do.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":252,"context_line":"        resource[\u0027f:resource_id\u0027] \u003d data[\u0027resource_id\u0027]"},{"line_number":253,"context_line":"        resource[\u0027f:project_id\u0027] \u003d data[\u0027project_id\u0027]"},{"line_number":254,"context_line":"        resource[\u0027f:user_id\u0027] \u003d data[\u0027user_id\u0027]"},{"line_number":255,"context_line":"        resource[\u0027f:timestamp\u0027] \u003d str(data[\u0027timestamp\u0027])"},{"line_number":256,"context_line":"        resource[\u0027f:received_timestamp\u0027] \u003d str(received_timestamp)"},{"line_number":257,"context_line":"        resource[\u0027f:metadata\u0027] \u003d json.dumps(data[\u0027resource_metadata\u0027])"},{"line_number":258,"context_line":"        resource[\u0027f:source\u0027] \u003d data[\u0027source\u0027]"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4xw%3D","line":255,"in_reply_to":"AAAAM3%2F%2B6hc%3D","updated":"2013-02-15 18:53:07.000000000","message":"Have a look at ceilometer.openstack.common.timeutils. There are a few functions there for handling time in a consistent way, without relying on locale settings as str() does.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":252,"context_line":"        resource[\u0027f:resource_id\u0027] \u003d data[\u0027resource_id\u0027]"},{"line_number":253,"context_line":"        resource[\u0027f:project_id\u0027] \u003d data[\u0027project_id\u0027]"},{"line_number":254,"context_line":"        resource[\u0027f:user_id\u0027] \u003d data[\u0027user_id\u0027]"},{"line_number":255,"context_line":"        resource[\u0027f:timestamp\u0027] \u003d str(data[\u0027timestamp\u0027])"},{"line_number":256,"context_line":"        resource[\u0027f:received_timestamp\u0027] \u003d str(received_timestamp)"},{"line_number":257,"context_line":"        resource[\u0027f:metadata\u0027] \u003d json.dumps(data[\u0027resource_metadata\u0027])"},{"line_number":258,"context_line":"        resource[\u0027f:source\u0027] \u003d data[\u0027source\u0027]"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6hc%3D","line":255,"in_reply_to":"AAAAM3%2F%2B8uU%3D","updated":"2013-02-14 17:05:21.000000000","message":"Problem with .isoformat() is that it returns date only without time.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":257,"context_line":"        resource[\u0027f:metadata\u0027] \u003d json.dumps(data[\u0027resource_metadata\u0027])"},{"line_number":258,"context_line":"        resource[\u0027f:source\u0027] \u003d data[\u0027source\u0027]"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        meters \u003d []"},{"line_number":261,"context_line":"        new_meter \u003d \"%s!%s\" % (data[\u0027counter_name\u0027], data[\u0027counter_type\u0027])"},{"line_number":262,"context_line":"        try:"},{"line_number":263,"context_line":"            meters \u003d resource[\u0027f:meter\u0027].strip(\"|\").split(\"|\")"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8rw%3D","line":260,"updated":"2013-02-13 17:02:38.000000000","message":"This logic is repeated for sources and meters. It seems like a helper function would be useful to avoid repeating the same logic.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":257,"context_line":"        resource[\u0027f:metadata\u0027] \u003d json.dumps(data[\u0027resource_metadata\u0027])"},{"line_number":258,"context_line":"        resource[\u0027f:source\u0027] \u003d data[\u0027source\u0027]"},{"line_number":259,"context_line":""},{"line_number":260,"context_line":"        meters \u003d []"},{"line_number":261,"context_line":"        new_meter \u003d \"%s!%s\" % (data[\u0027counter_name\u0027], data[\u0027counter_type\u0027])"},{"line_number":262,"context_line":"        try:"},{"line_number":263,"context_line":"            meters \u003d resource[\u0027f:meter\u0027].strip(\"|\").split(\"|\")"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6hU%3D","line":260,"in_reply_to":"AAAAM3%2F%2B8rw%3D","updated":"2013-02-14 17:05:21.000000000","message":"I\u0027ll see if I can stretch my Python skills to refactor this.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":270,"context_line":"        self.resource.put(data[\u0027resource_id\u0027], resource)"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":273,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":274,"context_line":"        m \u003d md5.new()"},{"line_number":275,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":276,"context_line":"                             data[\u0027project_id\u0027]))"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8rk%3D","line":273,"updated":"2013-02-13 17:02:38.000000000","message":"Be careful, not every meter will have a user set (not every action is triggered by a user). You probably want to use the project id instead.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":270,"context_line":"        self.resource.put(data[\u0027resource_id\u0027], resource)"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":273,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":274,"context_line":"        m \u003d md5.new()"},{"line_number":275,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":276,"context_line":"                             data[\u0027project_id\u0027]))"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4JY%3D","line":273,"in_reply_to":"AAAAM3%2F%2B6g0%3D","updated":"2013-02-15 18:53:07.000000000","message":"OK","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":270,"context_line":"        self.resource.put(data[\u0027resource_id\u0027], resource)"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":273,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":274,"context_line":"        m \u003d md5.new()"},{"line_number":275,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":276,"context_line":"                             data[\u0027project_id\u0027]))"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6g0%3D","line":273,"in_reply_to":"AAAAM3%2F%2B8rk%3D","updated":"2013-02-14 17:05:21.000000000","message":"This is just for uniqueness, if there\u0027s no userId, then there\u0027s always resource and project.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":275,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":276,"context_line":"                             data[\u0027project_id\u0027]))"},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"        rts \u003d reverse_timestamp(data[\u0027timestamp\u0027])"},{"line_number":279,"context_line":"        row \u003d \"%s_%d_%s\" % (data[\u0027counter_name\u0027], rts, m.hexdigest())"},{"line_number":280,"context_line":""},{"line_number":281,"context_line":"        record \u003d {\u0027f:timestamp\u0027: str(data[\u0027timestamp\u0027]),"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8q4%3D","line":278,"updated":"2013-02-13 17:02:38.000000000","message":"I\u0027m not an hbase expert, so it isn\u0027t obvious why you want to use a \"reverse\" timestamp (or even what reverse means in this context).","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":275,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":276,"context_line":"                             data[\u0027project_id\u0027]))"},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"        rts \u003d reverse_timestamp(data[\u0027timestamp\u0027])"},{"line_number":279,"context_line":"        row \u003d \"%s_%d_%s\" % (data[\u0027counter_name\u0027], rts, m.hexdigest())"},{"line_number":280,"context_line":""},{"line_number":281,"context_line":"        record \u003d {\u0027f:timestamp\u0027: str(data[\u0027timestamp\u0027]),"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6go%3D","line":278,"in_reply_to":"AAAAM3%2F%2B8q4%3D","updated":"2013-02-14 17:05:21.000000000","message":"I\u0027ll provide a docstring to reverse_timestamp()","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            q \u003d make_query(source\u003dsource, substr_sources\u003dTrue,"},{"line_number":311,"context_line":"                           query_only\u003dTrue, require_meter\u003dFalse)"},{"line_number":312,"context_line":"        users \u003d []"},{"line_number":313,"context_line":"        for key, _ in self.user.scan(filter\u003dq):"},{"line_number":314,"context_line":"            users.append(key)"},{"line_number":315,"context_line":"        return users"},{"line_number":316,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8qY%3D","line":313,"updated":"2013-02-13 17:02:38.000000000","message":"This method can return a generator expression, instead of a list.\n\n    return (key for key, ignored in self.user.scan(filter\u003dq))\n\nYou don\u0027t want to use the variable \"_\" because we will be using that for wrapping messages for translation.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":310,"context_line":"            q \u003d make_query(source\u003dsource, substr_sources\u003dTrue,"},{"line_number":311,"context_line":"                           query_only\u003dTrue, require_meter\u003dFalse)"},{"line_number":312,"context_line":"        users \u003d []"},{"line_number":313,"context_line":"        for key, _ in self.user.scan(filter\u003dq):"},{"line_number":314,"context_line":"            users.append(key)"},{"line_number":315,"context_line":"        return users"},{"line_number":316,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6gg%3D","line":313,"in_reply_to":"AAAAM3%2F%2B8qY%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":325,"context_line":"            q \u003d make_query(source\u003dsource, substr_sources\u003dTrue,"},{"line_number":326,"context_line":"                           query_only\u003dTrue, require_meter\u003dFalse)"},{"line_number":327,"context_line":"        projects \u003d []"},{"line_number":328,"context_line":"        for key, _ in self.project.scan(filter\u003dq):"},{"line_number":329,"context_line":"            projects.append(key)"},{"line_number":330,"context_line":"        return projects"},{"line_number":331,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8qQ%3D","line":328,"updated":"2013-02-13 17:02:38.000000000","message":"Return a generator expression.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":325,"context_line":"            q \u003d make_query(source\u003dsource, substr_sources\u003dTrue,"},{"line_number":326,"context_line":"                           query_only\u003dTrue, require_meter\u003dFalse)"},{"line_number":327,"context_line":"        projects \u003d []"},{"line_number":328,"context_line":"        for key, _ in self.project.scan(filter\u003dq):"},{"line_number":329,"context_line":"            projects.append(key)"},{"line_number":330,"context_line":"        return projects"},{"line_number":331,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6gc%3D","line":328,"in_reply_to":"AAAAM3%2F%2B8qQ%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":376,"context_line":"        resources \u003d []"},{"line_number":377,"context_line":"        for resource_id, data in self.resource.scan(filter\u003dq):"},{"line_number":378,"context_line":"            if not len(resource_ids) or resource_id in resource_ids:"},{"line_number":379,"context_line":"                r \u003d {\u0027resource_id\u0027: resource_id,"},{"line_number":380,"context_line":"                     \u0027metadata\u0027: json.loads(data[\u0027f:metadata\u0027]),"},{"line_number":381,"context_line":"                     \u0027project_id\u0027: data[\u0027f:project_id\u0027],"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8ow%3D","line":378,"updated":"2013-02-13 17:02:38.000000000","message":"\"if not resource_ids or resource_id in resource_ids:\"","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":376,"context_line":"        resources \u003d []"},{"line_number":377,"context_line":"        for resource_id, data in self.resource.scan(filter\u003dq):"},{"line_number":378,"context_line":"            if not len(resource_ids) or resource_id in resource_ids:"},{"line_number":379,"context_line":"                r \u003d {\u0027resource_id\u0027: resource_id,"},{"line_number":380,"context_line":"                     \u0027metadata\u0027: json.loads(data[\u0027f:metadata\u0027]),"},{"line_number":381,"context_line":"                     \u0027project_id\u0027: data[\u0027f:project_id\u0027],"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6gY%3D","line":378,"in_reply_to":"AAAAM3%2F%2B8ow%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":386,"context_line":"                     \u0027meter\u0027: []}"},{"line_number":387,"context_line":"                meters \u003d data[\u0027f:meter\u0027].split(\u0027|\u0027)"},{"line_number":388,"context_line":"                for meter in meters:"},{"line_number":389,"context_line":"                    if not len(meter):"},{"line_number":390,"context_line":"                        continue"},{"line_number":391,"context_line":"                    counter_name, counter_type \u003d meter.split(\"!\")"},{"line_number":392,"context_line":"                    r[\u0027meter\u0027].append({\"counter_name\": counter_name,"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8oc%3D","line":389,"updated":"2013-02-13 17:02:38.000000000","message":"You can combine the test for a valid meter name with the for loop:\n\n    for meter in (m for m in meters if m):\n\nThis lets you avoid entering the loop at all for empty values.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":386,"context_line":"                     \u0027meter\u0027: []}"},{"line_number":387,"context_line":"                meters \u003d data[\u0027f:meter\u0027].split(\u0027|\u0027)"},{"line_number":388,"context_line":"                for meter in meters:"},{"line_number":389,"context_line":"                    if not len(meter):"},{"line_number":390,"context_line":"                        continue"},{"line_number":391,"context_line":"                    counter_name, counter_type \u003d meter.split(\"!\")"},{"line_number":392,"context_line":"                    r[\u0027meter\u0027].append({\"counter_name\": counter_name,"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6gQ%3D","line":389,"in_reply_to":"AAAAM3%2F%2B8oc%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":412,"context_line":"        :param source: Optional source filter."},{"line_number":413,"context_line":"        :param metaquery: Optional dict with metadata to match on."},{"line_number":414,"context_line":"        \"\"\""},{"line_number":415,"context_line":"        q, _, _ \u003d make_query(user\u003duser, project\u003dproject,"},{"line_number":416,"context_line":"                             resource\u003dresource, source\u003dsource,"},{"line_number":417,"context_line":"                             require_meter\u003dFalse)"},{"line_number":418,"context_line":"        LOG.debug(\"q: %s\" % q)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8oU%3D","line":415,"updated":"2013-02-13 17:02:38.000000000","message":"Don\u0027t override the _ variable. It is the function for wrapping translatable strings.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":412,"context_line":"        :param source: Optional source filter."},{"line_number":413,"context_line":"        :param metaquery: Optional dict with metadata to match on."},{"line_number":414,"context_line":"        \"\"\""},{"line_number":415,"context_line":"        q, _, _ \u003d make_query(user\u003duser, project\u003dproject,"},{"line_number":416,"context_line":"                             resource\u003dresource, source\u003dsource,"},{"line_number":417,"context_line":"                             require_meter\u003dFalse)"},{"line_number":418,"context_line":"        LOG.debug(\"q: %s\" % q)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4JU%3D","line":415,"in_reply_to":"AAAAM3%2F%2B6gA%3D","updated":"2013-02-15 18:53:07.000000000","message":"Sounds good.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":412,"context_line":"        :param source: Optional source filter."},{"line_number":413,"context_line":"        :param metaquery: Optional dict with metadata to match on."},{"line_number":414,"context_line":"        \"\"\""},{"line_number":415,"context_line":"        q, _, _ \u003d make_query(user\u003duser, project\u003dproject,"},{"line_number":416,"context_line":"                             resource\u003dresource, source\u003dsource,"},{"line_number":417,"context_line":"                             require_meter\u003dFalse)"},{"line_number":418,"context_line":"        LOG.debug(\"q: %s\" % q)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6gA%3D","line":415,"in_reply_to":"AAAAM3%2F%2B8oU%3D","updated":"2013-02-14 17:05:21.000000000","message":"Will replace with q, start, stop \u003d make_query(...), where \"start\" and \"stop\" will not be used, if that\u0027s ok.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":428,"context_line":"                if not len(meter):"},{"line_number":429,"context_line":"                    continue"},{"line_number":430,"context_line":"                counter_name, counter_type \u003d meter.split(\"!\")"},{"line_number":431,"context_line":"                m \u003d {}"},{"line_number":432,"context_line":"                m[\u0027name\u0027] \u003d counter_name"},{"line_number":433,"context_line":"                m[\u0027type\u0027] \u003d counter_type"},{"line_number":434,"context_line":"                m[\u0027resource_id\u0027] \u003d data[\u0027f:resource_id\u0027]"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8oI%3D","line":431,"updated":"2013-02-13 17:02:38.000000000","message":"Building the dictionary in one step, instead of creating it then adding values, is more efficient.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":428,"context_line":"                if not len(meter):"},{"line_number":429,"context_line":"                    continue"},{"line_number":430,"context_line":"                counter_name, counter_type \u003d meter.split(\"!\")"},{"line_number":431,"context_line":"                m \u003d {}"},{"line_number":432,"context_line":"                m[\u0027name\u0027] \u003d counter_name"},{"line_number":433,"context_line":"                m[\u0027type\u0027] \u003d counter_type"},{"line_number":434,"context_line":"                m[\u0027resource_id\u0027] \u003d data[\u0027f:resource_id\u0027]"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6f4%3D","line":431,"in_reply_to":"AAAAM3%2F%2B8oI%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":463,"context_line":"        results \u003d {}"},{"line_number":464,"context_line":"        for _, meter in gen:"},{"line_number":465,"context_line":"            try:"},{"line_number":466,"context_line":"                results[meter[\u0027f:resource_id\u0027]] \\"},{"line_number":467,"context_line":"                    +\u003d int(meter[\u0027f:counter_volume\u0027])"},{"line_number":468,"context_line":"            except KeyError:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8mw%3D","line":465,"updated":"2013-02-13 17:02:38.000000000","message":"Use results.setdefault() instead of an exception for efficiency.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":463,"context_line":"        results \u003d {}"},{"line_number":464,"context_line":"        for _, meter in gen:"},{"line_number":465,"context_line":"            try:"},{"line_number":466,"context_line":"                results[meter[\u0027f:resource_id\u0027]] \\"},{"line_number":467,"context_line":"                    +\u003d int(meter[\u0027f:counter_volume\u0027])"},{"line_number":468,"context_line":"            except KeyError:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6fo%3D","line":465,"in_reply_to":"AAAAM3%2F%2B8mw%3D","updated":"2013-02-14 17:05:21.000000000","message":"Done","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":481,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":482,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":483,"context_line":"        results \u003d {}"},{"line_number":484,"context_line":"        for _, meter in gen:"},{"line_number":485,"context_line":"            try:"},{"line_number":486,"context_line":"                if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":487,"context_line":"                        int(meter[\u0027f:counter_volume\u0027]):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8mg%3D","line":484,"updated":"2013-02-13 17:02:38.000000000","message":"Does hbase not support these sorts of operations in the queries? Doing it in Python could be fairly expensive.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"4c236fd81fbae574a9905fa60caefc4317aa0665","unresolved":false,"context_lines":[{"line_number":481,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":482,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":483,"context_line":"        results \u003d {}"},{"line_number":484,"context_line":"        for _, meter in gen:"},{"line_number":485,"context_line":"            try:"},{"line_number":486,"context_line":"                if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":487,"context_line":"                        int(meter[\u0027f:counter_volume\u0027]):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4H0%3D","line":484,"in_reply_to":"AAAAM3%2F%2B4JQ%3D","updated":"2013-02-15 19:02:41.000000000","message":"Will do.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":481,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":482,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":483,"context_line":"        results \u003d {}"},{"line_number":484,"context_line":"        for _, meter in gen:"},{"line_number":485,"context_line":"            try:"},{"line_number":486,"context_line":"                if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":487,"context_line":"                        int(meter[\u0027f:counter_volume\u0027]):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4JQ%3D","line":484,"in_reply_to":"AAAAM3%2F%2B6fI%3D","updated":"2013-02-15 18:53:07.000000000","message":"OK, understood. Could you include a comment to that effect here (or maybe at the top of the file in the docstring for the module)?","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":481,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":482,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":483,"context_line":"        results \u003d {}"},{"line_number":484,"context_line":"        for _, meter in gen:"},{"line_number":485,"context_line":"            try:"},{"line_number":486,"context_line":"                if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":487,"context_line":"                        int(meter[\u0027f:counter_volume\u0027]):"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6fI%3D","line":484,"in_reply_to":"AAAAM3%2F%2B8mg%3D","updated":"2013-02-14 17:05:21.000000000","message":"This is understood, but in current production version of HBase this logic is not available. It looks like there will be a couple of options in (near) future HBase releases to solve this. At the moment - in other applications - aggregations are done through MapReduce which is not available through the RPC. One other option is using Hive, but we will have to assess the performance there too.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":120,"context_line":"    def upgrade(self, version\u003dNone):"},{"line_number":121,"context_line":"        pass"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def _get_connection(self, conf):"},{"line_number":124,"context_line":"        \"\"\"Return a connection to the database."},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        .. note::"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBw%3D","line":123,"updated":"2013-02-26 13:12:27.000000000","message":"@staticmethod","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":120,"context_line":"    def upgrade(self, version\u003dNone):"},{"line_number":121,"context_line":"        pass"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def _get_connection(self, conf):"},{"line_number":124,"context_line":"        \"\"\"Return a connection to the database."},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"        .. note::"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl5E%3D","line":123,"in_reply_to":"AAAAM3%2F%2BmBw%3D","updated":"2013-02-26 15:27:58.000000000","message":"Can you please elaborate? The same method is not static in Mongo and SQLAlchemy drivers.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        return happybase.Connection(host\u003dconf[\u0027host\u0027], port\u003dconf[\u0027port\u0027],"},{"line_number":133,"context_line":"                                    table_prefix\u003dconf[\u0027table_prefix\u0027])"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def _parse_connection_url(self, url):"},{"line_number":136,"context_line":"        \"\"\"Parse connection parameters from a database url."},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"        .. note::"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBo%3D","line":135,"updated":"2013-02-26 13:12:27.000000000","message":"@staticmethod","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":132,"context_line":"        return happybase.Connection(host\u003dconf[\u0027host\u0027], port\u003dconf[\u0027port\u0027],"},{"line_number":133,"context_line":"                                    table_prefix\u003dconf[\u0027table_prefix\u0027])"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def _parse_connection_url(self, url):"},{"line_number":136,"context_line":"        \"\"\"Parse connection parameters from a database url."},{"line_number":137,"context_line":""},{"line_number":138,"context_line":"        .. note::"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl5A%3D","line":135,"in_reply_to":"AAAAM3%2F%2BmBo%3D","updated":"2013-02-26 15:27:58.000000000","message":"Same as above","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":199,"context_line":""},{"line_number":200,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":201,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":202,"context_line":"        m \u003d hashlib.md5()"},{"line_number":203,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":204,"context_line":"                             data[\u0027project_id\u0027]))"},{"line_number":205,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBk%3D","line":202,"updated":"2013-02-26 13:12:27.000000000","message":"Don\u0027t want to run a long argument, but are we sure MD5 is the still a good choice?","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":199,"context_line":""},{"line_number":200,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":201,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":202,"context_line":"        m \u003d hashlib.md5()"},{"line_number":203,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":204,"context_line":"                             data[\u0027project_id\u0027]))"},{"line_number":205,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl4w%3D","line":202,"in_reply_to":"AAAAM3%2F%2BmBk%3D","updated":"2013-02-26 15:27:58.000000000","message":"MD5 I thought was the easiest way to hash user+resource+project in row key. If not done, this will potentially cause conflicts as the same meter data from different project/resource will be recorded over existing meter data. \nI don\u0027t know if it\u0027s a good choice, but why not?","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":233,"context_line":"        record[\u0027f:message\u0027] \u003d json.dumps(data)"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        self.meter.put(row, record)"},{"line_number":236,"context_line":"        return"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"    def get_users(self, source\u003dNone):"},{"line_number":239,"context_line":"        \"\"\"Return an iterable of user id strings."}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBg%3D","line":236,"updated":"2013-02-26 13:12:27.000000000","message":"not required","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":233,"context_line":"        record[\u0027f:message\u0027] \u003d json.dumps(data)"},{"line_number":234,"context_line":""},{"line_number":235,"context_line":"        self.meter.put(row, record)"},{"line_number":236,"context_line":"        return"},{"line_number":237,"context_line":""},{"line_number":238,"context_line":"    def get_users(self, source\u003dNone):"},{"line_number":239,"context_line":"        \"\"\"Return an iterable of user id strings."}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl4k%3D","line":236,"in_reply_to":"AAAAM3%2F%2BmBg%3D","updated":"2013-02-26 15:27:58.000000000","message":"Done","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":465,"context_line":"        # Initialise the stats and break down by time buckets if required"},{"line_number":466,"context_line":"        if period:"},{"line_number":467,"context_line":"            for i in range(int(math.ceil(timeutils.delta_seconds("},{"line_number":468,"context_line":"                    start_time, end_time) / float(period)))):"},{"line_number":469,"context_line":"                results.append(copy.copy(stat))"},{"line_number":470,"context_line":"                results[i][\u0027period\u0027] \u003d period"},{"line_number":471,"context_line":"                results[i][\u0027period_start\u0027] \u003d \\"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBM%3D","line":468,"updated":"2013-02-26 13:12:27.000000000","message":"That should be modified to use iter_period when https://review.openstack.org/#/c/22869/ is merged I guess.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":465,"context_line":"        # Initialise the stats and break down by time buckets if required"},{"line_number":466,"context_line":"        if period:"},{"line_number":467,"context_line":"            for i in range(int(math.ceil(timeutils.delta_seconds("},{"line_number":468,"context_line":"                    start_time, end_time) / float(period)))):"},{"line_number":469,"context_line":"                results.append(copy.copy(stat))"},{"line_number":470,"context_line":"                results[i][\u0027period\u0027] \u003d period"},{"line_number":471,"context_line":"                results[i][\u0027period_start\u0027] \u003d \\"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl4Y%3D","line":468,"in_reply_to":"AAAAM3%2F%2BmBM%3D","updated":"2013-02-26 15:27:58.000000000","message":"Not sure, this code works as expected already.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":601,"context_line":"    if source:"},{"line_number":602,"context_line":"        q.append(\"SingleColumnValueFilter \""},{"line_number":603,"context_line":"                 \"(\u0027f\u0027, \u0027source\u0027, \u003d, \u0027binary:%s\u0027)\" % source)"},{"line_number":604,"context_line":"        # when start_time and end_time is provided,"},{"line_number":605,"context_line":"    #    if it\u0027s filtered by meter,"},{"line_number":606,"context_line":"    #         rowkey will be used in the query;"},{"line_number":607,"context_line":"    #    if it\u0027s non meter filter query(eg. project_id, user_id etc),"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBI%3D","line":604,"updated":"2013-02-26 13:12:27.000000000","message":"weird alignment for comments :)","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":601,"context_line":"    if source:"},{"line_number":602,"context_line":"        q.append(\"SingleColumnValueFilter \""},{"line_number":603,"context_line":"                 \"(\u0027f\u0027, \u0027source\u0027, \u003d, \u0027binary:%s\u0027)\" % source)"},{"line_number":604,"context_line":"        # when start_time and end_time is provided,"},{"line_number":605,"context_line":"    #    if it\u0027s filtered by meter,"},{"line_number":606,"context_line":"    #         rowkey will be used in the query;"},{"line_number":607,"context_line":"    #    if it\u0027s non meter filter query(eg. project_id, user_id etc),"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl7g%3D","line":604,"in_reply_to":"AAAAM3%2F%2BmBI%3D","updated":"2013-02-26 15:27:58.000000000","message":"Done","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":18,"context_line":"# under the License."},{"line_number":19,"context_line":"\"\"\"Openstack Ceilometer HBase storage backend"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":".. note::"},{"line_number":22,"context_line":"  This driver is designed to enable Ceilometer store its data in HBase."},{"line_number":23,"context_line":"  The implementation is using HBase Thrift interface so it\u0027s necessary to have"},{"line_number":24,"context_line":"  the HBase Thrift server installed and started:"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bl2M%3D","line":21,"updated":"2013-02-26 16:06:43.000000000","message":"We should start a section of the documentation for configuring using hbase and include these details there. That can be done under a separate changeset.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":18,"context_line":"# under the License."},{"line_number":19,"context_line":"\"\"\"Openstack Ceilometer HBase storage backend"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":".. note::"},{"line_number":22,"context_line":"  This driver is designed to enable Ceilometer store its data in HBase."},{"line_number":23,"context_line":"  The implementation is using HBase Thrift interface so it\u0027s necessary to have"},{"line_number":24,"context_line":"  the HBase Thrift server installed and started:"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bjgg%3D","line":21,"in_reply_to":"AAAAM3%2F%2Bl2M%3D","updated":"2013-02-27 16:05:44.000000000","message":"Yep, we are working on a wiki page for that. Will replace with a link when it\u0027s ready.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":107,"context_line":"        Hbase Connection Initialization"},{"line_number":108,"context_line":"        \u0027\u0027\u0027"},{"line_number":109,"context_line":"        opts \u003d self._parse_connection_url(conf.database_connection)"},{"line_number":110,"context_line":"        opts[\u0027table_prefix\u0027] \u003d conf.table_prefix"},{"line_number":111,"context_line":"        self.conn \u003d self._get_connection(opts)"},{"line_number":112,"context_line":"        self.conn.open()"},{"line_number":113,"context_line":"        self.project \u003d self.conn.table(\u0027project\u0027)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bl2I%3D","line":110,"updated":"2013-02-26 16:06:43.000000000","message":"Where is this option defined?","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":107,"context_line":"        Hbase Connection Initialization"},{"line_number":108,"context_line":"        \u0027\u0027\u0027"},{"line_number":109,"context_line":"        opts \u003d self._parse_connection_url(conf.database_connection)"},{"line_number":110,"context_line":"        opts[\u0027table_prefix\u0027] \u003d conf.table_prefix"},{"line_number":111,"context_line":"        self.conn \u003d self._get_connection(opts)"},{"line_number":112,"context_line":"        self.conn.open()"},{"line_number":113,"context_line":"        self.project \u003d self.conn.table(\u0027project\u0027)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bjhw%3D","line":110,"in_reply_to":"AAAAM3%2F%2Bl2I%3D","updated":"2013-02-27 16:05:44.000000000","message":"Done","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":238,"context_line":"        :param source: Optional source filter."},{"line_number":239,"context_line":"        \"\"\""},{"line_number":240,"context_line":"        LOG.debug(\"source: %s\" % source)"},{"line_number":241,"context_line":"        if source:"},{"line_number":242,"context_line":"            return sorted(key for key, ignored in self.user.scan("},{"line_number":243,"context_line":"                columns\u003d[\u0027s:%s\u0027 % source]))"},{"line_number":244,"context_line":"        return sorted(key for key, ignored in self.user.scan())"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bl1c%3D","line":241,"updated":"2013-02-26 16:06:43.000000000","message":"This could be tightened up by building a dictionary containing the arguments to pass to self.user.scan() so you only need one version of the expression. Something like:\n\n  scan_args \u003d {}\n  if source:\n    scan_args[\u0027columns\u0027] \u003d [\u0027s:%s\u0027 % source]\n  return sorted(key for key, ignored in self.user.scan(**scan_args)]","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":238,"context_line":"        :param source: Optional source filter."},{"line_number":239,"context_line":"        \"\"\""},{"line_number":240,"context_line":"        LOG.debug(\"source: %s\" % source)"},{"line_number":241,"context_line":"        if source:"},{"line_number":242,"context_line":"            return sorted(key for key, ignored in self.user.scan("},{"line_number":243,"context_line":"                columns\u003d[\u0027s:%s\u0027 % source]))"},{"line_number":244,"context_line":"        return sorted(key for key, ignored in self.user.scan())"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bjhs%3D","line":241,"in_reply_to":"AAAAM3%2F%2Bl1c%3D","updated":"2013-02-27 16:05:44.000000000","message":"Done","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":249,"context_line":"        :param source: Optional source filter."},{"line_number":250,"context_line":"        \"\"\""},{"line_number":251,"context_line":"        LOG.debug(\"source: %s\" % source)"},{"line_number":252,"context_line":"        if source:"},{"line_number":253,"context_line":"            return (key for key, ignored in self.project.scan("},{"line_number":254,"context_line":"                columns\u003d[\u0027s:%s\u0027 % source]))"},{"line_number":255,"context_line":"        return (key for key, ignored in self.project.scan())"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bl1U%3D","line":252,"updated":"2013-02-26 16:06:43.000000000","message":"ditto","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":249,"context_line":"        :param source: Optional source filter."},{"line_number":250,"context_line":"        \"\"\""},{"line_number":251,"context_line":"        LOG.debug(\"source: %s\" % source)"},{"line_number":252,"context_line":"        if source:"},{"line_number":253,"context_line":"            return (key for key, ignored in self.project.scan("},{"line_number":254,"context_line":"                columns\u003d[\u0027s:%s\u0027 % source]))"},{"line_number":255,"context_line":"        return (key for key, ignored in self.project.scan())"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bjho%3D","line":252,"in_reply_to":"AAAAM3%2F%2Bl1U%3D","updated":"2013-02-27 16:05:44.000000000","message":"Done","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":287,"context_line":""},{"line_number":288,"context_line":"        resource_ids \u003d {}"},{"line_number":289,"context_line":"        if start_timestamp or end_timestamp:"},{"line_number":290,"context_line":"            # Look for resources matching the above criteria and with"},{"line_number":291,"context_line":"            # events in the time range we care about, then change the"},{"line_number":292,"context_line":"            # resource query to return just those resources by id."},{"line_number":293,"context_line":"            g \u003d self.meter.scan(filter\u003dq, row_start\u003dstart_row,"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bl0I%3D","line":290,"updated":"2013-02-26 16:06:43.000000000","message":"This double query (first for meters then for resources) doesn\u0027t seem like it\u0027s going to be a very efficient way to produce this information. We should think about changing the table schema during Havana to see if it can be improved.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":437,"context_line":"        # As HBase meters are stored as newest-first, we need to fetch them all"},{"line_number":438,"context_line":"        # and work with them in the reversed order, otherwise we can\u0027t reliably"},{"line_number":439,"context_line":"        # build the period buckets."},{"line_number":440,"context_line":"        meters \u003d []"},{"line_number":441,"context_line":"        for ignored, meter in gen:"},{"line_number":442,"context_line":"            LOG.error(\"\\nMETER R: %s\" % meter)"},{"line_number":443,"context_line":"            meters.insert(0, meter)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Blzg%3D","line":440,"updated":"2013-02-26 16:06:43.000000000","message":"meters \u003d reversed(meter for (ignored, meter) in gen)","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":437,"context_line":"        # As HBase meters are stored as newest-first, we need to fetch them all"},{"line_number":438,"context_line":"        # and work with them in the reversed order, otherwise we can\u0027t reliably"},{"line_number":439,"context_line":"        # build the period buckets."},{"line_number":440,"context_line":"        meters \u003d []"},{"line_number":441,"context_line":"        for ignored, meter in gen:"},{"line_number":442,"context_line":"            LOG.error(\"\\nMETER R: %s\" % meter)"},{"line_number":443,"context_line":"            meters.insert(0, meter)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2BjhU%3D","line":440,"in_reply_to":"AAAAM3%2F%2Blzg%3D","updated":"2013-02-27 16:05:44.000000000","message":"Fixed it by rewriting the logic, so not to reverse at all.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"ce54952f208867d11e236888ddd7bd6e8a4a2252","unresolved":false,"context_lines":[{"line_number":445,"context_line":"        start_time \u003d event_filter.start \\"},{"line_number":446,"context_line":"            or timeutils.parse_strtime(meters[0][\u0027f:timestamp\u0027])"},{"line_number":447,"context_line":"        end_time \u003d event_filter.end \\"},{"line_number":448,"context_line":"            or timeutils.parse_strtime(meters[len(meters) - 1][\u0027f:timestamp\u0027])"},{"line_number":449,"context_line":""},{"line_number":450,"context_line":"        LOG.error(\"START: %s\" % start_time)"},{"line_number":451,"context_line":"        LOG.error(\"END:   %s\" % end_time)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Blgk%3D","line":448,"updated":"2013-02-26 18:11:55.000000000","message":"if you use the index -1 you\u0027ll get the last item in the list.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"ce54952f208867d11e236888ddd7bd6e8a4a2252","unresolved":false,"context_lines":[{"line_number":469,"context_line":"                start_time, end_time) / float(period))))"},{"line_number":470,"context_line":"            for i in range(int(math.ceil(timeutils.delta_seconds("},{"line_number":471,"context_line":"                    start_time, end_time) / float(period)))):"},{"line_number":472,"context_line":"                results.append(copy.copy(stat))"},{"line_number":473,"context_line":"                results[i][\u0027period\u0027] \u003d period"},{"line_number":474,"context_line":"                results[i][\u0027period_start\u0027] \u003d \\"},{"line_number":475,"context_line":"                    start_time + datetime.timedelta(0, i * period)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Blhc%3D","line":472,"updated":"2013-02-26 18:11:55.000000000","message":"It will be more efficient to keep a reference to the copy as a local variable instead of indexing into the results list every time you want to modify its contents.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":469,"context_line":"                start_time, end_time) / float(period))))"},{"line_number":470,"context_line":"            for i in range(int(math.ceil(timeutils.delta_seconds("},{"line_number":471,"context_line":"                    start_time, end_time) / float(period)))):"},{"line_number":472,"context_line":"                results.append(copy.copy(stat))"},{"line_number":473,"context_line":"                results[i][\u0027period\u0027] \u003d period"},{"line_number":474,"context_line":"                results[i][\u0027period_start\u0027] \u003d \\"},{"line_number":475,"context_line":"                    start_time + datetime.timedelta(0, i * period)"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2BjhI%3D","line":472,"in_reply_to":"AAAAM3%2F%2Blhc%3D","updated":"2013-02-27 16:05:44.000000000","message":"That\u0027s been changed.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":482,"context_line":"        LOG.error(\"RESULTS: %s\" % results)"},{"line_number":483,"context_line":"        LOG.error(\"METERS: %s\" % meters)"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"        for meter in meters:"},{"line_number":486,"context_line":"            ts \u003d timeutils.parse_strtime(meter[\u0027f:timestamp\u0027])"},{"line_number":487,"context_line":"            # Track the global start time: should be taken from the query if"},{"line_number":488,"context_line":"            # present"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2Bly0%3D","line":485,"updated":"2013-02-26 16:06:43.000000000","message":"Why not do this with MapReduce?!","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":482,"context_line":"        LOG.error(\"RESULTS: %s\" % results)"},{"line_number":483,"context_line":"        LOG.error(\"METERS: %s\" % meters)"},{"line_number":484,"context_line":""},{"line_number":485,"context_line":"        for meter in meters:"},{"line_number":486,"context_line":"            ts \u003d timeutils.parse_strtime(meter[\u0027f:timestamp\u0027])"},{"line_number":487,"context_line":"            # Track the global start time: should be taken from the query if"},{"line_number":488,"context_line":"            # present"}],"source_content_type":"text/x-python","patch_set":16,"id":"AAAAM3%2F%2BjhE%3D","line":485,"in_reply_to":"AAAAM3%2F%2Bly0%3D","updated":"2013-02-27 16:05:44.000000000","message":"There is no MR in HBase itself :-(","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"930628c4b15f594f4c1349b966e40a353ab2880d","unresolved":false,"context_lines":[{"line_number":450,"context_line":"        # list will correspond to the start of the series,"},{"line_number":451,"context_line":"        # and the first - to its end."},{"line_number":452,"context_line":"        start_time \u003d event_filter.start \\"},{"line_number":453,"context_line":"            or timeutils.parse_strtime(meters[len(meters) - 1][\u0027f:timestamp\u0027])"},{"line_number":454,"context_line":"        end_time \u003d event_filter.end \\"},{"line_number":455,"context_line":"            or timeutils.parse_strtime(meters[0][\u0027f:timestamp\u0027])"},{"line_number":456,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2BjdM%3D","line":453,"updated":"2013-02-27 16:37:53.000000000","message":"Replace \"len(meters) - 1\" with \"-1\".","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"423a5d6e0b16228250178e9112abaa23fe2574a3","unresolved":false,"context_lines":[{"line_number":450,"context_line":"        # list will correspond to the start of the series,"},{"line_number":451,"context_line":"        # and the first - to its end."},{"line_number":452,"context_line":"        start_time \u003d event_filter.start \\"},{"line_number":453,"context_line":"            or timeutils.parse_strtime(meters[len(meters) - 1][\u0027f:timestamp\u0027])"},{"line_number":454,"context_line":"        end_time \u003d event_filter.end \\"},{"line_number":455,"context_line":"            or timeutils.parse_strtime(meters[0][\u0027f:timestamp\u0027])"},{"line_number":456,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2Bja0%3D","line":453,"in_reply_to":"AAAAM3%2F%2BjdM%3D","updated":"2013-02-27 16:53:31.000000000","message":"Done","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"930628c4b15f594f4c1349b966e40a353ab2880d","unresolved":false,"context_lines":[{"line_number":456,"context_line":""},{"line_number":457,"context_line":"        results \u003d []"},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"        if not period:"},{"line_number":460,"context_line":"            # No period is specified, only need one large time bucket"},{"line_number":461,"context_line":"            results.append({\u0027count\u0027: 0,"},{"line_number":462,"context_line":"                            \u0027min\u0027: 0,"}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2BjcQ%3D","line":459,"updated":"2013-02-27 16:37:53.000000000","message":"If you always insert one item into results here, you can avoid testing whether there is anything in the results list in the loop below.","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"423a5d6e0b16228250178e9112abaa23fe2574a3","unresolved":false,"context_lines":[{"line_number":456,"context_line":""},{"line_number":457,"context_line":"        results \u003d []"},{"line_number":458,"context_line":""},{"line_number":459,"context_line":"        if not period:"},{"line_number":460,"context_line":"            # No period is specified, only need one large time bucket"},{"line_number":461,"context_line":"            results.append({\u0027count\u0027: 0,"},{"line_number":462,"context_line":"                            \u0027min\u0027: 0,"}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2Bjaw%3D","line":459,"in_reply_to":"AAAAM3%2F%2BjcQ%3D","updated":"2013-02-27 16:53:31.000000000","message":"I only need this when period is *not* set","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"930628c4b15f594f4c1349b966e40a353ab2880d","unresolved":false,"context_lines":[{"line_number":479,"context_line":"                    start_time, ts) / float(period)) * period"},{"line_number":480,"context_line":"                period_start \u003d \\"},{"line_number":481,"context_line":"                    start_time + datetime.timedelta(0, offset)"},{"line_number":482,"context_line":"                if not len(results) or not results[0][\u0027period_start\u0027] \u003d\u003d \\"},{"line_number":483,"context_line":"                        period_start:"},{"line_number":484,"context_line":"                    period_end \u003d period_start + datetime.timedelta("},{"line_number":485,"context_line":"                        0, period)"}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2Bjcc%3D","line":482,"updated":"2013-02-27 16:37:53.000000000","message":"The \"not len(results)\" test can be removed here if you always insert one item above.","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"423a5d6e0b16228250178e9112abaa23fe2574a3","unresolved":false,"context_lines":[{"line_number":479,"context_line":"                    start_time, ts) / float(period)) * period"},{"line_number":480,"context_line":"                period_start \u003d \\"},{"line_number":481,"context_line":"                    start_time + datetime.timedelta(0, offset)"},{"line_number":482,"context_line":"                if not len(results) or not results[0][\u0027period_start\u0027] \u003d\u003d \\"},{"line_number":483,"context_line":"                        period_start:"},{"line_number":484,"context_line":"                    period_end \u003d period_start + datetime.timedelta("},{"line_number":485,"context_line":"                        0, period)"}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2Bjas%3D","line":482,"in_reply_to":"AAAAM3%2F%2Bjcc%3D","updated":"2013-02-27 16:53:31.000000000","message":"I only need this when period *is* set, so first round the results is going to be empty and results[0] will fail. I really wanted to refactor this logic since it is evidently not very clear, but perhaps I\u0027ll leave this till later.","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"930628c4b15f594f4c1349b966e40a353ab2880d","unresolved":false,"context_lines":[{"line_number":484,"context_line":"                    period_end \u003d period_start + datetime.timedelta("},{"line_number":485,"context_line":"                        0, period)"},{"line_number":486,"context_line":""},{"line_number":487,"context_line":"                    results.insert(0,"},{"line_number":488,"context_line":"                                   {\u0027count\u0027: 0,"},{"line_number":489,"context_line":"                                    \u0027min\u0027: 0,"},{"line_number":490,"context_line":"                                    \u0027max\u0027: 0,"}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2Bjbo%3D","line":487,"updated":"2013-02-27 16:37:53.000000000","message":"I believe it will be more efficient to grow the list from the end, instead of the front, and then reverse it once when it is returned.","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"423a5d6e0b16228250178e9112abaa23fe2574a3","unresolved":false,"context_lines":[{"line_number":484,"context_line":"                    period_end \u003d period_start + datetime.timedelta("},{"line_number":485,"context_line":"                        0, period)"},{"line_number":486,"context_line":""},{"line_number":487,"context_line":"                    results.insert(0,"},{"line_number":488,"context_line":"                                   {\u0027count\u0027: 0,"},{"line_number":489,"context_line":"                                    \u0027min\u0027: 0,"},{"line_number":490,"context_line":"                                    \u0027max\u0027: 0,"}],"source_content_type":"text/x-python","patch_set":18,"id":"AAAAM3%2F%2BjaA%3D","line":487,"in_reply_to":"AAAAM3%2F%2Bjbo%3D","updated":"2013-02-27 16:53:31.000000000","message":"Done","commit_id":"1f68ffb6ccb6006dbddada11fc8b3aa2b5cff1c5"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"6e5dacf9750e5d1f1b9ab027c5f92915441d92e4","unresolved":false,"context_lines":[{"line_number":463,"context_line":"        for meter in meters:"},{"line_number":464,"context_line":"            ts \u003d timeutils.parse_strtime(meter[\u0027f:timestamp\u0027])"},{"line_number":465,"context_line":"            offset \u003d int((timeutils.delta_seconds("},{"line_number":466,"context_line":"                start_time, ts)) / (period + 1)) * period"},{"line_number":467,"context_line":"            period_start \u003d \\"},{"line_number":468,"context_line":"                start_time + datetime.timedelta(0, offset)"},{"line_number":469,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"AAAAM3%2F%2BjSs%3D","line":466,"updated":"2013-02-27 17:56:25.000000000","message":"This +1 magic concerns me.","commit_id":"0e4df21707e0ad9ba705f29bdd2154d30e8c5e53"},{"author":{"_account_id":882,"name":"shengjie min","email":"minshengjie@chinacloud.com.cn","username":"shengjie-min"},"change_message_id":"ea5321505ea7ffbf659e3aae7391430da0784b5e","unresolved":false,"context_lines":[{"line_number":36,"context_line":"  The following four tables are expected to exist in HBase:"},{"line_number":37,"context_line":"    create \u0027project\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":38,"context_line":"    create \u0027user\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":39,"context_line":"    create \u0027resource\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027m\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":40,"context_line":"    create \u0027meter\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"  The driver is using HappyBase which is a wrapper library used to interact"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9g4%3D","line":39,"updated":"2013-03-01 13:33:16.000000000","message":"Column family is a container that allows sets of\ncolumns to have separate storage \u0026 semantics. So different CFs will be stored in different places physically. If there is no particular reason, we normally don\u0027t split columns into CFs. If it\u0027s just purely for better handling the list of sources, we can design the Column Qualifier using prefixes. eg. s_source1, s_source2.I guess if we don\u0027t need to be backward compatible every time, we can improve the schema as we go forward?","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"59190d3c26d40ac201be50386594b4c336fb3e5c","unresolved":false,"context_lines":[{"line_number":36,"context_line":"  The following four tables are expected to exist in HBase:"},{"line_number":37,"context_line":"    create \u0027project\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":38,"context_line":"    create \u0027user\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":39,"context_line":"    create \u0027resource\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027m\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":40,"context_line":"    create \u0027meter\u0027, {NAME\u003d\u003e\u0027f\u0027}, {NAME\u003d\u003e\u0027s\u0027}"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"  The driver is using HappyBase which is a wrapper library used to interact"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9do%3D","line":39,"in_reply_to":"AAAANH%2F%2F9g4%3D","updated":"2013-03-01 15:05:50.000000000","message":"Done","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":49,"context_line":"import json"},{"line_number":50,"context_line":"import hashlib"},{"line_number":51,"context_line":"import copy"},{"line_number":52,"context_line":"import math"},{"line_number":53,"context_line":"import datetime"},{"line_number":54,"context_line":"import happybase"},{"line_number":55,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9k8%3D","line":52,"updated":"2013-03-01 13:55:12.000000000","message":"Unused module","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"59190d3c26d40ac201be50386594b4c336fb3e5c","unresolved":false,"context_lines":[{"line_number":49,"context_line":"import json"},{"line_number":50,"context_line":"import hashlib"},{"line_number":51,"context_line":"import copy"},{"line_number":52,"context_line":"import math"},{"line_number":53,"context_line":"import datetime"},{"line_number":54,"context_line":"import happybase"},{"line_number":55,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9dk%3D","line":52,"in_reply_to":"AAAANH%2F%2F9k8%3D","updated":"2013-03-01 15:05:50.000000000","message":"Done","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":99,"context_line":"        \"\"\""},{"line_number":100,"context_line":"        conf.register_opts(self.OPTIONS)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def get_connection(self, conf):"},{"line_number":103,"context_line":"        \"\"\"Return a Connection instance based on the configuration settings."},{"line_number":104,"context_line":"        \"\"\""},{"line_number":105,"context_line":"        return Connection(conf)"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9lk%3D","line":102,"updated":"2013-03-01 13:55:12.000000000","message":"You don\u0027t use self, so that should be a @staticmethod :)","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"59190d3c26d40ac201be50386594b4c336fb3e5c","unresolved":false,"context_lines":[{"line_number":99,"context_line":"        \"\"\""},{"line_number":100,"context_line":"        conf.register_opts(self.OPTIONS)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"    def get_connection(self, conf):"},{"line_number":103,"context_line":"        \"\"\"Return a Connection instance based on the configuration settings."},{"line_number":104,"context_line":"        \"\"\""},{"line_number":105,"context_line":"        return Connection(conf)"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9aA%3D","line":102,"in_reply_to":"AAAANH%2F%2F9lk%3D","updated":"2013-03-01 15:05:50.000000000","message":"Done","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":121,"context_line":"        self.user \u003d self.conn.table(\u0027user\u0027)"},{"line_number":122,"context_line":"        self.resource \u003d self.conn.table(\u0027resource\u0027)"},{"line_number":123,"context_line":"        self.meter \u003d self.conn.table(\u0027meter\u0027)"},{"line_number":124,"context_line":"        return"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"    def upgrade(self, version\u003dNone):"},{"line_number":127,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9lg%3D","line":124,"updated":"2013-03-01 13:55:12.000000000","message":"useless","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"59190d3c26d40ac201be50386594b4c336fb3e5c","unresolved":false,"context_lines":[{"line_number":121,"context_line":"        self.user \u003d self.conn.table(\u0027user\u0027)"},{"line_number":122,"context_line":"        self.resource \u003d self.conn.table(\u0027resource\u0027)"},{"line_number":123,"context_line":"        self.meter \u003d self.conn.table(\u0027meter\u0027)"},{"line_number":124,"context_line":"        return"},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"    def upgrade(self, version\u003dNone):"},{"line_number":127,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9Z8%3D","line":124,"in_reply_to":"AAAANH%2F%2F9lg%3D","updated":"2013-03-01 15:05:50.000000000","message":"Done","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":205,"context_line":""},{"line_number":206,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":207,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":208,"context_line":"        m \u003d hashlib.md5()"},{"line_number":209,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":210,"context_line":"                             data[\u0027project_id\u0027]))"},{"line_number":211,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9lI%3D","line":208,"updated":"2013-03-01 13:55:12.000000000","message":"About MD5, my initial question was more about the problem for collision or things like that. But I\u0027m not very opiniated on that, just raising the issue now so that you don\u0027t have to switch to SHA1 in a year. :)","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"59190d3c26d40ac201be50386594b4c336fb3e5c","unresolved":false,"context_lines":[{"line_number":205,"context_line":""},{"line_number":206,"context_line":"        # Rowkey consists of reversed timestamp, meter and an md5 of"},{"line_number":207,"context_line":"        # user+resource+project for purposes of uniqueness"},{"line_number":208,"context_line":"        m \u003d hashlib.md5()"},{"line_number":209,"context_line":"        m.update(\"%s%s%s\" % (data[\u0027user_id\u0027], data[\u0027resource_id\u0027],"},{"line_number":210,"context_line":"                             data[\u0027project_id\u0027]))"},{"line_number":211,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9dY%3D","line":208,"in_reply_to":"AAAANH%2F%2F9lI%3D","updated":"2013-03-01 15:05:50.000000000","message":"This is just to hash user, resource and project together. If you have better ideas, please do suggest.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":289,"context_line":"                                           require_meter\u003dFalse)"},{"line_number":290,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":291,"context_line":"        # TODO implement metaquery support"},{"line_number":292,"context_line":"        if len(metaquery) \u003e 0:"},{"line_number":293,"context_line":"            raise NotImplementedError(\u0027metaquery not implemented\u0027)"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":"        resource_ids \u003d {}"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9kw%3D","line":292,"updated":"2013-03-01 13:55:12.000000000","message":"You could raise that earlier I think.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"59190d3c26d40ac201be50386594b4c336fb3e5c","unresolved":false,"context_lines":[{"line_number":289,"context_line":"                                           require_meter\u003dFalse)"},{"line_number":290,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":291,"context_line":"        # TODO implement metaquery support"},{"line_number":292,"context_line":"        if len(metaquery) \u003e 0:"},{"line_number":293,"context_line":"            raise NotImplementedError(\u0027metaquery not implemented\u0027)"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":"        resource_ids \u003d {}"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9dQ%3D","line":292,"in_reply_to":"AAAANH%2F%2F9kw%3D","updated":"2013-03-01 15:05:50.000000000","message":"I think I\u0027ll be adding the metaquery support after this patch is merged, so this be removed.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":349,"context_line":"                                         require_meter\u003dFalse)"},{"line_number":350,"context_line":"        LOG.debug(\"q: %s\" % q)"},{"line_number":351,"context_line":"        # TODO implement metaquery support"},{"line_number":352,"context_line":"        if len(metaquery) \u003e 0:"},{"line_number":353,"context_line":"            raise NotImplementedError(\u0027metaquery not implemented\u0027)"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":"        gen \u003d self.resource.scan(filter\u003dq)"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9ks%3D","line":352,"updated":"2013-03-01 13:55:12.000000000","message":"Same as above, raise earlier.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":642,"context_line":"                          raise an error."},{"line_number":643,"context_line":"    \"\"\""},{"line_number":644,"context_line":"    if event_filter.metaquery is not None and len(event_filter.metaquery) \u003e 0:"},{"line_number":645,"context_line":"        raise NotImplementedError(\u0027metaquery not implemented\u0027)"},{"line_number":646,"context_line":""},{"line_number":647,"context_line":"    return make_query(event_filter.user, event_filter.project,"},{"line_number":648,"context_line":"                      event_filter.meter, event_filter.resource,"}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9fw%3D","line":645,"updated":"2013-03-01 13:55:12.000000000","message":"This raise is in a lot of place, wouldn\u0027t it better to move it to make_query(). I know make_query don\u0027t use metaquery yet, but it could be added as an argument nevertheless.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"6dd2d7ce485ce43defe4ddc03a502636f0ce435b","unresolved":false,"context_lines":[{"line_number":504,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":505,"context_line":"        results \u003d {}"},{"line_number":506,"context_line":"        for ignored, meter in gen:"},{"line_number":507,"context_line":"            results.setdefault(meter[\u0027f:resource_id\u0027], 0)"},{"line_number":508,"context_line":"            results[meter[\u0027f:resource_id\u0027]] \\"},{"line_number":509,"context_line":"                +\u003d int(meter[\u0027f:counter_volume\u0027])"},{"line_number":510,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2FbA%3D","line":507,"updated":"2013-03-04 13:34:36.000000000","message":"I think you can use a defaultdict here, instead of calling setdefault","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"6f5ac4621f43aaddbeb955a37d8cb27150cd8635","unresolved":false,"context_lines":[{"line_number":504,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":505,"context_line":"        results \u003d {}"},{"line_number":506,"context_line":"        for ignored, meter in gen:"},{"line_number":507,"context_line":"            results.setdefault(meter[\u0027f:resource_id\u0027], 0)"},{"line_number":508,"context_line":"            results[meter[\u0027f:resource_id\u0027]] \\"},{"line_number":509,"context_line":"                +\u003d int(meter[\u0027f:counter_volume\u0027])"},{"line_number":510,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2FSI%3D","line":507,"in_reply_to":"AAAAN3%2F%2F%2FXg%3D","updated":"2013-03-04 15:05:32.000000000","message":"Avoid a function call on each iteration. Otherwise not so much I guess.","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"f52421d114f9e1a74e9c02f68e44955365fc0605","unresolved":false,"context_lines":[{"line_number":504,"context_line":"        gen \u003d self.meter.scan(filter\u003dq, row_start\u003dstart, row_stop\u003dstop)"},{"line_number":505,"context_line":"        results \u003d {}"},{"line_number":506,"context_line":"        for ignored, meter in gen:"},{"line_number":507,"context_line":"            results.setdefault(meter[\u0027f:resource_id\u0027], 0)"},{"line_number":508,"context_line":"            results[meter[\u0027f:resource_id\u0027]] \\"},{"line_number":509,"context_line":"                +\u003d int(meter[\u0027f:counter_volume\u0027])"},{"line_number":510,"context_line":""}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2FXg%3D","line":507,"in_reply_to":"AAAAN3%2F%2F%2FbA%3D","updated":"2013-03-04 14:08:42.000000000","message":"Is there any benefit?","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"6dd2d7ce485ce43defe4ddc03a502636f0ce435b","unresolved":false,"context_lines":[{"line_number":521,"context_line":"        results \u003d {}"},{"line_number":522,"context_line":"        for ignored, meter in gen:"},{"line_number":523,"context_line":"            results.setdefault(meter[\u0027f:resource_id\u0027],"},{"line_number":524,"context_line":"                               int(meter[\u0027f:counter_volume\u0027]))"},{"line_number":525,"context_line":"            if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":526,"context_line":"                    int(meter[\u0027f:counter_volume\u0027]):"},{"line_number":527,"context_line":"                results[meter[\u0027f:resource_id\u0027]] \\"}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2Fa8%3D","line":524,"updated":"2013-03-04 13:34:36.000000000","message":"Same here.","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"8a82b3d3f1343d6fade0e18a24888aaf9422f59c","unresolved":false,"context_lines":[{"line_number":521,"context_line":"        results \u003d {}"},{"line_number":522,"context_line":"        for ignored, meter in gen:"},{"line_number":523,"context_line":"            results.setdefault(meter[\u0027f:resource_id\u0027],"},{"line_number":524,"context_line":"                               int(meter[\u0027f:counter_volume\u0027]))"},{"line_number":525,"context_line":"            if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":526,"context_line":"                    int(meter[\u0027f:counter_volume\u0027]):"},{"line_number":527,"context_line":"                results[meter[\u0027f:resource_id\u0027]] \\"}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2FRU%3D","line":524,"in_reply_to":"AAAAN3%2F%2F%2FR4%3D","updated":"2013-03-04 15:10:04.000000000","message":"No, I\u0027m doing a max, see my next patch.","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"70ea916c6f9f269ae5b6477de3b51bf831b561bc","unresolved":false,"context_lines":[{"line_number":521,"context_line":"        results \u003d {}"},{"line_number":522,"context_line":"        for ignored, meter in gen:"},{"line_number":523,"context_line":"            results.setdefault(meter[\u0027f:resource_id\u0027],"},{"line_number":524,"context_line":"                               int(meter[\u0027f:counter_volume\u0027]))"},{"line_number":525,"context_line":"            if results[meter[\u0027f:resource_id\u0027]] \u003c \\"},{"line_number":526,"context_line":"                    int(meter[\u0027f:counter_volume\u0027]):"},{"line_number":527,"context_line":"                results[meter[\u0027f:resource_id\u0027]] \\"}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2FR4%3D","line":524,"in_reply_to":"AAAAN3%2F%2F%2Fa8%3D","updated":"2013-03-04 15:07:23.000000000","message":"Actually, I don\u0027t think you want to be using a defaultdict or setdefault here, do you? You\u0027re just doing results[meter[\u0027f:resourceid\u0027]] \u003d int(meter[\u0027f:counter_volume\u0027] aren\u0027t you?","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"6dd2d7ce485ce43defe4ddc03a502636f0ce435b","unresolved":false,"context_lines":[{"line_number":594,"context_line":"    if user:"},{"line_number":595,"context_line":"        q.append(\"SingleColumnValueFilter (\u0027f\u0027, \u0027user_id\u0027, \u003d, \u0027binary:%s\u0027)\""},{"line_number":596,"context_line":"                 % user)"},{"line_number":597,"context_line":"    elif project:"},{"line_number":598,"context_line":"        q.append(\"SingleColumnValueFilter (\u0027f\u0027, \u0027project_id\u0027, \u003d, \u0027binary:%s\u0027)\""},{"line_number":599,"context_line":"                 % project)"},{"line_number":600,"context_line":"    if resource:"}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2Fa4%3D","line":597,"updated":"2013-03-04 13:34:36.000000000","message":"Woh, that looks like a bug I just fixed in the SQLAlchemy driver.\nThere\u0027s no reason for an elif here.","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"f52421d114f9e1a74e9c02f68e44955365fc0605","unresolved":false,"context_lines":[{"line_number":594,"context_line":"    if user:"},{"line_number":595,"context_line":"        q.append(\"SingleColumnValueFilter (\u0027f\u0027, \u0027user_id\u0027, \u003d, \u0027binary:%s\u0027)\""},{"line_number":596,"context_line":"                 % user)"},{"line_number":597,"context_line":"    elif project:"},{"line_number":598,"context_line":"        q.append(\"SingleColumnValueFilter (\u0027f\u0027, \u0027project_id\u0027, \u003d, \u0027binary:%s\u0027)\""},{"line_number":599,"context_line":"                 % project)"},{"line_number":600,"context_line":"    if resource:"}],"source_content_type":"text/x-python","patch_set":23,"id":"AAAAN3%2F%2F%2FXU%3D","line":597,"in_reply_to":"AAAAN3%2F%2F%2Fa4%3D","updated":"2013-03-04 14:08:42.000000000","message":"I\u0027m pretty sure this is where this \u0027elif\u0027 has been copied from... Will fix in the next patch.","commit_id":"1e2ca97ea5a9846245d5e0d6f6b53a87abacfcac"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"29b7b5c7881999a1a6ae590085e203fa7587ae64","unresolved":false,"context_lines":[{"line_number":460,"context_line":"        # but factual period will be 3599."},{"line_number":461,"context_line":"        end_time \u003d event_filter.end \\"},{"line_number":462,"context_line":"            or timeutils.parse_strtime(meters[0][\u0027f:timestamp\u0027]) +\\"},{"line_number":463,"context_line":"            datetime.timedelta(seconds\u003d1)"},{"line_number":464,"context_line":""},{"line_number":465,"context_line":"        results \u003d []"},{"line_number":466,"context_line":""}],"source_content_type":"text/x-python","patch_set":24,"id":"AAAAN3%2F%2F%2FPA%3D","line":463,"updated":"2013-03-04 15:42:53.000000000","message":"I didn\u0027t notice this in my first re-read. I don\u0027t think we should be manipulating the end_time like this.","commit_id":"34ba7bfd9710298623db9e12746f2755fb8415c9"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"4df7bb32a6655064f4277dec1bf9aa0345553343","unresolved":false,"context_lines":[{"line_number":509,"context_line":"            results[meter[\u0027f:resource_id\u0027]] \\"},{"line_number":510,"context_line":"                +\u003d int(meter[\u0027f:counter_volume\u0027])"},{"line_number":511,"context_line":""},{"line_number":512,"context_line":"        return ({\u0027resource_id\u0027: key, \u0027value\u0027: results[key]} for key in results)"},{"line_number":513,"context_line":""},{"line_number":514,"context_line":"    def get_volume_max(self, event_filter):"},{"line_number":515,"context_line":"        \"\"\"Return the maximum of the volume field for the events"}],"source_content_type":"text/x-python","patch_set":24,"id":"AAAAN3%2F%2F%2FRI%3D","line":512,"updated":"2013-03-04 15:12:08.000000000","message":"See comment on line 527 for a way to improve this expression.","commit_id":"34ba7bfd9710298623db9e12746f2755fb8415c9"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"4df7bb32a6655064f4277dec1bf9aa0345553343","unresolved":false,"context_lines":[{"line_number":524,"context_line":"            results[meter[\u0027f:resource_id\u0027]] \u003d \\"},{"line_number":525,"context_line":"                max(results[meter[\u0027f:resource_id\u0027]],"},{"line_number":526,"context_line":"                    int(meter[\u0027f:counter_volume\u0027]))"},{"line_number":527,"context_line":"        return ({\u0027resource_id\u0027: key, \u0027value\u0027: results[key]} for key in results)"},{"line_number":528,"context_line":""},{"line_number":529,"context_line":"    def get_event_interval(self, event_filter):"},{"line_number":530,"context_line":"        \"\"\"Return the min and max timestamps from events,"}],"source_content_type":"text/x-python","patch_set":24,"id":"AAAAN3%2F%2F%2FRc%3D","line":527,"updated":"2013-03-04 15:12:08.000000000","message":"It will be more efficient to iterate over results.iteritems() like this:\n\n  return ({\u0027resource_id\u0027: k, \u0027value\u0027: v} for (k, v) in results.iteritems())\n\nThat avoids looking up results[k] for each value.","commit_id":"34ba7bfd9710298623db9e12746f2755fb8415c9"}],"tests/storage/test_impl_hbase.py":[{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"63a60d041b29b2000b69eeddc9166734f7e3c8f4","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# -*- encoding: utf-8 -*-"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Copyright © 2012, 2013 Dell Inc."},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B8mI%3D","line":1,"updated":"2013-02-13 17:02:38.000000000","message":"See ceilometer/tests/storage/base.py for base classes for tests that ensure all of the storage drivers return the same types of objects from their methods.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"630c8b8cbbf209a58a50c6392b30f4623033f1ae","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# -*- encoding: utf-8 -*-"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Copyright © 2012, 2013 Dell Inc."},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B4Iw%3D","line":1,"in_reply_to":"AAAAM3%2F%2B6eg%3D","updated":"2013-02-15 18:53:07.000000000","message":"Possibly. However, the driver *needs* to support those tests so we can ensure that every driver is returning the same type of data from the API methods. We have already had issues in the past where the specification was interpreted slightly differently between the drivers for Mongo and SQLAlchemy.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"070e9a3c4a30fab869e5b9653ddd724354daa0dc","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# -*- encoding: utf-8 -*-"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Copyright © 2012, 2013 Dell Inc."},{"line_number":4,"context_line":"#"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAAM3%2F%2B6eg%3D","line":1,"in_reply_to":"AAAAM3%2F%2B8mI%3D","updated":"2013-02-14 17:05:21.000000000","message":"Unfortunately this tests refactoring to use common base has caught me off guard, and it looks like for this driver it may not be so straight-forward - a lot of mocking to be done.","commit_id":"a7fb7792038b7d6169db9d326d67b63d06d8db8f"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":49,"context_line":"CEILOMETER_TEST_LIVE \u003d bool(int(os.environ.get(\u0027CEILOMETER_TEST_LIVE\u0027, 0)))"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"# Update this to run tests against your own HBase server"},{"line_number":52,"context_line":"HBASE_URL \u003d \u0027hbase://10.21.245.85:9090\u0027"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"PROJECT_TABLE \u003d \"project\""},{"line_number":55,"context_line":"USER_TABLE \u003d \"user\""}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBA%3D","line":52,"updated":"2013-02-26 13:12:27.000000000","message":"Any chance you could use a getenv() thing rather?\nI know that I want to do this for SQLAlchemy too, this is a PITA otherwise.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":49,"context_line":"CEILOMETER_TEST_LIVE \u003d bool(int(os.environ.get(\u0027CEILOMETER_TEST_LIVE\u0027, 0)))"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"# Update this to run tests against your own HBase server"},{"line_number":52,"context_line":"HBASE_URL \u003d \u0027hbase://10.21.245.85:9090\u0027"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"PROJECT_TABLE \u003d \"project\""},{"line_number":55,"context_line":"USER_TABLE \u003d \"user\""}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl5Q%3D","line":52,"in_reply_to":"AAAAM3%2F%2BmBA%3D","updated":"2013-02-26 15:27:58.000000000","message":"Done. I added CEILOMETER_TEST_DB_URL which you are free to reuse in SQLAlchemy driver, or even refactor it into something more common.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        self.conn.create_table(METER_TABLE, {\u0027f\u0027: dict(), \u0027s\u0027: dict()})"},{"line_number":81,"context_line":"        # Real HBase needs some time to propagate create_table changes"},{"line_number":82,"context_line":"        if CEILOMETER_TEST_LIVE:"},{"line_number":83,"context_line":"            sleep(10)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def drop_schema(self):"},{"line_number":86,"context_line":"        LOG.debug(\u0027Dropping HBase schema...\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2BmBE%3D","line":83,"updated":"2013-02-26 13:12:27.000000000","message":":-(","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        self.conn.create_table(METER_TABLE, {\u0027f\u0027: dict(), \u0027s\u0027: dict()})"},{"line_number":81,"context_line":"        # Real HBase needs some time to propagate create_table changes"},{"line_number":82,"context_line":"        if CEILOMETER_TEST_LIVE:"},{"line_number":83,"context_line":"            sleep(10)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    def drop_schema(self):"},{"line_number":86,"context_line":"        LOG.debug(\u0027Dropping HBase schema...\u0027)"}],"source_content_type":"text/x-python","patch_set":15,"id":"AAAAM3%2F%2Bl5M%3D","line":83,"in_reply_to":"AAAAM3%2F%2BmBE%3D","updated":"2013-02-26 15:27:58.000000000","message":"Nothing I can do here I\u0027m afraid. Creating table in HBase is very expensive, as this storage is distributed.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"# Export this variable before running tests against real HBase"},{"line_number":52,"context_line":"# e.g. export CEILOMETER_TEST_DBURL \u003d hbase://10.21.245.85:9090"},{"line_number":53,"context_line":"CEILOMETER_TEST_DB_URL \u003d os.environ.get(\u0027CEILOMETER_TEST_DB_URL\u0027)"},{"line_number":54,"context_line":"if CEILOMETER_TEST_LIVE:"},{"line_number":55,"context_line":"    if not CEILOMETER_TEST_DB_URL:"},{"line_number":56,"context_line":"        raise RuntimeError(\"CEILOMETER_TEST_LIVE is on, but \""}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9fk%3D","line":53,"updated":"2013-03-01 13:55:12.000000000","message":"Hm, don\u0027t use something so generic? I mean, DB_URL looks like it could be also used by SQL or MongoDB.\nIf someone wants to run all tests live (I do with Mongo and SQL for example) having different variables is better.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"7db76444c161038f1f646e2c20ad2682450f0353","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"# Export this variable before running tests against real HBase"},{"line_number":52,"context_line":"# e.g. export CEILOMETER_TEST_DBURL \u003d hbase://10.21.245.85:9090"},{"line_number":53,"context_line":"CEILOMETER_TEST_DB_URL \u003d os.environ.get(\u0027CEILOMETER_TEST_DB_URL\u0027)"},{"line_number":54,"context_line":"if CEILOMETER_TEST_LIVE:"},{"line_number":55,"context_line":"    if not CEILOMETER_TEST_DB_URL:"},{"line_number":56,"context_line":"        raise RuntimeError(\"CEILOMETER_TEST_LIVE is on, but \""}],"source_content_type":"text/x-python","patch_set":20,"id":"AAAANH%2F%2F9Y0%3D","line":53,"in_reply_to":"AAAANH%2F%2F9fk%3D","updated":"2013-03-01 15:12:01.000000000","message":"Done","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"}],"tools/pip-requires":[{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"57f8bf1af87be1af74afa98216ac1d4c983f5008","unresolved":false,"context_lines":[{"line_number":22,"context_line":"wsme\u003e\u003d0.5b1"},{"line_number":23,"context_line":"pyyaml"},{"line_number":24,"context_line":"http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg\u003doslo-config"},{"line_number":25,"context_line":"happybase"}],"source_content_type":"application/octet-stream","patch_set":15,"id":"AAAAM3%2F%2BmA4%3D","line":25,"updated":"2013-02-26 13:12:27.000000000","message":"I think it\u0027d be better to put this in another file (that doesn\u0027t exist yet) with recommends. If we start depending on every driver it\u0027s going to be a PITA for packagers.\nWe should add a \u0027recommends\u0027 thing to setup.py.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"a673fe28643d7c508107c412791523537b76af11","unresolved":false,"context_lines":[{"line_number":22,"context_line":"wsme\u003e\u003d0.5b1"},{"line_number":23,"context_line":"pyyaml"},{"line_number":24,"context_line":"http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg\u003doslo-config"},{"line_number":25,"context_line":"happybase"}],"source_content_type":"application/octet-stream","patch_set":15,"id":"AAAAM3%2F%2Bl5U%3D","line":25,"in_reply_to":"AAAAM3%2F%2BmA4%3D","updated":"2013-02-26 15:27:58.000000000","message":"This is a good point, however it would be something out of the scope of this patch as it relates to pymongo and/or sqlalchemy the same way it relates to happybase.","commit_id":"ee977329fe549cd6553eaef7a363e76f49fe817d"},{"author":{"_account_id":2472,"name":"Doug Hellmann","email":"dhellmann@redhat.com","username":"doug-hellmann"},"change_message_id":"a3fdca906b26396740e5a99e01daf5dec90c5cdc","unresolved":false,"context_lines":[{"line_number":22,"context_line":"wsme\u003e\u003d0.5b1"},{"line_number":23,"context_line":"pyyaml"},{"line_number":24,"context_line":"http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg\u003doslo-config"},{"line_number":25,"context_line":"happybase"}],"source_content_type":"application/octet-stream","patch_set":16,"id":"AAAAM3%2F%2Blyc%3D","line":25,"updated":"2013-02-26 16:06:43.000000000","message":"This needs a specific version number, or range, to avoid API version conflicts later.","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"88dda7a07d85412c8de88661c9e8f484d491ce16","unresolved":false,"context_lines":[{"line_number":22,"context_line":"wsme\u003e\u003d0.5b1"},{"line_number":23,"context_line":"pyyaml"},{"line_number":24,"context_line":"http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg\u003doslo-config"},{"line_number":25,"context_line":"happybase"}],"source_content_type":"application/octet-stream","patch_set":16,"id":"AAAAM3%2F%2Bjg4%3D","line":25,"in_reply_to":"AAAAM3%2F%2Blyc%3D","updated":"2013-02-27 16:05:44.000000000","message":"Done","commit_id":"9b1afc4d65fcb7b187a36ea467f2ed898e98d36b"},{"author":{"_account_id":1669,"name":"Julien Danjou","display_name":"jd","email":"julien@danjou.info","username":"jdanjou"},"change_message_id":"7c7121382fb1f416729f572c0af3e33a2fc8773b","unresolved":false,"context_lines":[{"line_number":22,"context_line":"wsme\u003e\u003d0.5b1"},{"line_number":23,"context_line":"pyyaml"},{"line_number":24,"context_line":"http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg\u003doslo-config"},{"line_number":25,"context_line":"happybase\u003d\u003d0.4"}],"source_content_type":"application/octet-stream","patch_set":20,"id":"AAAANH%2F%2F9fg%3D","line":25,"updated":"2013-03-01 13:55:12.000000000","message":"I don\u0027t know if happybase is a special case, but \u003e\u003d 0.4 is likely to be better.","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"},{"author":{"_account_id":6682,"name":"Stas Maksimov","email":"maksimov@gmail.com","username":"maksimov"},"change_message_id":"7db76444c161038f1f646e2c20ad2682450f0353","unresolved":false,"context_lines":[{"line_number":22,"context_line":"wsme\u003e\u003d0.5b1"},{"line_number":23,"context_line":"pyyaml"},{"line_number":24,"context_line":"http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg\u003doslo-config"},{"line_number":25,"context_line":"happybase\u003d\u003d0.4"}],"source_content_type":"application/octet-stream","patch_set":20,"id":"AAAANH%2F%2F9Y8%3D","line":25,"in_reply_to":"AAAANH%2F%2F9fg%3D","updated":"2013-03-01 15:12:01.000000000","message":"Done","commit_id":"145911666d12c332bd0828eff06d52010d0a7c8f"}]}
