{ "info": { "author": "Robert Brewer", "author_email": "dev@crunch.io", "bugtrack_url": null, "classifiers": [], "description": "# Diagnose\n\nA library for instrumenting Python code at runtime.\n\n## Probes\n\nStructured logs and metrics and observability are great, but almost always\nrequire you to alter your code, which interrupts the flow when reading code.\nIt also typically requires a build cycle to alter; it's no fun making a ticket,\ngetting review, waiting for a build and deploy, and then doing it all again\nto back out your temporary additions. This is doubly true when doing research,\nwhere you might perform a dozen small experiments to measure your live code.\n\nThis library allows you to dynamically add probes at runtime instead.\nProbes are:\n* reliable: errors will never affect your production code\n* ephemeral: set a \"lifespan\" (in minutes) for each instrument\n* comprehensive: all references to the target function are instrumented\n* fast: measure most functions with fast local lookups; uses hunter (in Cython) for more invasive internal probes.\n\nIndividual probes can be created directly by calling `attach_to(target)`:\n\n```#python\n>>> from path.to.module import myclass\n>>> myclass().add13(arg=5)\n18\n>>> p = diagnose.probes.attach_to(\"path.to.module.myclass.add13\")\n>>> p.instruments[\"foo\"] = diagnose.LogInstrument(\"foo\", \"arg\")\n>>> p.start()\n>>> myclass().add13(arg=5)\nProbe (foo) = 5\n18\n```\n\nInstruments aren't limited to recording devices! Use probes to fire off any kind of event handler. Instruments are free to maintain state themselves, or read it from somewhere else, to control their own behavior or even implement feedback mechanisms. A truly evil instrument could even alter the args/kwargs passed to a function on the fly, or call arbitrary Python code to do any number of crazy things. Consequently, it's up to you to govern what instruments are added to your environment.\n\n## Managers\n\nIn a running system, we want to add, remove, start, and stop probes and instruments without having to code at an interactive prompt or restart the system; we do this with an InstrumentManager. Start by configuring the global diagnose.manager:\n\n```#python\n>>> diagnose.manager.instrument_classes = {\n \"log\": LogInstrument,\n \"hist\": MyHistogramInstrument,\n \"incr\": MyIncrementInstrument,\n}\n>>> diagnose.manager.global_namespace.update({\"foo\": foo})\n```\n\nLater, you can define instruments:\n\n```#python\n>>> diagnose.manager.specs[\"instr-1\"] = {\n \"target\": \"myapp.module.file.class.method\",\n \"instrument\": {\n \"type\": \"log\",\n \"name\": \"myapp.method\",\n \"value\": \"result\",\n \"event\": \"return\",\n \"custom\": {},\n },\n \"lifespan\": 10,\n \"lastmodified\": datetime.datetime.utcnow(),\n \"applied\": {},\n}\n```\n\nThen call `diagnose.manager.apply()`, either when you add an instrument, or on a schedule if your store is in MongoDB and the process defining probes is not the target process.\n\nThe `applied` dictionary will be filled with information about which processes\nhave applied the probe, and whether they encountered any errors.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Crunch-io/diagnose", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "diagnose", "package_url": "https://pypi.org/project/diagnose/", "platform": "", "project_url": "https://pypi.org/project/diagnose/", "project_urls": { "Homepage": "https://github.com/Crunch-io/diagnose" }, "release_url": "https://pypi.org/project/diagnose/2.1.1/", "requires_dist": [ "hunter (>=2.2.0)", "mock" ], "requires_python": "", "summary": "A library for instrumenting Python code at runtime.", "version": "2.1.1" }, "last_serial": 5876533, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "5159c50b3465b10c51231e649628fc58", "sha256": "4ad526bfa3cfe8fe91b7b1540f08ec72ed31fbedb1da380a58d568f39844b314" }, "downloads": -1, "filename": "diagnose-1.0.0-py2-none-any.whl", "has_sig": false, "md5_digest": "5159c50b3465b10c51231e649628fc58", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 11625, "upload_time": "2019-07-03T21:38:32", "url": "https://files.pythonhosted.org/packages/16/dc/9102ec57f93d57f8bff2435746b9dd5d9053437b9b2cb4c06272ed8a27c8/diagnose-1.0.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e9b10c7de1b4ad72c42b5476ff28d47a", "sha256": "03e40f167c69c017b26891389c58b3f55d4e3d676a4d77783e260821ff333ff8" }, "downloads": -1, "filename": "diagnose-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e9b10c7de1b4ad72c42b5476ff28d47a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12299, "upload_time": "2019-07-03T21:38:34", "url": "https://files.pythonhosted.org/packages/8d/28/e5f2deb614d04700bad09275c6153d8bca27f5faedaf4e679a8dceafc364/diagnose-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a1fb1a25a0247d47c389462a1c6cbd43", "sha256": "678a1d2da2344a5acbcb5e159799abb62b2f6f19e3bbc83265bc413b186a3bf7" }, "downloads": -1, "filename": "diagnose-1.0.0.tar.gz", "has_sig": false, "md5_digest": "a1fb1a25a0247d47c389462a1c6cbd43", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9854, "upload_time": "2019-07-03T21:38:36", "url": "https://files.pythonhosted.org/packages/16/6b/3bb0c5c384e03ad1f56854ceb70e87cd13a24b30012dd0b16d2c9a747f51/diagnose-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "615443ea04a1be67500d7bbbc7903aa9", "sha256": "f03eea4a9c27a934d9959b0052bd0d0447e1175af5ea3029b920c3a4979030ce" }, "downloads": -1, "filename": "diagnose-1.0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "615443ea04a1be67500d7bbbc7903aa9", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 13663, "upload_time": "2019-07-03T21:57:03", "url": "https://files.pythonhosted.org/packages/ad/6b/664caef620cff3bc7e1e1944e7453a37a05aa669c5743492f9b8b5bce0f7/diagnose-1.0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "36cb7190b0b903ee492f3bcb415edb7a", "sha256": "0af412e40dd9f8b292cc0501e3c2ee99e67aa58901842c1f81232b6b1fe52321" }, "downloads": -1, "filename": "diagnose-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "36cb7190b0b903ee492f3bcb415edb7a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12412, "upload_time": "2019-07-03T22:00:23", "url": "https://files.pythonhosted.org/packages/25/39/7f595b1dfd9539fa3b27fd7d7b66ea5ba9b7a18fdcadb6fa46fc708525c9/diagnose-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "987165daa5e85391a159bc87bc4170d2", "sha256": "f9114ed184ce68d90afe668213160de33256c83c240d098c475226c459d600c9" }, "downloads": -1, "filename": "diagnose-1.0.1.tar.gz", "has_sig": false, "md5_digest": "987165daa5e85391a159bc87bc4170d2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11150, "upload_time": "2019-07-03T22:00:15", "url": "https://files.pythonhosted.org/packages/1c/35/945edd1571d2d4165a198f6032e396e0c718d397bdb74d165797c2f38d7e/diagnose-1.0.1.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "14ba5a321e3ab42023391bb4cf992496", "sha256": "152809d98d29dfe69abfc7a482c4b328fdcbb65ebdd1030cb05cdf0caf1b188b" }, "downloads": -1, "filename": "diagnose-2.0.0-py2-none-any.whl", "has_sig": false, "md5_digest": "14ba5a321e3ab42023391bb4cf992496", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 14041, "upload_time": "2019-07-05T21:53:31", "url": "https://files.pythonhosted.org/packages/e8/6a/a447a9b9add86bc218b35c8513349f55fedde5aa8b47f7c3ee277f572892/diagnose-2.0.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "80355a95887fb31c816c8fa3691ab630", "sha256": "519ddd5f835a5dd4a002edb65a4390d5bf3856a71f229f1412fbf42ba2902d0b" }, "downloads": -1, "filename": "diagnose-2.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "80355a95887fb31c816c8fa3691ab630", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12793, "upload_time": "2019-07-05T21:54:37", "url": "https://files.pythonhosted.org/packages/27/0e/7aaa93ff1d8929035b7d19fba349ab56214becd9fb153f0d95882ff812ac/diagnose-2.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ac4740358c3a9a275b17d0be7fc5cc82", "sha256": "387623af105c576745a3a5b735d142fb6bcb16b4de51dc0246d282025dd8493e" }, "downloads": -1, "filename": "diagnose-2.0.0.tar.gz", "has_sig": false, "md5_digest": "ac4740358c3a9a275b17d0be7fc5cc82", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12587, "upload_time": "2019-07-05T21:53:21", "url": "https://files.pythonhosted.org/packages/0c/ba/3491289761274a025e8a7a79ced71f4ba40c2df32c3f374204c19ef512ca/diagnose-2.0.0.tar.gz" } ], "2.1.0": [ { "comment_text": "", "digests": { "md5": "7f9004c316ad7d0b14fa2726ce4764c7", "sha256": "9e3e237d82e9ceb8722eb0d0da23eb70ffdcbb333149e68a5ca0f2e8c2e3b733" }, "downloads": -1, "filename": "diagnose-2.1.0-py2-none-any.whl", "has_sig": false, "md5_digest": "7f9004c316ad7d0b14fa2726ce4764c7", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 14443, "upload_time": "2019-07-11T01:17:43", "url": "https://files.pythonhosted.org/packages/27/0c/00ccf98bf8fdac5677bc4a7f1a5d1027fd4c8a4d3fd00b6fe81b3fea348c/diagnose-2.1.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "78cbe8b3d50c0a11ddb72ba9f6ea89da", "sha256": "81085b3e8f86031b7484e0f2d07a722fa3342dc1178f628548a29fc4796477e5" }, "downloads": -1, "filename": "diagnose-2.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "78cbe8b3d50c0a11ddb72ba9f6ea89da", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12954, "upload_time": "2019-07-11T01:18:24", "url": "https://files.pythonhosted.org/packages/9d/e0/07e675c8596d8b6269a2e836063186c5cb1368588df042d37bf74fb41bbc/diagnose-2.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "58300ad579819d67f88c7f605f5d327f", "sha256": "6b53ee310767088fb36383040bc5dfb74ca39f9f018388d0a2256305e8f9eabe" }, "downloads": -1, "filename": "diagnose-2.1.0.tar.gz", "has_sig": false, "md5_digest": "58300ad579819d67f88c7f605f5d327f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13263, "upload_time": "2019-07-11T01:17:56", "url": "https://files.pythonhosted.org/packages/24/d2/2466462e6f11f266a94806d725e8dc641fbd6f0e8ea3ab436203f89c6c15/diagnose-2.1.0.tar.gz" } ], "2.1.1": [ { "comment_text": "", "digests": { "md5": "524019ab089560e3337a24d759a04c98", "sha256": "a6e592803a27b22f557dd0dcf22bfc1368d8842bd438a2db2cbb044b806527c3" }, "downloads": -1, "filename": "diagnose-2.1.1-py2-none-any.whl", "has_sig": false, "md5_digest": "524019ab089560e3337a24d759a04c98", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 14738, "upload_time": "2019-09-23T22:59:08", "url": "https://files.pythonhosted.org/packages/dd/dd/45f5ebca2ceb1c768fce9e6e05ba8f50a7bd27bb7aa98399da94a91078ab/diagnose-2.1.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c2ccbeae658e26ccbef36e82b8ed6624", "sha256": "57ff94f15f2463cc5954b6016a5640909ed34a7c5ff5def51946a21ec50accfc" }, "downloads": -1, "filename": "diagnose-2.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "c2ccbeae658e26ccbef36e82b8ed6624", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13253, "upload_time": "2019-09-23T23:02:23", "url": "https://files.pythonhosted.org/packages/ce/a2/d139a4e771d2ba77ff1f46e9f8a7a2ab09a9ff5b089e8b03c92eaf102808/diagnose-2.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c5d431f3eae05784bc640af7cfc1ce88", "sha256": "fd0f904e077e61758a398f1ec9c81c62bb870d04811973d52a5c698dd479d615" }, "downloads": -1, "filename": "diagnose-2.1.1.tar.gz", "has_sig": false, "md5_digest": "c5d431f3eae05784bc640af7cfc1ce88", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13470, "upload_time": "2019-09-23T22:59:27", "url": "https://files.pythonhosted.org/packages/9a/e8/27b61a90168128aafc86cc7c53b5076059151e18d8b77e473af1f35505a3/diagnose-2.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "524019ab089560e3337a24d759a04c98", "sha256": "a6e592803a27b22f557dd0dcf22bfc1368d8842bd438a2db2cbb044b806527c3" }, "downloads": -1, "filename": "diagnose-2.1.1-py2-none-any.whl", "has_sig": false, "md5_digest": "524019ab089560e3337a24d759a04c98", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 14738, "upload_time": "2019-09-23T22:59:08", "url": "https://files.pythonhosted.org/packages/dd/dd/45f5ebca2ceb1c768fce9e6e05ba8f50a7bd27bb7aa98399da94a91078ab/diagnose-2.1.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c2ccbeae658e26ccbef36e82b8ed6624", "sha256": "57ff94f15f2463cc5954b6016a5640909ed34a7c5ff5def51946a21ec50accfc" }, "downloads": -1, "filename": "diagnose-2.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "c2ccbeae658e26ccbef36e82b8ed6624", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13253, "upload_time": "2019-09-23T23:02:23", "url": "https://files.pythonhosted.org/packages/ce/a2/d139a4e771d2ba77ff1f46e9f8a7a2ab09a9ff5b089e8b03c92eaf102808/diagnose-2.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c5d431f3eae05784bc640af7cfc1ce88", "sha256": "fd0f904e077e61758a398f1ec9c81c62bb870d04811973d52a5c698dd479d615" }, "downloads": -1, "filename": "diagnose-2.1.1.tar.gz", "has_sig": false, "md5_digest": "c5d431f3eae05784bc640af7cfc1ce88", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13470, "upload_time": "2019-09-23T22:59:27", "url": "https://files.pythonhosted.org/packages/9a/e8/27b61a90168128aafc86cc7c53b5076059151e18d8b77e473af1f35505a3/diagnose-2.1.1.tar.gz" } ] }