{"action":"created","issue":{"url":"https://api.github.com/repos/inconshreveable/sqltap/issues/20","labels_url":"https://api.github.com/repos/inconshreveable/sqltap/issues/20/labels{/name}","comments_url":"https://api.github.com/repos/inconshreveable/sqltap/issues/20/comments","events_url":"https://api.github.com/repos/inconshreveable/sqltap/issues/20/events","html_url":"https://github.com/inconshreveable/sqltap/pull/20","id":80162140,"number":20,"title":"Implement sqltap text reporter","user":{"login":"stanzgy","id":289564,"avatar_url":"https://avatars.githubusercontent.com/u/289564?v=3","gravatar_id":"","url":"https://api.github.com/users/stanzgy","html_url":"https://github.com/stanzgy","followers_url":"https://api.github.com/users/stanzgy/followers","following_url":"https://api.github.com/users/stanzgy/following{/other_user}","gists_url":"https://api.github.com/users/stanzgy/gists{/gist_id}","starred_url":"https://api.github.com/users/stanzgy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stanzgy/subscriptions","organizations_url":"https://api.github.com/users/stanzgy/orgs","repos_url":"https://api.github.com/users/stanzgy/repos","events_url":"https://api.github.com/users/stanzgy/events{/privacy}","received_events_url":"https://api.github.com/users/stanzgy/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-05-24T13:28:20Z","updated_at":"2015-05-24T13:30:44Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/inconshreveable/sqltap/pulls/20","html_url":"https://github.com/inconshreveable/sqltap/pull/20","diff_url":"https://github.com/inconshreveable/sqltap/pull/20.diff","patch_url":"https://github.com/inconshreveable/sqltap/pull/20.patch"},"body":"* fix two bugs including #17 \r\n* add Reporter class so we could get various ways to do a sqltap report.\r\n* add TextReporter and text.mako template to generate text report\r\n* refact sqltap.report() so we can make html/wsgi/text report now\r\n* sqltap.report() testcases updated"},"comment":{"url":"https://api.github.com/repos/inconshreveable/sqltap/issues/comments/105016519","html_url":"https://github.com/inconshreveable/sqltap/pull/20#issuecomment-105016519","issue_url":"https://api.github.com/repos/inconshreveable/sqltap/issues/20","id":105016519,"user":{"login":"stanzgy","id":289564,"avatar_url":"https://avatars.githubusercontent.com/u/289564?v=3","gravatar_id":"","url":"https://api.github.com/users/stanzgy","html_url":"https://github.com/stanzgy","followers_url":"https://api.github.com/users/stanzgy/followers","following_url":"https://api.github.com/users/stanzgy/following{/other_user}","gists_url":"https://api.github.com/users/stanzgy/gists{/gist_id}","starred_url":"https://api.github.com/users/stanzgy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stanzgy/subscriptions","organizations_url":"https://api.github.com/users/stanzgy/orgs","repos_url":"https://api.github.com/users/stanzgy/repos","events_url":"https://api.github.com/users/stanzgy/events{/privacy}","received_events_url":"https://api.github.com/users/stanzgy/received_events","type":"User","site_admin":false},"created_at":"2015-05-24T13:30:44Z","updated_at":"2015-05-24T13:30:44Z","body":"Text report test script:\r\n```\r\nfrom sqlalchemy import *\r\n\r\nimport sqltap\r\n\r\nif __name__ == '__main__':\r\n\r\n    engine = create_engine('sqlite://')\r\n\r\n    m1 = MetaData(engine)\r\n    t1 = Table(\"sometable\", m1,\r\n            Column(\"id\", Integer, primary_key=True),\r\n            Column(\"data\", String(255), nullable=False))\r\n\r\n    conn = engine.connect()\r\n    m1.create_all(conn)\r\n\r\n    profiler = sqltap.start()\r\n\r\n    conn.execute(\r\n        t1.insert(),\r\n        [{\"data\": \"entry %d\" % x} for x in xrange(100000)]\r\n    )\r\n\r\n    conn.execute(\r\n        t1.select().where(t1.c.data.between(\"entry 25\", \"entry 7800\")).order_by(desc(t1.c.data))\r\n    )\r\n    conn.execute(\r\n        t1.select().where(t1.c.data.between(\"entry 25\", \"entry 7800\")).order_by(desc(t1.c.data))\r\n    )\r\n    conn.execute(\r\n        t1.select().where(t1.c.data.between(\"entry 300\", \"entry 7800\")).order_by(desc(t1.c.data))\r\n    )\r\n\r\n\r\n    stat = profiler.collect()\r\n    sqltap.report(stat, \"report.txt\", report_format=\"text\")\r\n```\r\n\r\nsample result:\r\n```\r\n\r\n========================================================================\r\n======                  SQLTap Profiling Report                   ======\r\n========================================================================\r\nReport Generated Time: 2015-05-24 21:18:12.727911\r\n\r\n========================================================================\r\n======                          Summary                           ======\r\n========================================================================\r\nTotal queries: 4\r\nTotal time: 0.57 second(s)\r\n\r\n========================================================================\r\n======                          Details                           ======\r\n========================================================================\r\n\r\n============                  QueryGroup 0                  ============\r\n------------              QueryGroup 0 summary              ------------\r\nQuery count: 1\r\nQuery max time: 0.468 second(s)\r\nQuery min time: 0.468 second(s)\r\nQuery mean time: 0.468 second(s)\r\nQuery median time: 0.468 second(s)\r\n\r\n------------            QueryGroup 0 SQL pattern            ------------\r\nINSERT INTO sometable (id, data)\r\nVALUES (?,\r\n        ?)\r\n\r\n------------             QueryGroup 0 breakdown             ------------\r\nQuery 0:\r\n  Query duration: 0.468 second(s)\r\n  Query params:\r\n    data: None\r\n    id: None\r\n\r\n------------              QueryGroup 0 stacks               ------------\r\nTotal unique stack(s) issued this QueryGroup: 1\r\n\r\n\r\nStack 0:\r\n  1 call(s) from <module> @sqlt.py:21\r\n  Traceback:\r\n      File \"sqlt.py\", line 21, in <module>\r\n        [{\"data\": \"entry %d\" % x} for x in xrange(100000)]\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 914, in execute\r\n        return meth(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/sql/elements.py\", line 323, in _execute_on_connection\r\n        return connection._execute_clauseelement(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 1014, in _execute_clauseelement\r\n        elem, multiparams, params, ret)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/event/attr.py\", line 258, in __call__\r\n        fn(*args, **kw)\r\n\r\n============                  QueryGroup 1                  ============\r\n------------              QueryGroup 1 summary              ------------\r\nQuery count: 3\r\nQuery max time: 0.037 second(s)\r\nQuery min time: 0.032 second(s)\r\nQuery mean time: 0.034 second(s)\r\nQuery median time: 0.033 second(s)\r\n\r\n------------            QueryGroup 1 SQL pattern            ------------\r\nSELECT sometable.id,\r\n       sometable.data\r\nFROM sometable\r\nWHERE sometable.data BETWEEN ? AND ?\r\nORDER BY sometable.data DESC\r\n\r\n------------             QueryGroup 1 breakdown             ------------\r\nQuery 0:\r\n  Query duration: 0.032 second(s)\r\n  Query params:\r\n    data_2: entry 7800\r\n    data_1: entry 300\r\nQuery 1:\r\n  Query duration: 0.037 second(s)\r\n  Query params:\r\n    data_2: entry 7800\r\n    data_1: entry 25\r\nQuery 2:\r\n  Query duration: 0.033 second(s)\r\n  Query params:\r\n    data_2: entry 7800\r\n    data_1: entry 25\r\n\r\n------------              QueryGroup 1 stacks               ------------\r\nTotal unique stack(s) issued this QueryGroup: 3\r\n\r\n\r\nStack 0:\r\n  1 call(s) from <module> @sqlt.py:31\r\n  Traceback:\r\n      File \"sqlt.py\", line 31, in <module>\r\n        t1.select().where(t1.c.data.between(\"entry 300\", \"entry 7800\")).order_by(desc(t1.c.data))\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 914, in execute\r\n        return meth(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/sql/elements.py\", line 323, in _execute_on_connection\r\n        return connection._execute_clauseelement(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 1014, in _execute_clauseelement\r\n        elem, multiparams, params, ret)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/event/attr.py\", line 258, in __call__\r\n        fn(*args, **kw)\r\n\r\nStack 1:\r\n  1 call(s) from <module> @sqlt.py:28\r\n  Traceback:\r\n      File \"sqlt.py\", line 28, in <module>\r\n        t1.select().where(t1.c.data.between(\"entry 25\", \"entry 7800\")).order_by(desc(t1.c.data))\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 914, in execute\r\n        return meth(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/sql/elements.py\", line 323, in _execute_on_connection\r\n        return connection._execute_clauseelement(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 1014, in _execute_clauseelement\r\n        elem, multiparams, params, ret)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/event/attr.py\", line 258, in __call__\r\n        fn(*args, **kw)\r\n\r\nStack 2:\r\n  1 call(s) from <module> @sqlt.py:25\r\n  Traceback:\r\n      File \"sqlt.py\", line 25, in <module>\r\n        t1.select().where(t1.c.data.between(\"entry 25\", \"entry 7800\")).order_by(desc(t1.c.data))\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 914, in execute\r\n        return meth(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/sql/elements.py\", line 323, in _execute_on_connection\r\n        return connection._execute_clauseelement(self, multiparams, params)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py\", line 1014, in _execute_clauseelement\r\n        elem, multiparams, params, ret)\r\n      File \"/Users/stanzgy/workspace/openstack/devscripts/sql/.venv/lib/python2.7/site-packages/sqlalchemy/event/attr.py\", line 258, in __call__\r\n        fn(*args, **kw)\r\n\r\n```"}}