{ "info": { "author": "Hugo Rodger-Brown", "author_email": "hugo@rodger-brown.com", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2.7" ], "description": "Python-Errordite\r\n================\r\n\r\nThis app provides integration between Python and Errordite, a centralised\r\nerror logging and management service, not unlike Sentry, but with more\r\nfunctionality around the classification and management of errors.\r\n\r\nThe application is provided in the form of a standard Python logging handler.\r\nIn order to log exceptions with Errordite, you simply use ``logging.error`` or\r\n``logging.exception`` in your ``except`` block::\r\n\r\n >>> import logging\r\n >>> import errordite\r\n >>> logger = logging.getLogger(__name__)\r\n >>> logger.addHandler(errordite.ErrorditeHandler('token'))\r\n >>> try:\r\n ... raise Exception()\r\n ... except:\r\n ... # handler uses sys.exc_info() so no need to pass\r\n ... # exception info explicitly.\r\n ... logging.error(\"Something went wrong\")\r\n >>>\r\n\r\nDetails of the implementation are best found in the code itself - it's fairly\r\nself-explanatory.\r\n\r\n**Important info regarding sys.exc_info() and sys.exc_clear()**\r\n\r\nThis logging handler is explicitly designed to capture and publish Python\r\nexceptions. It is not a generic logger, and as such it relies on the use of\r\n``sys.exc_info()`` to determine whether there is anything to report. This can\r\nhave an unexpected effect if you are logging items as errors that have no\r\nexplicit exception attached, but where a previous exception has been swallowed.\r\n\r\nIn the example below - we are catching and swallowing the DoesNotExist error\r\nbecause it's a known code path::\r\n\r\n try:\r\n .. do something that raises a known error - e.g. model.DoesNotExist\r\n except model.DoesNotExist:\r\n .. we half expected this, so just ignore it for now\r\n\r\nHowever, the exception has not been cleared, and if you call ``sys.exc_info()``\r\nfurther on it will still return the DoesNotExist error. A little further on in\r\nour example we are logging a business exception (trying to checkout a negative\r\nbasket value) but not attaching any explicit python error::\r\n\r\n .. continue on with the method\r\n\r\n .. some time later\r\n\r\n if basket_total < 0:\r\n logger.error(\"Someone tried to hack our checkout.\")\r\n\r\n**In this case the wrong exception (DoesNotExist) information will be recorded.**\r\n\r\nThe solution to this is to call ``sys.exc_clear()`` in the ``except`` block\r\nso that the exception is removed explicitly. The Python docs state that:\r\n\r\n *This function is only needed in only a few obscure situations.*\r\n\r\nWhich suggest that this is not recommended, however, they go on to state:\r\n\r\n *These include logging and error handling systems that report information\r\n on the last or current exception.*\r\n\r\n**It is the author's opinion** that this describes our exact predicament,\r\nand so the use of ``sys.exc_clear()`` is justified. (That said, you may also\r\nwant to investigate why you are logging errors that aren't exceptions if\r\nyou see this situation occurring.)\r\n\r\nInstallation\r\n------------\r\n\r\nThe library is available at pypi as 'errordite', and can therefore be\r\ninstalled using pip::\r\n \r\n $ pip install errordite\r\n\r\nOnce installed you can import the handler::\r\n\r\n >>> import errordite\r\n >>> handler = errordite.ErrorditeHandler(\"your_errordite_token\")\r\n\r\nConfiguration\r\n-------------\r\n\r\nIn order to set up a valid **ErrorditeHandler** you must pass in an\r\nErrordite API token, which you can get by signing up at http://www.errordite.com\r\n\r\nTests\r\n-----\r\n\r\nThere are tests in the package - they can be run using ``unittest``::\r\n\r\n $ python -m unittest errordite.tests\r\n\r\nNB These tests do log real exceptions over the wire, so you will need to be\r\nconnected to the web to run them. You will also need to set a local environment\r\nvariable (**ERRORDITE_TOKEN**), which is picked up in the test suite.\r\n\r\nIf you are \\*nix you can pass this in on the command line::\r\n\r\n $ ERRORDITE_TOKEN=123 python -m unittest errordite.tests\r\n\r\nIf you are on Windows you'll need to set it up explicitly as an env var::\r\n\r\n c:\\> set ERRORDITE_TOKEN=123\r\n c:\\> python -m unittest errordite.tests\r\n\r\n(This is a technique used to prevent having to have sensitive information in\r\nthe public repo.)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/yunojuno/python-errordite", "keywords": "", "license": "Copyright (c) 2013, Hugo Rodger-Brown\r\nAll rights reserved.\r\n\r\nRedistribution and use in source and binary forms, with or without\r\nmodification, are permitted provided that the following conditions are met: \r\n\r\n1. Redistributions of source code must retain the above copyright notice, this\r\n list of conditions and the following disclaimer. \r\n2. Redistributions in binary form must reproduce the above copyright notice,\r\n this list of conditions and the following disclaimer in the documentation\r\n and/or other materials provided with the distribution. \r\n\r\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\r\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", "maintainer": "", "maintainer_email": "", "name": "errordite", "package_url": "https://pypi.org/project/errordite/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/errordite/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/yunojuno/python-errordite" }, "release_url": "https://pypi.org/project/errordite/0.5.1/", "requires_dist": null, "requires_python": null, "summary": "Errordite exception logging.", "version": "0.5.1" }, "last_serial": 725059, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "0bc42c2351697de0946abad2bac1e3f8", "sha256": "4df19e2571c463350a50579ffb9ffc772c78c75d510b7eb2a601849212e03346" }, "downloads": -1, "filename": "errordite-0.1.tar.gz", "has_sig": false, "md5_digest": "0bc42c2351697de0946abad2bac1e3f8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4483, "upload_time": "2013-03-01T18:19:01", "url": "https://files.pythonhosted.org/packages/e9/4b/2b35b0f3be081e19aa466cce172554ff509b96517a427cf0b51c68eef568/errordite-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "ac71a28dcd7e8e119f9ae3ca65bd0942", "sha256": "7a4600dd4f99a480a8df555e5878f4d7b51536857ff81327814693bede2768b6" }, "downloads": -1, "filename": "errordite-0.2.zip", "has_sig": false, "md5_digest": "ac71a28dcd7e8e119f9ae3ca65bd0942", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10579, "upload_time": "2013-03-02T12:22:44", "url": "https://files.pythonhosted.org/packages/c9/d5/69b06f8c50d6e7fbd66ac3cb914b34f2c0181b3c4c7d30938e4c0cfd1137/errordite-0.2.zip" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "e5b45f8c242db7eadc9d410d1cd109fc", "sha256": "b9d2e4edfea98574fa76925287411b3910e3a678eb30adc5c67dd874c4f3cd85" }, "downloads": -1, "filename": "errordite-0.2.1.zip", "has_sig": false, "md5_digest": "e5b45f8c242db7eadc9d410d1cd109fc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10788, "upload_time": "2013-03-02T12:33:55", "url": "https://files.pythonhosted.org/packages/9b/09/56d6069148b9043a254e522be90482c5345834a87b88a569851a954bd677/errordite-0.2.1.zip" } ], "0.2.2": [ { "comment_text": "", "digests": { "md5": "87c89cdb6d547685810fd2fd566ccc51", "sha256": "d95b71c9c26cc3be3b42d76903fbc07ac1ee5d3395c60a7cbc323b7428c45942" }, "downloads": -1, "filename": "errordite-0.2.2.zip", "has_sig": false, "md5_digest": "87c89cdb6d547685810fd2fd566ccc51", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10827, "upload_time": "2013-03-02T12:39:02", "url": "https://files.pythonhosted.org/packages/30/7f/82e7a7beb5a91cde1564a945ded1a919c4f2172139331cfceec15c44f1b8/errordite-0.2.2.zip" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "fe58c7959ed7d75dd2b07d2be674607c", "sha256": "aca72f287650d6e75d85c2804c8860fbe94fc4e55b91fb1405606c124e75cf1b" }, "downloads": -1, "filename": "errordite-0.3.zip", "has_sig": false, "md5_digest": "fe58c7959ed7d75dd2b07d2be674607c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10758, "upload_time": "2013-03-02T12:50:39", "url": "https://files.pythonhosted.org/packages/83/9f/7d97df7b589a84cd6133d50a8c009cf6b900c39ba969bec63471af58fd43/errordite-0.3.zip" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "39f70279891c493baa89255bb67bd60d", "sha256": "f9d1c2d4784399a6896aea6bc6ac8dc18fba935bdb4d14f70bce6533fce81b32" }, "downloads": -1, "filename": "errordite-0.4.zip", "has_sig": false, "md5_digest": "39f70279891c493baa89255bb67bd60d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11023, "upload_time": "2013-03-03T11:06:43", "url": "https://files.pythonhosted.org/packages/90/bf/7044fff08b670a0c92b1825fba50d116a691636e18b9c50206b9b148e358/errordite-0.4.zip" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "6ea1d8c00ac9e21caa70b5c5d061f2c9", "sha256": "b2f613dab1acf53fbc6e32a62eecefab444c2f239c10587913c7f5808a777de4" }, "downloads": -1, "filename": "errordite-0.5.tar.gz", "has_sig": false, "md5_digest": "6ea1d8c00ac9e21caa70b5c5d061f2c9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5407, "upload_time": "2013-03-03T20:29:21", "url": "https://files.pythonhosted.org/packages/54/19/bd52c3c72fc2be9d9fd91522303ce376528a319f7d791dd9fe1b2f40c3b2/errordite-0.5.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "a3402da167ace58bd7d8f5b99bf60496", "sha256": "19cb7e694902fb09c7048aff7e111de3aa514d8dc73d0b2fe61fccbc7a77c9ca" }, "downloads": -1, "filename": "errordite-0.5.1.tar.gz", "has_sig": false, "md5_digest": "a3402da167ace58bd7d8f5b99bf60496", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6294, "upload_time": "2013-03-06T17:16:40", "url": "https://files.pythonhosted.org/packages/90/a7/6f405c86c459babf32e9e81e3163e776618b0764891c8b8cc0deca082e7c/errordite-0.5.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a3402da167ace58bd7d8f5b99bf60496", "sha256": "19cb7e694902fb09c7048aff7e111de3aa514d8dc73d0b2fe61fccbc7a77c9ca" }, "downloads": -1, "filename": "errordite-0.5.1.tar.gz", "has_sig": false, "md5_digest": "a3402da167ace58bd7d8f5b99bf60496", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6294, "upload_time": "2013-03-06T17:16:40", "url": "https://files.pythonhosted.org/packages/90/a7/6f405c86c459babf32e9e81e3163e776618b0764891c8b8cc0deca082e7c/errordite-0.5.1.tar.gz" } ] }