or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

breadcrumb-system.mdcontext-management.mdcore-client.mddata-processing.mdframework-integrations.mdindex.mdlogging-integration.mdtransport-layer.md

logging-integration.mddocs/

0

# Logging Integration

1

2

Raven provides native Python logging integration, automatically capturing log records as Sentry events with configurable filtering, formatting, and context inclusion.

3

4

## Capabilities

5

6

### Sentry Logging Handler

7

8

Python logging handler that sends log records to Sentry as events.

9

10

```python { .api }

11

from raven.handlers.logging import SentryHandler

12

13

class SentryHandler(logging.Handler):

14

def __init__(self, client=None, dsn=None, level=logging.NOTSET,

15

client_cls=None, tags=None, extra=None, **kwargs):

16

"""

17

Logging handler for Sentry integration.

18

19

Parameters:

20

- client (Client): Existing Sentry client instance

21

- dsn (str): Sentry DSN for new client creation

22

- level (int): Minimum logging level

23

- client_cls (type): Custom client class

24

- tags (dict): Default tags for all log events

25

- extra (dict): Default extra data for all log events

26

"""

27

28

def emit(self, record):

29

"""

30

Process log record and send to Sentry.

31

32

Parameters:

33

- record (LogRecord): Python logging record

34

"""

35

36

def can_record(self, record):

37

"""

38

Determine if record should be processed.

39

40

Parameters:

41

- record (LogRecord): Python logging record

42

43

Returns:

44

bool: True if record should be sent to Sentry

45

"""

46

```

47

48

### Logbook Integration

49

50

Integration with the Logbook logging library.

51

52

```python { .api }

53

from raven.handlers.logbook import SentryHandler as LogbookSentryHandler

54

55

class SentryHandler(logbook.Handler):

56

def __init__(self, client=None, dsn=None, level=logbook.NOTSET, **kwargs):

57

"""

58

Logbook handler for Sentry integration.

59

60

Parameters:

61

- client (Client): Existing Sentry client instance

62

- dsn (str): Sentry DSN for new client creation

63

- level (int): Minimum logging level

64

"""

65

66

def emit(self, record):

67

"""Process Logbook record and send to Sentry."""

68

```

69

70

### Logging Configuration

71

72

Utility function for configuring logging to pipe to Sentry.

73

74

```python { .api }

75

from raven.conf import setup_logging, EXCLUDE_LOGGER_DEFAULTS

76

77

def setup_logging(handler, exclude=EXCLUDE_LOGGER_DEFAULTS):

78

"""

79

Configure logging to pipe to Sentry.

80

81

Parameters:

82

- handler (Handler): Sentry logging handler instance

83

- exclude (tuple): Logger names to exclude from Sentry

84

85

Returns:

86

bool: True if logging was successfully configured

87

"""

88

89

# Default excluded loggers

90

EXCLUDE_LOGGER_DEFAULTS = (

91

'raven',

92

'gunicorn',

93

'south',

94

'sentry.errors',

95

'django.request',

96

'dill',

97

)

98

```

99

100

## Usage Examples

101

102

### Basic Logging Setup

103

104

```python

105

import logging

106

from raven import Client

107

from raven.handlers.logging import SentryHandler

108

from raven.conf import setup_logging

109

110

# Create client and handler

111

client = Client('https://your-dsn@sentry.io/project-id')

112

handler = SentryHandler(client)

113

handler.setLevel(logging.ERROR)

114

115

# Setup logging

116

setup_logging(handler)

117

118

# Use logging normally

119

logger = logging.getLogger(__name__)

120

121

logger.info('This will not be sent to Sentry')

122

logger.error('This error will be sent to Sentry')

123

logger.exception('This exception will be sent with stack trace')

124

```

125

126

### Advanced Handler Configuration

127

128

```python

129

import logging

130

from raven.handlers.logging import SentryHandler

131

132

# Handler with custom tags and extra data

133

handler = SentryHandler(

134

dsn='https://your-dsn@sentry.io/project-id',

135

level=logging.WARNING,

136

tags={'component': 'auth', 'environment': 'prod'},

137

extra={'server': 'web-01', 'version': '1.2.3'}

138

)

139

140

# Add to specific logger

141

logger = logging.getLogger('myapp.auth')

142

logger.addHandler(handler)

143

logger.setLevel(logging.WARNING)

144

145

# Log with additional context

146

logger.warning('Login attempt failed', extra={

147

'user_id': 123,

148

'ip_address': '192.168.1.1',

149

'user_agent': 'Mozilla/5.0...'

150

})

151

```

152

153

### Custom Handler with Filtering

154

155

```python

156

import logging

157

from raven.handlers.logging import SentryHandler

158

159

class FilteredSentryHandler(SentryHandler):

160

def can_record(self, record):

161

# Skip sensitive operations

162

if hasattr(record, 'funcName') and 'password' in record.funcName:

163

return False

164

165

# Only send errors from specific modules

166

if record.levelno >= logging.ERROR:

167

return record.name.startswith('myapp.')

168

169

return super().can_record(record)

170

171

handler = FilteredSentryHandler('https://your-dsn@sentry.io/project-id')

172

```

173

174

### Structured Logging Configuration

175

176

```python

177

import logging.config

178

179

LOGGING_CONFIG = {

180

'version': 1,

181

'disable_existing_loggers': False,

182

'formatters': {

183

'verbose': {

184

'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',

185

'style': '{',

186

},

187

},

188

'handlers': {

189

'console': {

190

'class': 'logging.StreamHandler',

191

'formatter': 'verbose',

192

},

193

'sentry': {

194

'class': 'raven.handlers.logging.SentryHandler',

195

'dsn': 'https://your-dsn@sentry.io/project-id',

196

'level': 'ERROR',

197

'tags': {'environment': 'production'},

198

},

199

},

200

'loggers': {

201

'myapp': {

202

'handlers': ['console', 'sentry'],

203

'level': 'INFO',

204

'propagate': False,

205

},

206

'django': {

207

'handlers': ['console'],

208

'level': 'INFO',

209

'propagate': False,

210

},

211

},

212

'root': {

213

'handlers': ['console', 'sentry'],

214

'level': 'WARNING',

215

},

216

}

217

218

logging.config.dictConfig(LOGGING_CONFIG)

219

```

220

221

### Logbook Integration

222

223

```python

224

import logbook

225

from raven.handlers.logbook import SentryHandler

226

227

# Setup Logbook with Sentry

228

handler = SentryHandler('https://your-dsn@sentry.io/project-id')

229

230

with handler:

231

logger = logbook.Logger(__name__)

232

233

logger.info('This is just info')

234

logger.error('This error goes to Sentry')

235

236

try:

237

1/0

238

except ZeroDivisionError:

239

logger.exception('Division by zero error')

240

```

241

242

### Context-Aware Logging

243

244

```python

245

import logging

246

from raven import Client

247

from raven.handlers.logging import SentryHandler

248

249

client = Client('https://your-dsn@sentry.io/project-id')

250

handler = SentryHandler(client)

251

252

logger = logging.getLogger(__name__)

253

logger.addHandler(handler)

254

logger.setLevel(logging.ERROR)

255

256

def process_user_request(user_id, request_data):

257

# Set context for all events in this request

258

client.user_context({'id': user_id})

259

client.tags_context({'operation': 'user_request'})

260

261

try:

262

result = complex_operation(request_data)

263

logger.info('Request processed successfully')

264

return result

265

except Exception as e:

266

# This will include the user context

267

logger.exception('Request processing failed')

268

raise

269

```

270

271

### Performance Considerations

272

273

```python

274

import logging

275

from raven.handlers.logging import SentryHandler

276

277

class ThrottledSentryHandler(SentryHandler):

278

def __init__(self, *args, **kwargs):

279

super().__init__(*args, **kwargs)

280

self._error_counts = {}

281

self._max_errors_per_minute = 10

282

283

def can_record(self, record):

284

if not super().can_record(record):

285

return False

286

287

# Throttling logic to prevent spam

288

import time

289

now = time.time()

290

minute = int(now // 60)

291

292

key = f"{record.name}:{record.levelno}"

293

if key not in self._error_counts:

294

self._error_counts[key] = {}

295

296

current_count = self._error_counts[key].get(minute, 0)

297

if current_count >= self._max_errors_per_minute:

298

return False

299

300

self._error_counts[key][minute] = current_count + 1

301

302

# Clean old entries

303

for k in list(self._error_counts.keys()):

304

self._error_counts[k] = {

305

m: c for m, c in self._error_counts[k].items()

306

if m >= minute - 5

307

}

308

309

return True

310

```