summaryrefslogtreecommitdiff
path: root/docs/integrations/logging.rst
blob: 106a17b71a7960dae732e6713dea1800f45d8715 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
Logging
=======

.. default-domain:: py

Installation
------------

If you haven't already, start by downloading Raven. The easiest way is
with *pip*::

	pip install raven --upgrade

Setup
-----
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::

    from raven.handlers.logging import SentryHandler

    # Manually specify a client
    client = Client(...)
    handler = SentryHandler(client)

You can also automatically configure the default client with a DSN::

    # Configure the default client
    handler = SentryHandler('___DSN___')

You may want to specify the logging level at this point so you don't send INFO or DEBUG messages to Sentry::

    handler.setLevel(logging.ERROR)

Finally, call the :func:`setup_logging` helper function::

    from raven.conf import setup_logging

    setup_logging(handler)

Another option is to use :mod:`logging.config.dictConfig`::

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': True,

        'formatters': {
            'console': {
                'format': '[%(asctime)s][%(levelname)s] %(name)s '
                          '%(filename)s:%(funcName)s:%(lineno)d | %(message)s',
                'datefmt': '%H:%M:%S',
                },
            },

        'handlers': {
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
                'formatter': 'console'
                },
            'sentry': {
                'level': 'ERROR',
                'class': 'raven.handlers.logging.SentryHandler',
                'dsn': '___DSN___',
                },
            },

        'loggers': {
            '': {
                'handlers': ['console', 'sentry'],
                'level': 'DEBUG',
                'propagate': False,
                },
            'your_app': {
                'level': 'DEBUG',
                'propagate': True,
            },
        }
    }

Usage
~~~~~

A recommended pattern in logging is to simply reference the modules name for
each logger, so for example, you might at the top of your module define the
following::

    import logging
    logger = logging.getLogger(__name__)

You can also use the ``exc_info`` and ``extra={'stack': True}`` arguments on
your ``log`` methods. This will store the appropriate information and allow
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
    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 2.7.4 and 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::

    client = Client(..., auto_log_stacks=True)
    handler = SentryHandler(client)

    logger.error('There was an error, with a stacktrace!')

Passing tags and user context is also available through extra::

    logger.error('There was an error, with user context and tags'), extra={
        'user': {'email': 'test@test.com'},
        'tags': {'database': '1.0'},
    })

You may also pass additional information to be stored as meta information with
the event. As long as the key name is not reserved and not private (_foo) it
will be displayed on the Sentry dashboard. To do this, pass it as ``data``
within your ``extra`` clause::

    logger.error('There was some crazy error', exc_info=True, extra={
        # Optionally you can pass additional arguments to specify request info
        'culprit': 'my.view.name',
        'fingerprint': [...],

        'data': {
            # You may specify any values here and Sentry will log and output them
            'username': request.user.username,
        }
    })

.. 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.

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)

Exclusions
~~~~~~~~~~

You can also configure some logging exclusions during setup. These loggers
will not propagate their logs to the Sentry handler::

    from raven.conf import setup_logging

    setup_logging(handler, exclude=("logger1", "logger2", ...))