{"componentChunkName":"component---src-templates-doc-tsx","path":"/clients/python/breadcrumbs/","result":{"data":{"file":{"id":"ea9b1172-6ef9-5509-9b09-2af722f57b2f","relativePath":"clients/python/breadcrumbs.mdx","sourceInstanceName":"docs","childMarkdownRemark":null,"childMdx":{"body":"function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"draft\": false,\n  \"categories\": [],\n  \"toc\": true,\n  \"title\": \"Logging Breadcrumbs\",\n  \"sidebar_order\": 2,\n  \"noindex\": true,\n  \"tags\": []\n};\n\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\n\nvar CodeTabs = makeShortcode(\"CodeTabs\");\nvar CodeBlock = makeShortcode(\"CodeBlock\");\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Newer Sentry versions support logging of breadcrumbs in addition of errors. This means that whenever an error or other Sentry event is submitted to the system, breadcrumbs that were logged before are sent along to make it easier to reproduce what lead up to an error.\"), mdx(\"p\", null, \"In the default configuration the Python client instruments the logging framework and a few popular libraries to emit crumbs.\"), mdx(\"p\", null, \"You can however also manually emit events if you want to do so. There are a few ways this can be done.\"), mdx(\"p\", null, \"Breadcrumbs are enabled by default but starting with Raven 5.15 you can disable them on a per-client basis by passing \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"enable_breadcrumbs=False\"), \" to the client constructor.\"), mdx(\"h2\", {\n    \"id\": \"enabling-disabling-instrumentation\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#enabling-disabling-instrumentation\",\n    \"aria-label\": \"enabling disabling instrumentation permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"viewBox\": \"0 0 24 24\",\n    \"xmlns\": \"http://www.w3.org/2000/svg\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"d\": \"M10.879 6.05L15 1.93A5.001 5.001 0 0 1 22.071 9l-4.121 4.121a1 1 0 0 1-1.414-1.414l4.12-4.121a3 3 0 1 0-4.242-4.243l-4.121 4.121a1 1 0 1 1-1.414-1.414zm2.242 11.9L9 22.07A5 5 0 1 1 1.929 15l4.121-4.121a1 1 0 0 1 1.414 1.414l-4.12 4.121a3 3 0 1 0 4.242 4.243l4.121-4.121a1 1 0 1 1 1.414 1.414zm-8.364-.122l13.071-13.07a1 1 0 0 1 1.415 1.414L6.172 19.242a1 1 0 1 1-1.415-1.414z\",\n    \"fill\": \"currentColor\"\n  })))), \"Enabling / Disabling Instrumentation\"), mdx(\"p\", null, \"When a sentry client is constructed then the raven library will by default automatically instrument some popular libraries. There are a few ways this can be controlled by passing parameters to the client constructor:\"), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"dt\"\n  }, \"install_logging_hook\"), \":\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"If this keyword argument is set to \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"False\"), \" the Python logging system will not be instrumented. Note that this is a global instrumentation so that if you are using multiple sentry clients at once you need to disable this on all of them.\"))), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"dt\"\n  }, \"hook_libraries\"), \":\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"This is a list of libraries that you want to hook. The default is to hook all libraries that we have integrations for. If this is set to an empty list then no libraries are hooked.\"))), mdx(\"p\", null, \"The following libraries are supported currently:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"'requests'\"), \": hooks the Python requests library.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"'httplib'\"), \": hooks the stdlib http library (also hooks urllib in the process)\")), mdx(\"p\", null, \"Additionally framework integration will hook more things automatically. For instance when you use Django, database queries will be recorded.\"), mdx(\"p\", null, \"Another option to control what happens is to register special handlers for the logging system or to disable loggers entirely. For this you can use the \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"#raven.breadcrumbs.ignore_logger\",\n    \"title\": \"raven.breadcrumbs.ignore_logger\"\n  }), mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"ignore_logger()\")), \" and \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"#raven.breadcrumbs.register_special_log_handler\",\n    \"title\": \"raven.breadcrumbs.register_special_log_handler\"\n  }), mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"register_special_log_handler()\")), \" functions:\"), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, \"{: #raven.breadcrumbs.ignore\", mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"logger}\", mdx(\"inlineCode\", {\n    parentName: \"em\"\n  }, \"raven.breadcrumbs.``ignore_logger\"), \"(\", \"_\", \"name_or_logger\"), \", \", mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"allow_level=None\"), \")\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"If called with the name of a logger, this will ignore all messages that come from that logger. For instance if you have a very spammy logger you can disable it this way.\"))), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, \"{: #raven.breadcrumbs.register\", mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"special_log_handler}\", mdx(\"inlineCode\", {\n    parentName: \"em\"\n  }, \"raven.breadcrumbs.``register_special_log_handler\"), \"(\", \"_\", \"name_or_logger\"), \", \", mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"callback\"), \")\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"Registers a callback for log handling. The callback is invoked with given arguments: \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"logger\"), \", \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"level\"), \", \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"msg\"), \", \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"args\"), \" and \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"kwargs\"), \" which are the values passed to the logging system. If the callback returns true value the default handling is disabled. Only one callback can be registered per one logger name. Logger tree is not traversed so calling this method with \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"spammy_module\"), \" argument will not silence messages from \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"spammy_module.child\"), \".\"))), mdx(\"p\", null, \"Typically it makes sense to invoke \", mdx(\"a\", _extends({\n    parentName: \"p\"\n  }, {\n    \"href\": \"#raven.breadcrumbs.record\",\n    \"title\": \"raven.breadcrumbs.record\"\n  }), mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"record()\")), \" from it unless you want to silence a message based on its attributes other than \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"level\"), \".\"), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, \"{: #raven.breadcrumbs.register\", mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"logging_handler}\", mdx(\"inlineCode\", {\n    parentName: \"em\"\n  }, \"raven.breadcrumbs.``register_logging_handler\"), \"(\", \"_\", \"callback\"), \")\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"This is similar to \", mdx(\"a\", _extends({\n    parentName: \"dd\"\n  }, {\n    \"href\": \"#raven.breadcrumbs.register_special_log_handler\",\n    \"title\": \"raven.breadcrumbs.register_special_log_handler\"\n  }), mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"register_special_log_handler()\")), \" but it adds a global callback that is invoked for all log entries. Otherwise it works the same but multiple handlers can be registered.\"))), mdx(\"h2\", {\n    \"id\": \"manually-emitting-breadcrumbs\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", _extends({\n    parentName: \"h2\"\n  }, {\n    \"href\": \"#manually-emitting-breadcrumbs\",\n    \"aria-label\": \"manually emitting breadcrumbs permalink\",\n    \"className\": \"anchor before\"\n  }), mdx(\"svg\", _extends({\n    parentName: \"a\"\n  }, {\n    \"viewBox\": \"0 0 24 24\",\n    \"xmlns\": \"http://www.w3.org/2000/svg\"\n  }), mdx(\"path\", _extends({\n    parentName: \"svg\"\n  }, {\n    \"d\": \"M10.879 6.05L15 1.93A5.001 5.001 0 0 1 22.071 9l-4.121 4.121a1 1 0 0 1-1.414-1.414l4.12-4.121a3 3 0 1 0-4.242-4.243l-4.121 4.121a1 1 0 1 1-1.414-1.414zm2.242 11.9L9 22.07A5 5 0 1 1 1.929 15l4.121-4.121a1 1 0 0 1 1.414 1.414l-4.12 4.121a3 3 0 1 0 4.242 4.243l4.121-4.121a1 1 0 1 1 1.414 1.414zm-8.364-.122l13.071-13.07a1 1 0 0 1 1.415 1.414L6.172 19.242a1 1 0 1 1-1.415-1.414z\",\n    \"fill\": \"currentColor\"\n  })))), \"Manually Emitting Breadcrumbs\"), mdx(\"p\", null, \"If you want to manually record breadcrumbs the most convenient way to do that is to use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"record()\"), \" function which will automatically record the crumbs with the clients that are working with the current thread. This is more convenient than to call the \", mdx(\"em\", {\n    parentName: \"p\"\n  }, \"captureBreadcrumb\"), \" method on the client itself as you need to hold a reference to that.\"), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, \"{: #raven.breadcrumbs.record}\", mdx(\"inlineCode\", {\n    parentName: \"dt\"\n  }, \"raven.breadcrumbs.``record\"), \"(\", mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"*\", \"*\", \"options\"), \")\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"This function accepts keyword arguments matching the attributes of a breadcrumb. For more information see \", mdx(\"a\", _extends({\n    parentName: \"dd\"\n  }, {\n    \"href\": \"https://develop.sentry.dev/sdk/event-payloads/\"\n  }), mdx(\"em\", {\n    parentName: \"a\"\n  }, \"Event Payloads\")), \". Additionally, a \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"processor\"), \" callback can be passed which will be invoked to process the data if the crumb was not rejected.\"))), mdx(\"p\", null, \"The most important parameters:\"), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"message\"), \":\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"the message that should be recorded.\"))), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"data\"), \":\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"a data dictionary that should be recorded with the event.\"))), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"category\"), \":\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"The category for this error. This can be a module name, or just a string that clearly identifies the crumb (eg: \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"http\"), \", \", mdx(\"em\", {\n    parentName: \"dd\"\n  }, \"rpc\"), \", etc.)\"))), mdx(\"p\", null, mdx(\"dl\", {\n    parentName: \"p\"\n  }, mdx(\"dt\", {\n    parentName: \"dl\"\n  }, mdx(\"em\", {\n    parentName: \"dt\"\n  }, \"type\"), \":\"), mdx(\"dd\", {\n    parentName: \"dl\"\n  }, \"can override the type if a special type should be sent to Sentry.\"))), mdx(\"p\", null, \"Example:\"), mdx(\"div\", {\n    \"className\": \"code-tabs-wrapper\"\n  }, mdx(CodeTabs, {\n    mdxType: \"CodeTabs\"\n  }, mdx(CodeBlock, {\n    language: \"python\",\n    title: \"\",\n    filename: \"\",\n    mdxType: \"CodeBlock\"\n  }, mdx(\"div\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"python\"\n  }), mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-python\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-python\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), \"from\"), \" raven \", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), \"import\"), \" breadcrumbs\\n\\nbreadcrumbs\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \".\"), \"record\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \"(\"), \"message\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'This is an important message'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \",\"), \"\\n                   category\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'my_module'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \",\"), \" level\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'warning'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \")\"))))))), mdx(\"p\", null, \"Because crumbs go into a ring buffer, often it can be useful to defer processing of expensive operations until the crumb is actually needed. For this you can pass a processor which will be passed the data dict for modifications:\"), mdx(\"div\", {\n    \"className\": \"code-tabs-wrapper\"\n  }, mdx(CodeTabs, {\n    mdxType: \"CodeTabs\"\n  }, mdx(CodeBlock, {\n    language: \"python\",\n    title: \"\",\n    filename: \"\",\n    mdxType: \"CodeBlock\"\n  }, mdx(\"div\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"gatsby-highlight\",\n    \"data-language\": \"python\"\n  }), mdx(\"pre\", _extends({\n    parentName: \"div\"\n  }, {\n    \"className\": \"language-python\"\n  }), mdx(\"code\", _extends({\n    parentName: \"pre\"\n  }, {\n    \"className\": \"language-python\"\n  }), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), \"from\"), \" raven\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \".\"), \"breadcrumbs \", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), \"import\"), \" record\\n\\n\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token keyword\"\n  }), \"def\"), \" \", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token function\"\n  }), \"process_crumb\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \"(\"), \"data\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \")\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \":\"), \"\\n    data\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \"[\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'data'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \"]\"), \" \", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), \" compute_expensive_data\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \"(\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \")\"), \"\\n\\nrecord\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \"(\"), \"message\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'This is an important message'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \",\"), \"\\n       category\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'my_module'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \",\"), \" level\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token string\"\n  }), \"'warning'\"), mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \",\"), \"\\n       processor\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token operator\"\n  }), \"=\"), \"process_crumb\", mdx(\"span\", _extends({\n    parentName: \"code\"\n  }, {\n    \"className\": \"token punctuation\"\n  }), \")\"))))))));\n}\n;\nMDXContent.isMDXComponent = true;","tableOfContents":{"items":[{"url":"#enabling--disabling-instrumentation-enabling-disabling-instrumentation","title":"Enabling / Disabling Instrumentation {#enabling-disabling-instrumentation}"},{"url":"#manually-emitting-breadcrumbs","title":"Manually Emitting Breadcrumbs"}]},"internal":{"type":"Mdx"}}}},"pageContext":{"excerpt":"Newer Sentry versions support logging of breadcrumbs in addition of errors. This means that whenever an error or other Sentry event is submitted to the system, breadcrumbs that were logged before are sent along to make it easier to reproduce what lead up to an error. In the default configuration the Python client instruments the logging framework and a few popular libraries to emit crumbs. You can however also manually emit events if you want to do so. There are a few ways this can be done. Breadcrumbs are enabled by default but starting with Raven 5.15 you can disable them on a per-client basis by passing  enable_breadcrumbs=False  to the client constructor. Enabling / Disabling Instrumentation {#enabling-disabling-instrumentation} When a sentry client is constructed then the raven library will by default automatically instrument some popular libraries. There are a few ways this can be controlled by passing parameters to the client constructor: install_logging_hook : : If this keyword argument is set to  False  the Python logging system will not be instrumented. Note that this is a global instrumentation so that if you are using multiple sentry clients at once you need to disable this on all of them. hook_libraries : : This is a list of libraries that you want to hook. The default is to hook all libraries that we have integrations for. If this is set to an empty list then no libraries are hooked. The following libraries are supported currently: 'requests' : hooks the Python requests library. 'httplib' : hooks the stdlib http library (also hooks urllib in the process) Additionally framework integration will hook more things automatically. For instance when you use Django, database queries will be recorded. Another option to control what happens is to register special handlers for the logging system or to disable loggers entirely. For this you can use the  ignore_logger()  and  register_special_log_handler()  functions: {: #raven.breadcrumbs.ignore logger} raven.breadcrumbs.``ignore_logger ( _ name_or_logger ,  allow_level=None ) : If called with the name of a logger, this will ignore all messages that come from that logger. For instance if you have a very spammy logger you can disable it this way. {: #raven.breadcrumbs.register special_log_handler} raven.breadcrumbs.``register_special_log_handler ( _ name_or_logger ,  callback ) : Registers a callback for log handling. The callback is invoked with given arguments:  logger ,  level ,  msg ,  args  and  kwargs  which are the values passed to the logging system. If the callback returns true value the default handling is disabled. Only one callback can be registered per one logger name. Logger tree is not traversed so calling this method with  spammy_module  argument will not silence messages from  spammy_module.child . Typically it makes sense to invoke  record()  from it unless you want to silence a message based on its attributes other than  level . {: #raven.breadcrumbs.register logging_handler} raven.breadcrumbs.``register_logging_handler ( _ callback ) : This is similar to  register_special_log_handler()  but it adds a global callback that is invoked for all log entries. Otherwise it works the same but multiple handlers can be registered. Manually Emitting Breadcrumbs If you want to manually record breadcrumbs the most convenient way to do that is to use the  record()  function which will automatically record the crumbs with the clients that are working with the current thread. This is more convenient than to call the  captureBreadcrumb  method on the client itself as you need to hold a reference to that. {: #raven.breadcrumbs.record} raven.breadcrumbs.``record ( * * options ) : This function accepts keyword arguments matching the attributes of a breadcrumb. For more information see  Event Payloads . Additionally, a  processor  callback can be passed which will be invoked to process the data if the crumb was not rejected. The most important parameters: message : : the message that should be recorded. data : : a data dictionary that should be recorded with the event. category : : The category for this error. This can be a module name, or just a string that clearly identifies the crumb (eg:  http ,  rpc , etc.) type : : can override the type if a special type should be sent to Sentry. Example: Because crumbs go into a ring buffer, often it can be useful to defer processing of expensive operations until the crumb is actually needed. For this you can pass a processor which will be passed the data dict for modifications:","title":"Logging Breadcrumbs","description":null,"draft":false,"noindex":true,"notoc":null,"sidebar_order":2,"redirect_from":null,"keywords":null,"id":"ea9b1172-6ef9-5509-9b09-2af722f57b2f","legacy":true}},"staticQueryHashes":["1218203755","1222113826","1222113826","1766336459","2158593473","2764967025","3345802723","3818502851","3990806462","4015007367","4192517163","4264099332","518019976"]}