Imported new docs
This commit is contained in:
parent
d13b3cf78c
commit
9e385c43b9
|
@ -13,8 +13,7 @@ pip-log.txt
|
|||
/cover
|
||||
/dist
|
||||
/example_project/local_settings.py
|
||||
/docs/html
|
||||
/docs/doctrees
|
||||
/docs/_build
|
||||
/sentry_index/
|
||||
/sentry_test_index
|
||||
/example_project/*.db
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = ./
|
||||
BUILDDIR = ./_build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
API Reference
|
||||
=============
|
||||
|
||||
.. default-domain:: py
|
||||
|
||||
This gives you an overview of the public API that raven-python exposes.
|
||||
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
.. py:class:: raven.Client(dsn=None, **kwargs)
|
||||
|
||||
The client needs to be instanciated once and can then be used for
|
||||
submitting events to the Sentry server. For information about the
|
||||
configuration of that client and which parameters are accepted see
|
||||
:ref:`python-client-config`.
|
||||
|
||||
.. py:method:: capture(event_type, data=None, date=None, \
|
||||
time_spent=None, extra=None, stack=False, tags=None, **kwargs)
|
||||
|
||||
This method is the low-level method for reporting events to
|
||||
Sentry. It captures and processes an event and pipes it via the
|
||||
configured transport to Sentry.
|
||||
|
||||
Example::
|
||||
|
||||
capture('raven.events.Message', message='foo', data={
|
||||
'request': {
|
||||
'url': '...',
|
||||
'data': {},
|
||||
'query_string': '...',
|
||||
'method': 'POST',
|
||||
},
|
||||
'logger': 'logger.name',
|
||||
}, extra={
|
||||
'key': 'value',
|
||||
})
|
||||
|
||||
:param event_type: the module path to the Event class. Builtins can
|
||||
use shorthand class notation and exclude the
|
||||
full module path.
|
||||
:param data: the data base, useful for specifying structured data
|
||||
interfaces. Any key which contains a '.' will be
|
||||
assumed to be a data interface.
|
||||
:param date: the datetime of this event. If not supplied the
|
||||
current timestamp is used.
|
||||
:param time_spent: a integer value representing the duration of the
|
||||
event (in milliseconds)
|
||||
:param extra: a dictionary of additional standard metadata.
|
||||
:param stack: If set to `True` a stack frame is recorded together
|
||||
with the event.
|
||||
:param tags: list of extra tags
|
||||
:param kwargs: extra keyword arguments are handled specific to the
|
||||
reported event type.
|
||||
:return: a tuple with a 32-length string identifying this event
|
||||
|
||||
.. py:method:: captureMessage(message, **kwargs)
|
||||
|
||||
This is a shorthand to reporting a message via :meth:`capture`.
|
||||
It passes ``'raven.events.Message'`` as `event_type` and the
|
||||
message along. All other keyword arguments are regularly
|
||||
forwarded.
|
||||
|
||||
Example::
|
||||
|
||||
client.captureMessage('This just happened!')
|
||||
|
||||
.. py:method:: captureException(message, exc_info=None, **kwargs)
|
||||
|
||||
This is a shorthand to reporting an exception via :meth:`capture`.
|
||||
It passes ``'raven.events.Exception'`` as `event_type` and the
|
||||
traceback along. All other keyword arguments are regularly
|
||||
forwarded.
|
||||
|
||||
If exc_info is not provided, or is set to True, then this method
|
||||
will perform the ``exc_info = sys.exc_info()`` and the requisite
|
||||
clean-up for you.
|
||||
|
||||
Example::
|
||||
|
||||
try:
|
||||
1 / 0
|
||||
except Exception:
|
||||
client.captureException()
|
||||
|
||||
.. py:method:: send(**data)
|
||||
|
||||
Accepts all data parameters and serializes them, then sends then
|
||||
onwards via the transport to Sentry. This can be used as to send
|
||||
low-level protocol data to the server.
|
||||
|
||||
.. py:attribute:: context
|
||||
|
||||
Returns a reference to the thread local context object. See
|
||||
:py:class:`raven.context.Context` for more information.
|
||||
|
||||
Context
|
||||
-------
|
||||
|
||||
.. py:class:: raven.context.Context()
|
||||
|
||||
The context object works similar to a dictionary and is used to record
|
||||
information that should be submitted with events automatically. It is
|
||||
available through :py:attr:`raven.Client.context` and is thread local.
|
||||
This means that you can modify this object over time to feed it with
|
||||
more appropriate information.
|
||||
|
||||
.. py:method:: merge(data)
|
||||
|
||||
Performs a merge of the current data in the context and the new
|
||||
data provided.
|
||||
|
||||
.. py:method:: clear()
|
||||
|
||||
Clears the context. It's important that you make sure to call
|
||||
this when you reuse the thread for something else. For instance
|
||||
for web frameworks it's generally a good idea to call this at the
|
||||
end of the HTTP request.
|
||||
|
||||
Otherwise you run at risk of seeing incorrect information after
|
||||
the first use of the thread.
|
|
@ -1,4 +0,0 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
.. include:: ../../CHANGES
|
|
@ -0,0 +1,204 @@
|
|||
Configuration
|
||||
=============
|
||||
|
||||
.. default-domain:: py
|
||||
|
||||
This document describes configuration options available to the Raven
|
||||
client for the use with Sentry. It also covers some other important parts
|
||||
about configuring the environment.
|
||||
|
||||
|
||||
.. _python-client-config:
|
||||
|
||||
Configuring the Client
|
||||
----------------------
|
||||
|
||||
Settings are specified as part of the initialization of the client. The
|
||||
client is a class that can be instanciated with a specific configuration
|
||||
and all reporting can then happen from the instance of that object.
|
||||
Typically an instance is created somewhere globally and then imported as
|
||||
necessary.
|
||||
|
||||
As of Raven 1.2.0, you can now configure all clients through a standard DSN
|
||||
string. This can be specified as a default using the ``SENTRY_DSN`` environment
|
||||
variable, as well as passed to all clients by using the ``dsn`` argument.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from raven import Client
|
||||
|
||||
# Read configuration from the environment
|
||||
client = Client()
|
||||
|
||||
# Manually specify a DSN
|
||||
client = Client('___DSN___')
|
||||
|
||||
|
||||
A reasonably configured client should generally include a few additional
|
||||
settings:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import raven
|
||||
|
||||
client = raven.Client(
|
||||
dsn='___DSN___'
|
||||
|
||||
# inform the client which parts of code are yours
|
||||
# include_paths=['my.app']
|
||||
include_paths=[__name__.split('.', 1)[0]],
|
||||
|
||||
# pass along the version of your application
|
||||
# release='1.0.0'
|
||||
# release=raven.fetch_package_version('my-app')
|
||||
release=raven.fetch_git_sha(os.path.dirname(__file__)),
|
||||
)
|
||||
|
||||
.. versionadded:: 5.2.0
|
||||
The *fetch_package_version* and *fetch_git_sha* helpers.
|
||||
|
||||
|
||||
The Sentry DSN
|
||||
--------------
|
||||
|
||||
.. sentry:edition:: hosted, on-premise
|
||||
|
||||
The most important information is the Sentry DSN. For information
|
||||
about it see :ref:`configure-the-dsn` in the general Sentry docs.
|
||||
|
||||
The Python client supports one additional modification to the regular DSN
|
||||
values which is the choice of the transport. To select a specific
|
||||
transport, the DSN needs to be prepended with the name of the transport.
|
||||
For instance to select the ``gevent`` transport, the following DSN would
|
||||
be used::
|
||||
|
||||
'gevent+___DSN___'
|
||||
|
||||
For more information see :doc:`transports`.
|
||||
|
||||
Client Arguments
|
||||
----------------
|
||||
|
||||
The following are valid arguments which may be passed to the Raven client:
|
||||
|
||||
.. describe:: dsn
|
||||
|
||||
A Sentry compatible DSN as mentioned before::
|
||||
|
||||
dsn = '___DSN___'
|
||||
|
||||
.. describe:: site
|
||||
|
||||
An optional, arbitrary string to identify this client installation::
|
||||
|
||||
site = 'my site name'
|
||||
|
||||
.. describe:: name
|
||||
|
||||
This will override the ``server_name`` value for this installation.
|
||||
Defaults to ``socket.gethostname()``::
|
||||
|
||||
name = 'sentry_rocks_' + socket.gethostname()
|
||||
|
||||
.. describe:: release
|
||||
|
||||
The version of your application. This will map up into a Release in
|
||||
Sentry::
|
||||
|
||||
release = '1.0.3'
|
||||
|
||||
.. describe:: exclude_paths
|
||||
|
||||
Extending this allow you to ignore module prefixes when we attempt to
|
||||
discover which function an error comes from (typically a view)::
|
||||
|
||||
exclude_paths = [
|
||||
'django',
|
||||
'sentry',
|
||||
'raven',
|
||||
'lxml.objectify',
|
||||
]
|
||||
|
||||
.. describe:: include_paths
|
||||
|
||||
For example, in Django this defaults to your list of ``INSTALLED_APPS``,
|
||||
and is used for drilling down where an exception is located::
|
||||
|
||||
include_paths = [
|
||||
'django',
|
||||
'sentry',
|
||||
'raven',
|
||||
'lxml.objectify',
|
||||
]
|
||||
|
||||
.. describe:: max_list_length
|
||||
|
||||
The maximum number of items a list-like container should store.
|
||||
|
||||
If an iterable is longer than the specified length, the left-most
|
||||
elements up to length will be kept.
|
||||
|
||||
.. note:: This affects sets as well, which are unordered.
|
||||
|
||||
::
|
||||
|
||||
list_max_length = 50
|
||||
|
||||
.. describe:: string_max_length
|
||||
|
||||
The maximum characters of a string that should be stored.
|
||||
|
||||
If a string is longer than the given length, it will be truncated down
|
||||
to the specified size::
|
||||
|
||||
string_max_length = 200
|
||||
|
||||
.. describe:: auto_log_stacks
|
||||
|
||||
Should Raven automatically log frame stacks (including locals) for all
|
||||
calls as it would for exceptions::
|
||||
|
||||
auto_log_stacks = True
|
||||
|
||||
.. describe:: processors
|
||||
|
||||
A list of processors to apply to events before sending them to the
|
||||
Sentry server. Useful for sending additional global state data or
|
||||
sanitizing data that you want to keep off of the server::
|
||||
|
||||
processors = (
|
||||
'raven.processors.SanitizePasswordsProcessor',
|
||||
)
|
||||
|
||||
Sanitizing Data
|
||||
---------------
|
||||
|
||||
Several processors are included with Raven to assist in data
|
||||
sanitiziation. These are configured with the ``processors`` value.
|
||||
|
||||
.. data:: raven.processors.SanitizePasswordsProcessor
|
||||
:noindex:
|
||||
|
||||
Removes all keys which resemble ``password``, ``secret``, or
|
||||
``api_key`` within stacktrace contexts, HTTP bits (such as cookies,
|
||||
POST data, the querystring, and environment), and extra data.
|
||||
|
||||
.. data:: raven.processors.RemoveStackLocalsProcessor
|
||||
:noindex:
|
||||
|
||||
Removes all stacktrace context variables. This will cripple the
|
||||
functionality of Sentry, as you'll only get raw tracebacks, but it will
|
||||
ensure no local scoped information is available to the server.
|
||||
|
||||
.. data:: raven.processors.RemovePostDataProcessor
|
||||
:noindex:
|
||||
|
||||
Removes the ``body`` of all HTTP data.
|
||||
|
||||
|
||||
A Note on uWSGI
|
||||
---------------
|
||||
|
||||
If you're using uWSGI you will need to add ``enable-threads`` to the
|
||||
default invocation, or you will need to switch off of the threaded default
|
||||
transport.
|
|
@ -1,247 +0,0 @@
|
|||
Configuration
|
||||
=============
|
||||
|
||||
This document describes configuration options available to Sentry.
|
||||
|
||||
|
||||
Configuring the Client
|
||||
----------------------
|
||||
|
||||
Settings are specified as part of the initialization of the client.
|
||||
|
||||
As of Raven 1.2.0, you can now configure all clients through a standard DSN
|
||||
string. This can be specified as a default using the ``SENTRY_DSN`` environment
|
||||
variable, as well as passed to all clients by using the ``dsn`` argument.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from raven import Client
|
||||
|
||||
# Read configuration from the environment
|
||||
client = Client()
|
||||
|
||||
# Manually specify a DSN
|
||||
client = Client('http://public:secret@example.com/1')
|
||||
|
||||
|
||||
A reasonably configured client should generally include a few additional settings:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import raven
|
||||
|
||||
client = raven.Client(
|
||||
dsn='http://public:secret@example.com/1'
|
||||
|
||||
# inform the client which parts of code are yours
|
||||
# include_paths=['my.app']
|
||||
include_paths=[__name__.split('.', 1)[0]],
|
||||
|
||||
# pass along the version of your application
|
||||
# release='1.0.0'
|
||||
# release=raven.fetch_package_version('my-app')
|
||||
release=raven.fetch_git_sha(os.path.dirname(__file__)),
|
||||
)
|
||||
|
||||
.. versionadded:: 5.2.0
|
||||
The *fetch_package_version* and *fetch_git_sha* helpers.
|
||||
|
||||
|
||||
The Sentry DSN
|
||||
--------------
|
||||
|
||||
The DSN can be found in Sentry by navigation to Account -> Projects -> [Project Name] -> [Member Name]. Its template resembles the following::
|
||||
|
||||
'{PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}/{PATH}{PROJECT_ID}'
|
||||
|
||||
It is composed of six important pieces:
|
||||
|
||||
* The Protocol used. This can be one of the following: http or https.
|
||||
|
||||
* The public and secret keys to authenticate the client.
|
||||
|
||||
* The hostname of the Sentry server.
|
||||
|
||||
* An optional path if Sentry is not located at the webserver root. This is specific to HTTP requests.
|
||||
|
||||
* The project ID which the authenticated user is bound to.
|
||||
|
||||
|
||||
Client Arguments
|
||||
----------------
|
||||
|
||||
The following are valid arguments which may be passed to the Raven client:
|
||||
|
||||
dsn
|
||||
~~~
|
||||
|
||||
A sentry compatible DSN.
|
||||
|
||||
::
|
||||
|
||||
dsn = 'http://public:secret@example.com/1'
|
||||
|
||||
project
|
||||
~~~~~~~
|
||||
|
||||
Set this to your Sentry project ID. The default value for installations is ``1``.
|
||||
|
||||
::
|
||||
|
||||
project = 1
|
||||
|
||||
|
||||
public_key
|
||||
~~~~~~~~~~
|
||||
|
||||
Set this to the public key of the project member which will authenticate as the
|
||||
client. You can find this information on the member details page of your project
|
||||
within Sentry.
|
||||
|
||||
::
|
||||
|
||||
public_key = 'fb9f9e31ea4f40d48855c603f15a2aa4'
|
||||
|
||||
|
||||
secret_key
|
||||
~~~~~~~~~~
|
||||
|
||||
Set this to the secret key of the project member which will authenticate as the
|
||||
client. You can find this information on the member details page of your project
|
||||
within Sentry.
|
||||
|
||||
::
|
||||
|
||||
secret_key = '6e968b3d8ba240fcb50072ad9cba0810'
|
||||
|
||||
site
|
||||
~~~~
|
||||
|
||||
An optional, arbitrary string to identify this client installation.
|
||||
|
||||
::
|
||||
|
||||
site = 'my site name'
|
||||
|
||||
|
||||
name
|
||||
~~~~
|
||||
|
||||
This will override the ``server_name`` value for this installation. Defaults to ``socket.gethostname()``.
|
||||
|
||||
::
|
||||
|
||||
name = 'sentry_rocks_' + socket.gethostname()
|
||||
|
||||
|
||||
release
|
||||
~~~~~~~~
|
||||
|
||||
The version of your application. This will map up into a Release in Sentry.
|
||||
|
||||
::
|
||||
|
||||
release = '1.0.3'
|
||||
|
||||
|
||||
exclude_paths
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Extending this allow you to ignore module prefixes when we attempt to discover which function an error comes from (typically a view)
|
||||
|
||||
::
|
||||
|
||||
exclude_paths = [
|
||||
'django',
|
||||
'sentry',
|
||||
'raven',
|
||||
'lxml.objectify',
|
||||
]
|
||||
|
||||
include_paths
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
For example, in Django this defaults to your list of ``INSTALLED_APPS``, and is used for drilling down where an exception is located
|
||||
|
||||
::
|
||||
|
||||
include_paths = [
|
||||
'django',
|
||||
'sentry',
|
||||
'raven',
|
||||
'lxml.objectify',
|
||||
]
|
||||
|
||||
list_max_length
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The maximum number of items a list-like container should store.
|
||||
|
||||
If an iterable is longer than the specified length, the left-most elements up to length will be kept.
|
||||
|
||||
.. note:: This affects sets as well, which are unordered.
|
||||
|
||||
::
|
||||
|
||||
list_max_length = 50
|
||||
|
||||
string_max_length
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The maximum characters of a string that should be stored.
|
||||
|
||||
If a string is longer than the given length, it will be truncated down to the specified size.
|
||||
|
||||
::
|
||||
|
||||
string_max_length = 200
|
||||
|
||||
auto_log_stacks
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Should Raven automatically log frame stacks (including locals) for all calls as
|
||||
it would for exceptions.
|
||||
|
||||
::
|
||||
|
||||
auto_log_stacks = True
|
||||
|
||||
|
||||
processors
|
||||
~~~~~~~~~~
|
||||
|
||||
A list of processors to apply to events before sending them to the Sentry server. Useful for sending
|
||||
additional global state data or sanitizing data that you want to keep off of the server.
|
||||
|
||||
::
|
||||
|
||||
processors = (
|
||||
'raven.processors.SanitizePasswordsProcessor',
|
||||
)
|
||||
|
||||
Sanitizing Data
|
||||
---------------
|
||||
|
||||
Several processors are included with Raven to assist in data sanitiziation. These are configured with the
|
||||
``processors`` value.
|
||||
|
||||
.. data:: raven.processors.SanitizePasswordsProcessor
|
||||
|
||||
Removes all keys which resemble ``password``, ``secret``, or ``api_key``
|
||||
within stacktrace contexts, HTTP bits (such as cookies, POST data,
|
||||
the querystring, and environment), and extra data.
|
||||
|
||||
.. data:: raven.processors.RemoveStackLocalsProcessor
|
||||
|
||||
Removes all stacktrace context variables. This will cripple the functionality of Sentry, as you'll only
|
||||
get raw tracebacks, but it will ensure no local scoped information is available to the server.
|
||||
|
||||
.. data:: raven.processors.RemovePostDataProcessor
|
||||
|
||||
Removes the ``body`` of all HTTP data.
|
||||
|
||||
|
||||
A Note on uWSGI
|
||||
---------------
|
||||
|
||||
If you're using uWSGI you will need to add ``enable-threads`` to the default invocation, or you will need to switch off of the threaded transport.
|
|
@ -1,68 +1,74 @@
|
|||
raven-python
|
||||
============
|
||||
.. sentry:edition:: self
|
||||
|
||||
Raven is a standalone (and the official) Python client for `Sentry <http://www.getsentry.com/>`_.
|
||||
Raven Python
|
||||
============
|
||||
|
||||
This version of Raven requires Sentry 7.0 or newer.
|
||||
.. sentry:edition:: hosted, on-premise
|
||||
|
||||
Users Guide
|
||||
-----------
|
||||
.. class:: platform-python
|
||||
|
||||
Python
|
||||
======
|
||||
|
||||
Raven for Python (raven-python) is the official standalone Python client
|
||||
for Sentry. It can be used with any modern Python interpreter be it
|
||||
CPython 2.x or 3.x, PyPy or Jython. It's an Open Source project and
|
||||
available under a very liberal BSD license.
|
||||
|
||||
.. sentry:edition:: self
|
||||
|
||||
Users Guide
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
install/index
|
||||
config/index
|
||||
installation
|
||||
config
|
||||
usage
|
||||
integrations/index
|
||||
transports/index
|
||||
transports
|
||||
platform-support
|
||||
api
|
||||
|
||||
Developers
|
||||
----------
|
||||
.. sentry:edition:: self
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
For Developers
|
||||
--------------
|
||||
|
||||
contributing/index
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:titlesonly:
|
||||
|
||||
Reference
|
||||
---------
|
||||
contributing
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
Supported Platforms
|
||||
-------------------
|
||||
|
||||
changelog/index
|
||||
- Python 2.6
|
||||
- Python 2.7
|
||||
- Python 3.2
|
||||
- Python 3.3
|
||||
- PyPy
|
||||
- Google App Engine
|
||||
|
||||
Supported Platforms
|
||||
-------------------
|
||||
Deprecation Notes
|
||||
-----------------
|
||||
|
||||
Milestones releases are 1.3 or 1.4, and our deprecation policy is to a two
|
||||
version step. For example, a feature will be deprecated in 1.3, and
|
||||
completely removed in 1.4.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
- Python 2.6
|
||||
- Python 2.7
|
||||
- Python 3.2
|
||||
- Python 3.3
|
||||
- PyPy
|
||||
- Google App Engine
|
||||
.. sentry:edition:: hosted, on-premise
|
||||
|
||||
About Sentry
|
||||
------------
|
||||
|
||||
Sentry provides you with a generic interface to view and interact with your error logs. With this
|
||||
it allows you to interact and view near real-time information to discover issues and more
|
||||
easily trace them in your application.
|
||||
|
||||
More information about Sentry can be found at http://www.getsentry.com/
|
||||
|
||||
Resources
|
||||
---------
|
||||
Resources:
|
||||
|
||||
* `Documentation <http://raven.readthedocs.org/>`_
|
||||
* `Bug Tracker <http://github.com/getsentry/raven-python/issues>`_
|
||||
* `Code <http://github.com/getsentry/raven-python>`_
|
||||
* `Mailing List <https://groups.google.com/group/getsentry>`_
|
||||
* `IRC <irc://irc.freenode.net/sentry>`_ (irc.freenode.net, #sentry)
|
||||
|
||||
Deprecation Notes
|
||||
-----------------
|
||||
|
||||
Milestones releases are 1.3 or 1.4, and our deprecation policy is to a two version step. For example,
|
||||
a feature will be deprecated in 1.3, and completely removed in 1.4.
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
Install
|
||||
=======
|
||||
|
||||
If you haven't already, start by downloading Raven. The easiest way is with **pip**::
|
||||
|
||||
pip install raven --upgrade
|
||||
|
||||
Or with *setuptools*::
|
||||
|
||||
easy_install -U raven
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
If you installed using pip or setuptools you shouldn't need to worry about requirements. Otherwise
|
||||
you will need to install the following packages in your environment:
|
||||
|
||||
- ``simplejson``
|
|
@ -0,0 +1,25 @@
|
|||
Installation
|
||||
============
|
||||
|
||||
If you haven't already, start by downloading Raven. The easiest way is
|
||||
with *pip*::
|
||||
|
||||
pip install raven --upgrade
|
||||
|
||||
Or alternatively with *setuptools*::
|
||||
|
||||
easy_install -U raven
|
||||
|
||||
If you want to use the latest git version you can get it from `the github
|
||||
repository <https://github.com/getsentry/raven-python>`_::
|
||||
|
||||
git clone https://github.com/getsentry/raven-python
|
||||
pip install raven-python
|
||||
|
||||
Certain additional features can be installed by defining the feature when
|
||||
``pip`` installing it. For instance to install all dependencies needed to
|
||||
use the Flask integration, you can depend on ``raven[flask]``::
|
||||
|
||||
pip install raven[flask]
|
||||
|
||||
For more information refer to the individual integration documentation.
|
|
@ -1,6 +1,9 @@
|
|||
Bottle
|
||||
======
|
||||
|
||||
`Bottle <http://bottlepy.org/>`_ is a microframework for Python. Raven
|
||||
supports this framework through the WSGI integration.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
|
@ -11,11 +14,14 @@ The first thing you'll need to do is to disable catchall in your Bottle app::
|
|||
app = bottle.app()
|
||||
app.catchall = False
|
||||
|
||||
.. note:: Bottle will not propagate exceptions to the underlying WSGI middleware by default. Setting catchall to False disables that.
|
||||
.. note:: Bottle will not propagate exceptions to the underlying WSGI
|
||||
middleware by default. Setting catchall to False disables that.
|
||||
|
||||
Sentry will act as Middleware::
|
||||
Sentry will then act as Middleware::
|
||||
|
||||
from raven import Client
|
||||
from raven.contrib.bottle import Sentry
|
||||
client = Client('___DSN___')
|
||||
app = Sentry(app, client)
|
||||
|
||||
Usage
|
||||
|
@ -25,15 +31,16 @@ Once you've configured the Sentry application you need only call run with it::
|
|||
|
||||
run(app=app)
|
||||
|
||||
If you want to send additional events, a couple of shortcuts are provided on the Bottle request app object.
|
||||
If you want to send additional events, a couple of shortcuts are provided
|
||||
on the Bottle request app object.
|
||||
|
||||
Capture an arbitrary exception by calling ``captureException``::
|
||||
|
||||
>>> try:
|
||||
>>> 1 / 0
|
||||
>>> except ZeroDivisionError:
|
||||
>>> request.app.sentry.captureException()
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError:
|
||||
request.app.sentry.captureException()
|
||||
|
||||
Log a generic message with ``captureMessage``::
|
||||
|
||||
>>> request.app.sentry.captureMessage('hello, world!')
|
||||
request.app.sentry.captureMessage('Hello, world!')
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
Celery
|
||||
======
|
||||
|
||||
tl;dr register a couple of signals to hijack Celery error handling
|
||||
`Celery <http://www.celeryproject.org/>`_ is a distributed task queue
|
||||
system for Python built on AMQP principles. For Celery built-in support
|
||||
by Raven is provided but it requires some manual configuraiton.
|
||||
|
||||
.. code-block:: python
|
||||
To capture errors, you need to register a couple of signals to hijack
|
||||
Celery error handling::
|
||||
|
||||
from raven import Client
|
||||
from raven.contrib.celery import register_signal, register_logger_signal
|
||||
|
||||
client = Client()
|
||||
client = Client('___DSN___')
|
||||
|
||||
# register a custom filter to filter out duplicate logs
|
||||
register_logger_signal(client)
|
||||
|
@ -26,13 +29,13 @@ A more complex version to encapsulate behavior:
|
|||
.. code-block:: python
|
||||
|
||||
import celery
|
||||
import raven
|
||||
from raven.contrib.celery import register_signal, register_logger_signal
|
||||
|
||||
class Celery(celery.Celery):
|
||||
def on_configure(self):
|
||||
import raven
|
||||
from raven.contrib.celery import register_signal, register_logger_signal
|
||||
|
||||
client = raven.Client()
|
||||
def on_configure(self):
|
||||
client = raven.Client('___DSN___')
|
||||
|
||||
# register a custom filter to filter out duplicate logs
|
||||
register_logger_signal(client)
|
||||
|
|
|
@ -1,27 +1,35 @@
|
|||
Django
|
||||
======
|
||||
|
||||
Support
|
||||
-------
|
||||
.. default-domain:: py
|
||||
|
||||
While older versions of Django will likely work, officially only version 1.4 and newer are supported.
|
||||
`Django <http://djangoproject.com/>`_ is one of (if not the) Python's most
|
||||
popular web frameworks. Support is built into Raven but needs some
|
||||
configuration. While older versions of Django will likely work,
|
||||
officially only version 1.4 and newer are supported.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
Using the Django integration is as simple as adding :mod:`raven.contrib.django.raven_compat` to your installed apps::
|
||||
Using the Django integration is as simple as adding
|
||||
:mod:`raven.contrib.django.raven_compat` to your installed apps::
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'raven.contrib.django.raven_compat',
|
||||
)
|
||||
|
||||
.. note:: This causes Raven to install a hook in Django that will automatically report uncaught exceptions.
|
||||
.. note:: This causes Raven to install a hook in Django that will
|
||||
automatically report uncaught exceptions.
|
||||
|
||||
Additional settings for the client are configured using the ``RAVEN_CONFIG`` dictionary::
|
||||
Additional settings for the client are configured using the
|
||||
``RAVEN_CONFIG`` dictionary::
|
||||
|
||||
import raven
|
||||
|
||||
RAVEN_CONFIG = {
|
||||
'dsn': 'http://public:secret@example.com/1',
|
||||
'dsn': '___DSN___',
|
||||
# If you are using git, you can also automatically configure the
|
||||
# release based on the git info.
|
||||
'release': raven.fetch_git_sha(os.path.dirname(__file__)),
|
||||
}
|
||||
|
||||
|
@ -40,27 +48,38 @@ You'll be referencing the client slightly differently in Django as well::
|
|||
Using with Raven.js
|
||||
-------------------
|
||||
|
||||
A Django template tag is provided to render a proper public DSN inside your templates, you must first load ``raven``::
|
||||
A Django template tag is provided to render a proper public DSN inside
|
||||
your templates, you must first load ``raven``:
|
||||
|
||||
.. sourcecode:: django
|
||||
|
||||
{% load raven %}
|
||||
|
||||
Inside your template, you can now use::
|
||||
Inside your template, you can now use:
|
||||
|
||||
.. sourcecode:: html+django
|
||||
|
||||
<script>Raven.config('{% sentry_public_dsn %}').install()</script>
|
||||
|
||||
By default, the DSN is generated in a protocol relative fashion, e.g. ``//public@example.com/1``. If you need a specific protocol, you can override::
|
||||
By default, the DSN is generated in a protocol relative fashion, e.g.
|
||||
``//public@example.com/1``. If you need a specific protocol, you can
|
||||
override:
|
||||
|
||||
.. sourcecode:: html+django
|
||||
|
||||
{% sentry_public_dsn 'https' %}
|
||||
|
||||
See `Raven.js documentation <http://raven-js.readthedocs.org/>`_ for more information.
|
||||
.. sentry:edition:: hosted, on-premise
|
||||
|
||||
See the :doc:`Raven.js documentation <../../../clients/javascript/index>`
|
||||
for more information.
|
||||
|
||||
|
||||
Integration with :mod:`logging`
|
||||
-------------------------------
|
||||
|
||||
To integrate with the standard library's :mod:`logging` module:
|
||||
|
||||
::
|
||||
To integrate with the standard library's :mod:`logging` module the
|
||||
following config can be used::
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
|
@ -71,7 +90,8 @@ To integrate with the standard library's :mod:`logging` module:
|
|||
},
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
|
||||
'format': '%(levelname)s %(asctime)s %(module)s '
|
||||
'%(process)d %(thread)d %(message)s'
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
|
@ -136,8 +156,8 @@ Message References
|
|||
|
||||
Sentry supports sending a message ID to your clients so that they can be
|
||||
tracked easily by your development team. There are two ways to access this
|
||||
information, the first is via the ``X-Sentry-ID`` HTTP response header. Adding
|
||||
this is as simple as appending a middleware to your stack::
|
||||
information, the first is via the ``X-Sentry-ID`` HTTP response header.
|
||||
Adding this is as simple as appending a middleware to your stack::
|
||||
|
||||
MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + (
|
||||
# We recommend putting this as high in the chain as possible
|
||||
|
@ -146,25 +166,24 @@ this is as simple as appending a middleware to your stack::
|
|||
)
|
||||
|
||||
Another alternative method is rendering it within a template. By default,
|
||||
Sentry will attach :attr:`request.sentry` when it catches a Django exception.
|
||||
In our example, we will use this information to modify the default
|
||||
:file:`500.html` which is rendered, and show the user a case reference ID. The
|
||||
first step in doing this is creating a custom :func:`handler500` in your
|
||||
:file:`urls.py` file::
|
||||
Sentry will attach :attr:`request.sentry` when it catches a Django
|
||||
exception. In our example, we will use this information to modify the
|
||||
default :file:`500.html` which is rendered, and show the user a case
|
||||
reference ID. The first step in doing this is creating a custom
|
||||
:func:`handler500` in your :file:`urls.py` file::
|
||||
|
||||
from django.conf.urls.defaults import *
|
||||
|
||||
from django.views.defaults import page_not_found, server_error
|
||||
from django.template import Context, loader
|
||||
from django.http import HttpResponseServerError
|
||||
|
||||
def handler500(request):
|
||||
"""
|
||||
500 error handler which includes ``request`` in the context.
|
||||
"""500 error handler which includes ``request`` in the context.
|
||||
|
||||
Templates: `500.html`
|
||||
Context: None
|
||||
"""
|
||||
from django.template import Context, loader
|
||||
from django.http import HttpResponseServerError
|
||||
|
||||
t = loader.get_template('500.html') # You need to create a 500.html template.
|
||||
return HttpResponseServerError(t.render(Context({
|
||||
|
@ -174,11 +193,12 @@ first step in doing this is creating a custom :func:`handler500` in your
|
|||
Once we've successfully added the :data:`request` context variable, adding the
|
||||
Sentry reference ID to our :file:`500.html` is simple:
|
||||
|
||||
.. code-block:: django
|
||||
.. sourcecode:: html+django
|
||||
|
||||
<p>You've encountered an error, oh noes!</p>
|
||||
{% if request.sentry.id %}
|
||||
<p>If you need assistance, you may reference this error as <strong>{{ request.sentry.id }}</strong>.</p>
|
||||
<p>If you need assistance, you may reference this error as
|
||||
<strong>{{ request.sentry.id }}</strong>.</p>
|
||||
{% endif %}
|
||||
|
||||
WSGI Middleware
|
||||
|
@ -197,30 +217,31 @@ level of your Django application::
|
|||
Additional Settings
|
||||
-------------------
|
||||
|
||||
SENTRY_CLIENT
|
||||
~~~~~~~~~~~~~~
|
||||
.. describe:: SENTRY_CLIENT
|
||||
|
||||
In some situations you may wish for a slightly different behavior to how Sentry
|
||||
communicates with your server. For this, Raven allows you to specify a custom
|
||||
client::
|
||||
In some situations you may wish for a slightly different behavior to
|
||||
how Sentry communicates with your server. For this, Raven allows you
|
||||
to specify a custom client::
|
||||
|
||||
SENTRY_CLIENT = 'raven.contrib.django.raven_compat.DjangoClient'
|
||||
SENTRY_CLIENT = 'raven.contrib.django.raven_compat.DjangoClient'
|
||||
|
||||
SENTRY_CELERY_LOGLEVEL
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
.. describe:: SENTRY_CELERY_LOGLEVEL
|
||||
|
||||
If you are also using Celery, there is a handler being automatically registered
|
||||
for you that captures the errors from workers. The default logging level for
|
||||
that handler is ``logging.ERROR`` and can be customized using this setting::
|
||||
If you are also using Celery, there is a handler being automatically
|
||||
registered for you that captures the errors from workers. The default
|
||||
logging level for that handler is ``logging.ERROR`` and can be
|
||||
customized using this setting::
|
||||
|
||||
SENTRY_CELERY_LOGLEVEL = logging.INFO
|
||||
RAVEN_CONFIG = {
|
||||
'CELERY_LOGLEVEL': logging.INFO
|
||||
}
|
||||
SENTRY_CELERY_LOGLEVEL = logging.INFO
|
||||
RAVEN_CONFIG = {
|
||||
'CELERY_LOGLEVEL': logging.INFO
|
||||
}
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
The following things you should keep in mind when using Raven with Django.
|
||||
|
||||
Error Handling Middleware
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -238,6 +259,7 @@ To work around this, you can either disable your error handling middleware, or
|
|||
add something like the following::
|
||||
|
||||
from django.core.signals import got_request_exception
|
||||
|
||||
class MyMiddleware(object):
|
||||
def process_exception(self, request, exception):
|
||||
# Make sure the exception signal is fired for Sentry
|
||||
|
@ -253,6 +275,7 @@ response codes.
|
|||
Or, alternatively, you can just enable Sentry responses::
|
||||
|
||||
from raven.contrib.django.raven_compat.models import sentry_exception_handler
|
||||
|
||||
class MyMiddleware(object):
|
||||
def process_exception(self, request, exception):
|
||||
# Make sure the exception signal is fired for Sentry
|
||||
|
@ -263,12 +286,14 @@ Or, alternatively, you can just enable Sentry responses::
|
|||
Gunicorn
|
||||
~~~~~~~~
|
||||
|
||||
If you are running Django with `gunicorn <http://gunicorn.org/>`_ and using the
|
||||
``gunicorn`` executable, instead of the ``run_gunicorn`` management command, you
|
||||
will need to add a hook to gunicorn to activate Raven::
|
||||
If you are running Django with `gunicorn <http://gunicorn.org/>`_ and
|
||||
using the ``gunicorn`` executable, instead of the ``run_gunicorn``
|
||||
management command, you will need to add a hook to gunicorn to activate
|
||||
Raven::
|
||||
|
||||
from django.core.management import call_command
|
||||
|
||||
def when_ready(server):
|
||||
from django.core.management import call_command
|
||||
call_command('validate')
|
||||
|
||||
Circus
|
||||
|
@ -278,20 +303,22 @@ If you are running Django with `circus <http://circus.rtfd.org/>`_ and
|
|||
`chaussette <http://chaussette.readthedocs.org/>`_ you will also need
|
||||
to add a hook to circus to activate Raven::
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
|
||||
def run_raven(*args, **kwargs):
|
||||
"""Set up raven for django by running a django command.
|
||||
It is necessary because chaussette doesn't run a django command.
|
||||
|
||||
"""
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
if not settings.configured:
|
||||
settings.configure()
|
||||
|
||||
call_command('validate')
|
||||
return True
|
||||
|
||||
And in your circus configuration::
|
||||
And in your circus configuration:
|
||||
|
||||
.. sourcecode:: ini
|
||||
|
||||
[socket:dwebapp]
|
||||
host = 127.0.0.1
|
||||
|
@ -302,4 +329,3 @@ And in your circus configuration::
|
|||
use_sockets = True
|
||||
numprocesses = 2
|
||||
hooks.after_start = dproject.hooks.run_raven
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
Flask
|
||||
=====
|
||||
|
||||
`Flask <http://flask.pocoo.org/>`_ is a popular Python micro webframework.
|
||||
Support for Flask is provided by Raven directly but for some dependencies
|
||||
you need to install raven with the flask feature set.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
If you haven't already, install raven with its explicit Flask dependencies:
|
||||
If you haven't already, install raven with its explicit Flask dependencies::
|
||||
|
||||
pip install raven[flask]
|
||||
|
||||
|
@ -14,10 +18,13 @@ Setup
|
|||
The first thing you'll need to do is to initialize Raven under your application::
|
||||
|
||||
from raven.contrib.flask import Sentry
|
||||
sentry = Sentry(app, dsn='http://public_key:secret_key@example.com/1')
|
||||
sentry = Sentry(app, dsn='___DSN___')
|
||||
|
||||
If you don't specify the ``dsn`` value, we will attempt to read it from your environment under
|
||||
the ``SENTRY_DSN`` key.
|
||||
If you don't specify the ``dsn`` value, we will attempt to read it from
|
||||
your environment under the ``SENTRY_DSN`` key.
|
||||
|
||||
Extended Setup
|
||||
--------------
|
||||
|
||||
You can optionally configure logging too::
|
||||
|
||||
|
@ -44,25 +51,36 @@ You can pass parameters in the ``init_app`` hook::
|
|||
logging=True, level=logging.ERROR)
|
||||
return app
|
||||
|
||||
|
||||
Settings
|
||||
--------
|
||||
|
||||
Additional settings for the client can be configured using ``SENTRY_<setting name>`` in your application's configuration::
|
||||
Additional settings for the client can be configured using
|
||||
``SENTRY_<setting name>`` in your application's configuration::
|
||||
|
||||
class MyConfig(object):
|
||||
SENTRY_DSN = 'http://public_key:secret_key@example.com/1'
|
||||
SENTRY_DSN = '___DSN___'
|
||||
SENTRY_INCLUDE_PATHS = ['myproject']
|
||||
|
||||
If `Flask-Login <https://pypi.python.org/pypi/Flask-Login/>`_ is used by your application (including `Flask-Security <https://pypi.python.org/pypi/Flask-Security/>`_), user information will be captured when an exception or message is captured.
|
||||
By default, only the ``id`` (current_user.get_id()), ``is_authenticated``, and ``is_anonymous`` is captured for the user. If you would like additional attributes on the ``current_user`` to be captured, you can configure them using ``SENTRY_USER_ATTRS``::
|
||||
If `Flask-Login <https://pypi.python.org/pypi/Flask-Login/>`_ is used by
|
||||
your application (including `Flask-Security
|
||||
<https://pypi.python.org/pypi/Flask-Security/>`_), user information will
|
||||
be captured when an exception or message is captured. By default, only
|
||||
the ``id`` (current_user.get_id()), ``is_authenticated``, and
|
||||
``is_anonymous`` is captured for the user. If you would like additional
|
||||
attributes on the ``current_user`` to be captured, you can configure them
|
||||
using ``SENTRY_USER_ATTRS``::
|
||||
|
||||
class MyConfig(object):
|
||||
SENTRY_USER_ATTRS = ['username', 'first_name', 'last_name', 'email']
|
||||
|
||||
``email`` will be captured as ``sentry.interfaces.User.email``, and any additionl attributes will be available under ``sentry.interfaces.User.data``
|
||||
``email`` will be captured as ``sentry.interfaces.User.email``, and any
|
||||
additionl attributes will be available under
|
||||
``sentry.interfaces.User.data``
|
||||
|
||||
You can specify the types of exceptions that should not be reported by Sentry client in your application by setting the ``RAVEN_IGNORE_EXCEPTIONS`` configuration value on your Flask app configuration::
|
||||
You can specify the types of exceptions that should not be reported by
|
||||
Sentry client in your application by setting the
|
||||
``RAVEN_IGNORE_EXCEPTIONS`` configuration value on your Flask app
|
||||
configuration::
|
||||
|
||||
class MyExceptionType(Exception):
|
||||
def __init__(self, message):
|
||||
|
@ -74,25 +92,28 @@ You can specify the types of exceptions that should not be reported by Sentry cl
|
|||
Usage
|
||||
-----
|
||||
|
||||
Once you've configured the Sentry application it will automatically capture uncaught exceptions within Flask. If you
|
||||
want to send additional events, a couple of shortcuts are provided on the Sentry Flask middleware object.
|
||||
Once you've configured the Sentry application it will automatically
|
||||
capture uncaught exceptions within Flask. If you want to send additional
|
||||
events, a couple of shortcuts are provided on the Sentry Flask middleware
|
||||
object.
|
||||
|
||||
Capture an arbitrary exception by calling ``captureException``::
|
||||
|
||||
>>> try:
|
||||
>>> 1 / 0
|
||||
>>> except ZeroDivisionError:
|
||||
>>> sentry.captureException()
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError:
|
||||
sentry.captureException()
|
||||
|
||||
Log a generic message with ``captureMessage``::
|
||||
|
||||
>>> sentry.captureMessage('hello, world!')
|
||||
sentry.captureMessage('hello, world!')
|
||||
|
||||
Getting the last event id
|
||||
-------------------------
|
||||
|
||||
If possible, the last Sentry event ID is stored in the request context ``g.sentry_event_id`` variable.
|
||||
This allow to present the user an error ID if have done a custom error 500 page.
|
||||
If possible, the last Sentry event ID is stored in the request context
|
||||
``g.sentry_event_id`` variable. This allow to present the user an error
|
||||
ID if have done a custom error 500 page.
|
||||
|
||||
.. code-block:: html+jinja
|
||||
|
||||
|
@ -104,10 +125,17 @@ This allow to present the user an error ID if have done a custom error 500 page.
|
|||
Dealing with proxies
|
||||
--------------------
|
||||
|
||||
When your Flask application is behind a proxy such as nginx, Sentry will use the remote address from the proxy, rather than from the actual requesting computer.
|
||||
By using ``ProxyFix`` from `werkzeug.contrib.fixers <http://werkzeug.pocoo.org/docs/0.10/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix>`_ the Flask ``.wsgi_app`` can be modified to send the actual ``REMOTE_ADDR`` along to Sentry. ::
|
||||
When your Flask application is behind a proxy such as nginx, Sentry will
|
||||
use the remote address from the proxy, rather than from the actual
|
||||
requesting computer. By using ``ProxyFix`` from `werkzeug.contrib.fixers
|
||||
<http://werkzeug.pocoo.org/docs/0.10/contrib/fixers/#werkzeug.contrib.fixers.ProxyFix>`_
|
||||
the Flask ``.wsgi_app`` can be modified to send the actual ``REMOTE_ADDR``
|
||||
along to Sentry. ::
|
||||
|
||||
from werkzeug.contrib.fixers import ProxyFix
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||
|
||||
This may also require `changes <http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#proxy-setups>`_ to the proxy configuration to pass the right headers if it isn't doing so already.
|
||||
This may also require `changes
|
||||
<http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#proxy-setups>`_
|
||||
to the proxy configuration to pass the right headers if it isn't doing so
|
||||
already.
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
Integrations
|
||||
============
|
||||
|
||||
.. note:: Some integrations allow specifying these in a standard configuration, otherwise they are generally passed upon
|
||||
instantiation of the Sentry client.
|
||||
The Raven Python module also comes with integration for some commonly used
|
||||
libraries to automatically capture errors from common environments. This
|
||||
means that once you have such an integration configured you typically do
|
||||
not need to report errors manually.
|
||||
|
||||
Some integrations allow specifying these in a standard configuration,
|
||||
otherwise they are generally passed upon instantiation of the Sentry
|
||||
client.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
|
||||
asyncio
|
||||
bottle
|
||||
celery
|
||||
django
|
||||
|
@ -16,7 +21,8 @@ Integrations
|
|||
logging
|
||||
pylons
|
||||
pyramid
|
||||
rq
|
||||
tornado
|
||||
wsgi
|
||||
zerorpc
|
||||
zope
|
||||
tornado
|
||||
|
|
|
@ -15,7 +15,7 @@ First you'll need to configure a handler::
|
|||
You can also automatically configure the default client with a DSN::
|
||||
|
||||
# Configure the default client
|
||||
handler = SentryHandler('http://public:secret@example.com/1')
|
||||
handler = SentryHandler('___DSN___')
|
||||
|
||||
Finally, bind your handler to your context::
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
Logging
|
||||
=======
|
||||
|
||||
Sentry supports the ability to directly tie into the :mod:`logging` module. To
|
||||
use it simply add :class:`SentryHandler` to your logger.
|
||||
.. default-domain:: py
|
||||
|
||||
Sentry supports the ability to directly tie into the :mod:`logging`
|
||||
module. To use it simply add :class:`SentryHandler` to your logger.
|
||||
|
||||
First you'll need to configure a handler::
|
||||
|
||||
|
@ -15,7 +17,7 @@ First you'll need to configure a handler::
|
|||
You can also automatically configure the default client with a DSN::
|
||||
|
||||
# Configure the default client
|
||||
handler = SentryHandler('http://public:secret@example.com/1')
|
||||
handler = SentryHandler('___DSN___')
|
||||
|
||||
Finally, call the :func:`setup_logging` helper function::
|
||||
|
||||
|
@ -31,7 +33,8 @@ Another option is to use :mod:`logging.config.dictConfig`::
|
|||
|
||||
'formatters': {
|
||||
'console': {
|
||||
'format': '[%(asctime)s][%(levelname)s] %(name)s %(filename)s:%(funcName)s:%(lineno)d | %(message)s',
|
||||
'format': '[%(asctime)s][%(levelname)s] %(name)s '
|
||||
'%(filename)s:%(funcName)s:%(lineno)d | %(message)s',
|
||||
'datefmt': '%H:%M:%S',
|
||||
},
|
||||
},
|
||||
|
@ -45,7 +48,7 @@ Another option is to use :mod:`logging.config.dictConfig`::
|
|||
'sentry': {
|
||||
'level': 'ERROR',
|
||||
'class': 'raven.handlers.logging.SentryHandler',
|
||||
'dsn': 'http://public:secret@example.com/1',
|
||||
'dsn': '___DSN___',
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -79,14 +82,21 @@ Sentry to render it based on that information::
|
|||
# If you're actually catching an exception, use `exc_info=True`
|
||||
logger.error('There was an error, with a stacktrace!', exc_info=True)
|
||||
|
||||
# If you don't have an exception, but still want to capture a stacktrace, use the `stack` arg
|
||||
# If you don't have an exception, but still want to capture a
|
||||
# stacktrace, use the `stack` arg
|
||||
logger.error('There was an error, with a stacktrace!', extra={
|
||||
'stack': True,
|
||||
})
|
||||
|
||||
.. note:: Depending on the version of Python you're using, ``extra`` might not be an acceptable keyword argument for a logger's ``.exception()`` method (``.debug()``, ``.info()``, ``.warning()``, ``.error()`` and ``.critical()`` should work fine regardless of Python version). This should be fixed as of Python 3.2. Official issue here: http://bugs.python.org/issue15541.
|
||||
.. note:: Depending on the version of Python you're using, ``extra`` might
|
||||
not be an acceptable keyword argument for a logger's ``.exception()``
|
||||
method (``.debug()``, ``.info()``, ``.warning()``, ``.error()`` and
|
||||
``.critical()`` should work fine regardless of Python version). This
|
||||
should be fixed as of Python 3.2. Official issue here:
|
||||
http://bugs.python.org/issue15541.
|
||||
|
||||
While we don't recommend this, you can also enable implicit stack capturing for all messages::
|
||||
While we don't recommend this, you can also enable implicit stack
|
||||
capturing for all messages::
|
||||
|
||||
client = Client(..., auto_log_stacks=True)
|
||||
handler = SentryHandler(client)
|
||||
|
@ -108,20 +118,16 @@ within your ``extra`` clause::
|
|||
}
|
||||
})
|
||||
|
||||
.. note:: The ``url`` and ``view`` keys are used internally by Sentry within the extra data.
|
||||
.. note:: Any key (in ``data``) prefixed with ``_`` will not automatically output on the Sentry details view.
|
||||
.. note:: The ``url`` and ``view`` keys are used internally by Sentry
|
||||
within the extra data.
|
||||
|
||||
Sentry will intelligently group messages if you use proper string formatting. For example, the following messages would
|
||||
be seen as the same message within Sentry::
|
||||
.. note:: Any key (in ``data``) prefixed with ``_`` will not automatically
|
||||
output on the Sentry details view.
|
||||
|
||||
Sentry will intelligently group messages if you use proper string
|
||||
formatting. For example, the following messages would be seen as the same
|
||||
message within Sentry::
|
||||
|
||||
logger.error('There was some %s error', 'crazy')
|
||||
logger.error('There was some %s error', 'fun')
|
||||
logger.error('There was some %s error', 1)
|
||||
|
||||
.. note::
|
||||
|
||||
Other languages that provide a logging package that is comparable to the
|
||||
python :mod:`logging` package may define a Sentry handler. Check the
|
||||
`Extending Sentry
|
||||
<http://sentry.readthedocs.org/en/latest/developer/client/index.html>`_
|
||||
documentation.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
Pylons
|
||||
======
|
||||
|
||||
Pylons is a framework for Python.
|
||||
|
||||
WSGI Middleware
|
||||
---------------
|
||||
|
||||
|
@ -17,7 +19,7 @@ Configuration is handled via the sentry namespace:
|
|||
.. code-block:: ini
|
||||
|
||||
[sentry]
|
||||
dsn=http://public:secret@example.com/1
|
||||
dsn=___DSN___
|
||||
include_paths=my.package,my.other.package,
|
||||
exclude_paths=my.package.crud
|
||||
|
||||
|
@ -65,5 +67,3 @@ Add the following lines to your project's `.ini` file to setup `SentryHandler`:
|
|||
datefmt = %H:%M:%S
|
||||
|
||||
.. note:: You may want to setup other loggers as well.
|
||||
|
||||
|
||||
|
|
|
@ -8,11 +8,13 @@ Usage
|
|||
|
||||
The simplest way is passing your ``SENTRY_DSN`` through ``rqworker``::
|
||||
|
||||
$ rqworker --sentry-dsn="http://public:secret@example.com/1"
|
||||
$ rqworker --sentry-dsn="___DSN___"
|
||||
|
||||
Custom Client
|
||||
-------------
|
||||
|
||||
It's possible to use a custom ``Client`` object and use your own worker process as an alternative to ``rqworker``.
|
||||
It's possible to use a custom ``Client`` object and use your own worker
|
||||
process as an alternative to ``rqworker``.
|
||||
|
||||
Please see ``rq``'s documentation for more information: http://python-rq.org/patterns/sentry/
|
||||
Please see ``rq``'s documentation for more information:
|
||||
http://python-rq.org/patterns/sentry/
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
Tornado
|
||||
=======
|
||||
|
||||
Tornado is an async web framework for Python.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
|
@ -8,7 +10,6 @@ The first thing you'll need to do is to initialize sentry client under
|
|||
your application
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 2,11,12,13
|
||||
|
||||
import tornado.web
|
||||
from raven.contrib.tornado import AsyncSentryClient
|
||||
|
@ -21,7 +22,7 @@ your application
|
|||
(r"/", MainHandler),
|
||||
])
|
||||
application.sentry_client = AsyncSentryClient(
|
||||
'http://public_key:secret_key@host:port/project'
|
||||
'___DSN___'
|
||||
)
|
||||
|
||||
|
||||
|
@ -36,7 +37,8 @@ can automatically capture uncaught exceptions by inheriting the `SentryMixin` cl
|
|||
import tornado.web
|
||||
from raven.contrib.tornado import SentryMixin
|
||||
|
||||
class UncaughtExceptionExampleHandler(SentryMixin, tornado.web.RequestHandler):
|
||||
class UncaughtExceptionExampleHandler(
|
||||
SentryMixin, tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
1/0
|
||||
|
||||
|
@ -79,7 +81,7 @@ Asynchronous
|
|||
|
||||
.. tip::
|
||||
|
||||
The value returned by the yield is a HTTPResponse obejct.
|
||||
The value returned by the yield is a ``HTTPResponse`` object.
|
||||
|
||||
|
||||
Synchronous
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
ZeroRPC
|
||||
=======
|
||||
|
||||
ZeroRPC is a light-weight, reliable and language-agnostic library for
|
||||
distributed communication between server-side processes.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
|
@ -12,25 +15,17 @@ registered into ZeroRPC's context manager::
|
|||
|
||||
from raven.contrib.zerorpc import SentryMiddleware
|
||||
|
||||
sentry = SentryMiddleware(dsn='udp://public_key:secret_key@example.com:4242/1')
|
||||
sentry = SentryMiddleware(dsn='___DSN___')
|
||||
zerorpc.Context.get_instance().register_middleware(sentry)
|
||||
|
||||
By default, the middleware will hide internal frames from ZeroRPC when it
|
||||
submits exceptions to Sentry. This behavior can be disabled by passing the
|
||||
``hide_zerorpc_frames`` parameter to the middleware::
|
||||
|
||||
sentry = SentryMiddleware(hide_zerorpc_frames=False, dsn='udp://public_key:secret_key@example.com:4242/1')
|
||||
sentry = SentryMiddleware(hide_zerorpc_frames=False, dsn='___DSN___')
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
- ZeroRPC-Python < 0.4.0 is compatible with Raven <= 3.1.0;
|
||||
- ZeroRPC-Python >= 0.4.0 requires Raven > 3.1.0.
|
||||
|
||||
Caveats
|
||||
-------
|
||||
|
||||
Since sending an exception to Sentry will basically block your RPC call, you are
|
||||
*strongly* advised to use the UDP server of Sentry. In any cases, a cleaner and
|
||||
long term solution would be to make Raven requests to the Sentry server
|
||||
asynchronous.
|
||||
|
|
|
@ -18,17 +18,18 @@ A basic setup for logging looks like that:
|
|||
|
||||
%import raven.contrib.zope
|
||||
<sentry>
|
||||
dsn YOUR_DSN
|
||||
dsn ___DSN___
|
||||
level ERROR
|
||||
</sentry>
|
||||
</eventlog>
|
||||
|
||||
This configuration keeps the regular logging to a logfile, but adds logging to sentry for ERRORs.
|
||||
This configuration keeps the regular logging to a logfile, but adds
|
||||
logging to sentry for ERRORs.
|
||||
|
||||
All options of :py:class:`raven.base.Client` are supported. See :ref:`usage-label`
|
||||
All options of :py:class:`raven.base.Client` are supported.
|
||||
|
||||
Nobody writes zope.conf files these days, instead buildout recipe does that.
|
||||
To add the equivalent configuration, you would do this:
|
||||
Nobody writes zope.conf files these days, instead buildout recipe does
|
||||
that. To add the equivalent configuration, you would do this:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
|
@ -42,6 +43,6 @@ To add the equivalent configuration, you would do this:
|
|||
level INFO
|
||||
</logfile>
|
||||
<sentry>
|
||||
dsn YOUR_DSN
|
||||
dsn ___DSN___
|
||||
level ERROR
|
||||
</sentry>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Supported Platforms
|
||||
===================
|
||||
|
||||
- Python 2.6
|
||||
- Python 2.7
|
||||
- Python 3.2
|
||||
- Python 3.3
|
||||
- PyPy
|
||||
- Google App Engine
|
|
@ -0,0 +1,107 @@
|
|||
Transports
|
||||
==========
|
||||
|
||||
A transport is the mechanism in which Raven sends the HTTP request to the
|
||||
Sentry server. By default, Raven uses a threaded asynchronous transport,
|
||||
but you can easily adjust this by modifying your ``SENTRY_DSN`` value.
|
||||
|
||||
Transport registration is done via the URL prefix, so for example, a
|
||||
synchronous transport is as simple as prefixing your ``SENTRY_DSN`` with
|
||||
the ``sync+`` value.
|
||||
|
||||
Options are passed to transports via the querystring.
|
||||
|
||||
All transports should support at least the following options:
|
||||
|
||||
``timeout = 1``
|
||||
The time to wait for a response from the server, in seconds.
|
||||
|
||||
``verify_ssl = 1``
|
||||
If the connection is HTTPS, validate the certificate and hostname.
|
||||
|
||||
``ca_certs = [raven]/data/cacert.pem``
|
||||
A certificate bundle to use when validating SSL connections.
|
||||
|
||||
For example, to increase the timeout and to disable SSL verification::
|
||||
|
||||
SENTRY_DSN = '___DSN___?timeout=5&verify_ssl=0'
|
||||
|
||||
|
||||
aiohttp
|
||||
-------
|
||||
|
||||
Should only be used within a :pep:`3156` compatible event loops
|
||||
(*asyncio* itself and others).
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'aiohttp+___DSN___'
|
||||
|
||||
Eventlet
|
||||
--------
|
||||
|
||||
Should only be used within an Eventlet IO loop.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'eventlet+___DSN___'
|
||||
|
||||
|
||||
Gevent
|
||||
------
|
||||
|
||||
Should only be used within a Gevent IO loop.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'gevent+___DSN___'
|
||||
|
||||
|
||||
Requests
|
||||
--------
|
||||
|
||||
Requires the ``requests`` library. Synchronous.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'requests+___DSN___'
|
||||
|
||||
|
||||
Sync
|
||||
----
|
||||
|
||||
A synchronous blocking transport.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'sync+___DSN___'
|
||||
|
||||
|
||||
Threaded (Default)
|
||||
------------------
|
||||
|
||||
Spawns an async worker for processing messages.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'threaded+___DSN___'
|
||||
|
||||
|
||||
Tornado
|
||||
-------
|
||||
|
||||
Should only be used within a Tornado IO loop.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'tornado+___DSN___'
|
||||
|
||||
|
||||
Twisted
|
||||
-------
|
||||
|
||||
Should only be used within a Twisted event loop.
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'twisted+___DSN___'
|
|
@ -1,68 +0,0 @@
|
|||
Transports
|
||||
==========
|
||||
|
||||
A transport is the mechanism in which Raven sends the HTTP request to the Sentry server. By default, Raven uses a threaded asynchronous transport, but you can easily adjust this by modifying your ``SENTRY_DSN`` value.
|
||||
|
||||
Transport registration is done as part of the Client configuration:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Use the synchronous HTTP transport
|
||||
client = Client('http://public:secret@example.com/1', transport=HTTPTransport)
|
||||
|
||||
Options are passed to transports via the querystring.
|
||||
|
||||
All transports should support at least the following options:
|
||||
|
||||
``timeout = 1``
|
||||
The time to wait for a response from the server, in seconds.
|
||||
|
||||
``verify_ssl = 1``
|
||||
If the connection is HTTPS, validate the certificate and hostname.
|
||||
|
||||
``ca_certs = [raven]/data/cacert.pem``
|
||||
A certificate bundle to use when validating SSL connections.
|
||||
|
||||
For example, to increase the timeout and to disable SSL verification:
|
||||
|
||||
::
|
||||
|
||||
SENTRY_DSN = 'http://public:secret@example.com/1?timeout=5&verify_ssl=0'
|
||||
|
||||
|
||||
Builtin Transports
|
||||
------------------
|
||||
|
||||
.. data:: raven.transport.threaded.ThreadedHTTPTransport
|
||||
|
||||
The default transport. Manages a threaded worker for processing messages asynchronously.
|
||||
|
||||
.. data:: raven.transport.http.HTTPTransport
|
||||
|
||||
A synchronous blocking transport.
|
||||
|
||||
.. data:: raven.transport.eventlet.EventletHTTPTransport
|
||||
|
||||
Should only be used within an Eventlet IO loop.
|
||||
|
||||
.. data:: raven.transport.gevent.GeventedHTTPTransport
|
||||
|
||||
Should only be used within a Gevent IO loop.
|
||||
|
||||
.. data:: raven.transport.requests.RequestsHTTPTransport
|
||||
|
||||
A synchronous transport which relies on the ``requests`` library.
|
||||
|
||||
.. data:: raven.transport.tornado.TornadoHTTPTransport
|
||||
|
||||
Should only be used within a Tornado IO loop.
|
||||
|
||||
.. data:: raven.transport.twisted.TwistedHTTPTransport
|
||||
|
||||
Should only be used within a Twisted event loop.
|
||||
|
||||
|
||||
Other Transports
|
||||
----------------
|
||||
|
||||
- `aiohttp <https://github.com/getsentry/raven-aiohttp>`_
|
|
@ -1,78 +1,79 @@
|
|||
Usage
|
||||
=====
|
||||
|
||||
This gives a basic overview of how to use the raven client with Python
|
||||
directly.
|
||||
|
||||
Capture an Error
|
||||
----------------
|
||||
|
||||
::
|
||||
The most basic use for raven is to record one specific error that occurs::
|
||||
|
||||
from raven import Client
|
||||
|
||||
client = Client('http://dd2c825ff9b1417d88a99573903ebf80:91631495b10b45f8a1cdbc492088da6a@localhost:9000/1')
|
||||
client = Client('___DSN___')
|
||||
|
||||
try:
|
||||
1 / 0
|
||||
except ZeroDivisionError:
|
||||
client.captureException()
|
||||
|
||||
Reporting an Event
|
||||
------------------
|
||||
|
||||
To report an arbitrary event you can use the
|
||||
:py:meth:`~raven.Client.capture` method. This is the most low-level
|
||||
method available. In most cases you would want to use the
|
||||
:py:meth:`~raven.Client.captureMessage` method instead however which
|
||||
directly reports a message::
|
||||
|
||||
client.captureMessage('Something went fundamentally wrong')
|
||||
|
||||
|
||||
Adding Context
|
||||
--------------
|
||||
|
||||
A few helpers exist for adding context to a request. These are most useful within a middleware, or some kind of context wrapper.
|
||||
The raven client internally keeps a thread local mapping that can carry
|
||||
additional information. Whenever a message is submitted to Sentry that
|
||||
additional data will be passed along.
|
||||
|
||||
::
|
||||
For instance if you use a web framework, you can use this to inject
|
||||
additional information into the context. The basic primitive for this is
|
||||
the :py:attr:`~raven.Client.context` attribute. It provides a `merge()`
|
||||
and `clear()` function that can be used::
|
||||
|
||||
# If you're using the Django client, we already deal with this for you.
|
||||
class DjangoUserContext(object):
|
||||
def process_request(self, request):
|
||||
client.user_context({
|
||||
'email': request.user.email,
|
||||
})
|
||||
|
||||
def process_response(self, request):
|
||||
def handle_request(request):
|
||||
client.context.merge({'user': {
|
||||
'email': request.user.email
|
||||
}})
|
||||
try:
|
||||
...
|
||||
finally:
|
||||
client.context.clear()
|
||||
|
||||
|
||||
See also:
|
||||
|
||||
- Client.extra_context
|
||||
- Client.http_context
|
||||
- Client.tags_context
|
||||
|
||||
|
||||
Testing the Client
|
||||
------------------
|
||||
|
||||
Once you've got your server configured, you can test the Raven client by using its CLI::
|
||||
Once you've got your server configured, you can test the Raven client by
|
||||
using its CLI::
|
||||
|
||||
raven test <DSN value>
|
||||
raven test ___DSN___
|
||||
|
||||
If you've configured your environment to have SENTRY_DSN available, you can simply drop
|
||||
the optional DSN argument::
|
||||
If you've configured your environment to have ``SENTRY_DSN`` available, you
|
||||
can simply drop the optional DSN argument::
|
||||
|
||||
raven test
|
||||
raven test
|
||||
|
||||
You should get something like the following, assuming you're configured everything correctly::
|
||||
|
||||
$ raven test http://dd2c825ff9b1417d88a99573903ebf80:91631495b10b45f8a1cdbc492088da6a@localhost:9000/1
|
||||
Using DSN configuration:
|
||||
http://dd2c825ff9b1417d88a99573903ebf80:91631495b10b45f8a1cdbc492088da6a@localhost:9000/1
|
||||
$ raven test sync+___DSN___
|
||||
Using DSN configuration:
|
||||
sync+___DSN___
|
||||
|
||||
Client configuration:
|
||||
servers : ['http://localhost:9000/api/store/']
|
||||
project : 1
|
||||
public_key : dd2c825ff9b1417d88a99573903ebf80
|
||||
secret_key : 91631495b10b45f8a1cdbc492088da6a
|
||||
Client configuration:
|
||||
servers : ['___API_URL___/api/store/']
|
||||
project : ___PROJECT_ID___
|
||||
public_key : ___PUBLIC_KEY___
|
||||
secret_key : ___SECRET_KEY___
|
||||
|
||||
Sending a test message... success!
|
||||
|
||||
The test message can be viewed at the following URL:
|
||||
http://localhost:9000/1/search/?q=c988bf5cb7db4653825c92f6864e7206$b8a6fbd29cc9113a149ad62cf7e0ddd5
|
||||
|
||||
|
||||
Client API
|
||||
----------
|
||||
|
||||
.. autoclass:: raven.base.Client
|
||||
:members:
|
||||
Sending a test message... success!
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"configurations": {
|
||||
"python": {
|
||||
"name": "Python",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": false,
|
||||
"doc_link": "installation",
|
||||
"snippets": [
|
||||
"installation#installation",
|
||||
"usage#capture-an-error",
|
||||
"usage#reporting-an-event"
|
||||
]
|
||||
},
|
||||
"python-flask": {
|
||||
"name": "Flask",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/flask",
|
||||
"snippets": [
|
||||
"integrations/flask#installation",
|
||||
"integrations/flask#setup"
|
||||
]
|
||||
},
|
||||
"python-bottle": {
|
||||
"name": "Bottle",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/bottle",
|
||||
"snippets": [
|
||||
"integrations/bottle#setup",
|
||||
"integrations/bottle#usage"
|
||||
]
|
||||
},
|
||||
"python-celery": {
|
||||
"name": "Celery",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/celery",
|
||||
"snippets": [
|
||||
"integrations/celery"
|
||||
]
|
||||
},
|
||||
"python-django": {
|
||||
"name": "Django",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/django",
|
||||
"snippets": [
|
||||
"integrations/django#setup"
|
||||
]
|
||||
},
|
||||
"python-pylons": {
|
||||
"name": "Pylons",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/pylons",
|
||||
"snippets": [
|
||||
"integrations/pylons#wsgi-middleware",
|
||||
"integrations/pylons#logger-setup"
|
||||
]
|
||||
},
|
||||
"python-pyramid": {
|
||||
"name": "Pyramid",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/pyramid",
|
||||
"snippets": [
|
||||
"integrations/pyramid#pastedeploy-filter",
|
||||
"integrations/pyramid#logger-setup"
|
||||
]
|
||||
},
|
||||
"python-tornado": {
|
||||
"name": "Tornado",
|
||||
"client_lib": "raven-python",
|
||||
"is_framework": true,
|
||||
"doc_link": "integrations/tornado",
|
||||
"snippets": [
|
||||
"integrations/tornado#setup",
|
||||
"integrations/tornado#usage"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue