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

breadcrumb-system.mddocs/

0

# Breadcrumb System

1

2

Raven's breadcrumb system provides automatic and manual tracking of user actions and application state leading up to errors, creating a timeline of events that helps with debugging and understanding error context.

3

4

## Capabilities

5

6

### Breadcrumb Buffer

7

8

Core breadcrumb storage and management with size limits and processing.

9

10

```python { .api }

11

from raven.breadcrumbs import BreadcrumbBuffer

12

13

class BreadcrumbBuffer:

14

def __init__(self, limit=100, message_max_length=1024):

15

"""

16

Initialize breadcrumb buffer with configurable limits.

17

18

Parameters:

19

- limit (int): Maximum number of breadcrumbs to store

20

- message_max_length (int): Maximum length of breadcrumb messages

21

"""

22

23

def record(self, timestamp=None, level=None, message=None, category=None,

24

data=None, type=None, processor=None):

25

"""

26

Record a breadcrumb.

27

28

Parameters:

29

- timestamp (datetime): Breadcrumb timestamp (defaults to now)

30

- level (str): Breadcrumb level ('debug', 'info', 'warning', 'error', 'critical')

31

- message (str): Breadcrumb message

32

- category (str): Breadcrumb category

33

- data (dict): Additional breadcrumb data

34

- type (str): Breadcrumb type

35

- processor (callable): Custom breadcrumb processor

36

"""

37

38

def clear(self):

39

"""Clear all breadcrumbs from buffer."""

40

41

def get_buffer(self):

42

"""

43

Get processed breadcrumbs for event inclusion.

44

45

Returns:

46

list: List of processed breadcrumb dictionaries

47

"""

48

49

def format(self, result):

50

"""

51

Format breadcrumb data, applying length limits.

52

53

Parameters:

54

- result (dict): Raw breadcrumb data

55

56

Returns:

57

dict: Formatted breadcrumb data

58

"""

59

```

60

61

### Breadcrumb Deduplication

62

63

Prevent duplicate consecutive breadcrumbs.

64

65

```python { .api }

66

from raven.breadcrumbs import event_payload_considered_equal

67

68

def event_payload_considered_equal(a, b):

69

"""

70

Check if two breadcrumb payloads are considered equal for deduplication.

71

72

Parameters:

73

- a (dict): First breadcrumb payload

74

- b (dict): Second breadcrumb payload

75

76

Returns:

77

bool: True if payloads are considered equal

78

"""

79

```

80

81

### Global Breadcrumb Functions

82

83

Module-level functions for recording breadcrumbs across all active clients.

84

85

```python { .api }

86

from raven.breadcrumbs import record, record_breadcrumb

87

88

def record(**kwargs):

89

"""

90

Record breadcrumb for all active clients.

91

92

Parameters:

93

- message (str): Breadcrumb message

94

- timestamp (datetime): Breadcrumb timestamp

95

- level (str): Breadcrumb level

96

- category (str): Breadcrumb category

97

- data (dict): Additional breadcrumb data

98

- type (str): Breadcrumb type

99

- processor (callable): Custom breadcrumb processor

100

"""

101

102

def record_breadcrumb(type, **kwargs):

103

"""

104

Legacy breadcrumb recording function.

105

106

Parameters:

107

- type (str): Breadcrumb type

108

- **kwargs: Breadcrumb data

109

"""

110

```

111

112

### Automatic Breadcrumb Collection

113

114

Functions for enabling automatic breadcrumb collection from various sources.

115

116

```python { .api }

117

from raven.breadcrumbs import (

118

install_logging_hook, ignore_logger, register_logging_handler, hook_libraries

119

)

120

121

def install_logging_hook():

122

"""Install logging breadcrumb hook for automatic log capture."""

123

124

def ignore_logger(name_or_logger, allow_level=None):

125

"""

126

Ignore logger for breadcrumb collection.

127

128

Parameters:

129

- name_or_logger (str|Logger): Logger name or instance to ignore

130

- allow_level (int): Optional minimum level to still capture

131

"""

132

133

def register_logging_handler(callback):

134

"""

135

Register custom logging handler for breadcrumbs.

136

137

Parameters:

138

- callback (callable): Handler function for log records

139

"""

140

141

def hook_libraries(libraries):

142

"""

143

Hook libraries for automatic breadcrumb collection.

144

145

Parameters:

146

- libraries (list): List of library names to hook

147

"""

148

```

149

150

### Client Breadcrumb Methods

151

152

Client methods for breadcrumb management and recording.

153

154

```python { .api }

155

# From Client class

156

def captureBreadcrumb(self, message=None, timestamp=None, level=None,

157

category=None, data=None, type=None, processor=None):

158

"""

159

Record breadcrumb for this client.

160

161

Parameters:

162

- message (str): Breadcrumb message

163

- timestamp (datetime): Breadcrumb timestamp

164

- level (str): Breadcrumb level

165

- category (str): Breadcrumb category

166

- data (dict): Additional breadcrumb data

167

- type (str): Breadcrumb type

168

- processor (callable): Custom breadcrumb processor

169

"""

170

```

171

172

## Usage Examples

173

174

### Manual Breadcrumb Recording

175

176

```python

177

from raven import Client

178

179

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

180

181

def process_user_order():

182

# Record user action

183

client.captureBreadcrumb(

184

message='User started checkout process',

185

category='ui.click',

186

level='info',

187

data={'button_id': 'checkout-btn', 'cart_items': 3}

188

)

189

190

# Record API call

191

client.captureBreadcrumb(

192

message='Calling payment API',

193

category='http',

194

level='info',

195

data={'url': '/api/payments', 'method': 'POST'}

196

)

197

198

try:

199

payment_result = process_payment()

200

201

# Record successful operation

202

client.captureBreadcrumb(

203

message='Payment processed successfully',

204

category='payment',

205

level='info',

206

data={'transaction_id': payment_result.id}

207

)

208

209

except PaymentError as e:

210

# Record failure details

211

client.captureBreadcrumb(

212

message='Payment processing failed',

213

category='payment',

214

level='error',

215

data={'error_code': e.code, 'error_message': str(e)}

216

)

217

218

# Exception will include all breadcrumbs

219

client.captureException()

220

raise

221

```

222

223

### Automatic Logging Breadcrumbs

224

225

```python

226

from raven import Client

227

from raven.breadcrumbs import install_logging_hook, ignore_logger

228

import logging

229

230

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

231

232

# Enable automatic logging breadcrumbs

233

install_logging_hook()

234

235

# Ignore noisy loggers

236

ignore_logger('urllib3')

237

ignore_logger('requests.packages.urllib3')

238

239

# Configure logging

240

logging.basicConfig(level=logging.INFO)

241

logger = logging.getLogger(__name__)

242

243

def user_workflow():

244

logger.info('User login started')

245

246

try:

247

authenticate_user()

248

logger.info('User authenticated successfully')

249

250

load_user_data()

251

logger.info('User data loaded')

252

253

process_request()

254

logger.info('Request processed')

255

256

except AuthenticationError:

257

logger.error('Authentication failed')

258

client.captureException() # Includes log breadcrumbs

259

except Exception:

260

logger.exception('Unexpected error in user workflow')

261

client.captureException() # Includes log breadcrumbs

262

```

263

264

### Web Request Breadcrumbs

265

266

```python

267

from flask import Flask, request

268

from raven.contrib.flask import Sentry

269

270

app = Flask(__name__)

271

sentry = Sentry(app)

272

273

@app.before_request

274

def before_request():

275

# Record request start

276

sentry.client.captureBreadcrumb(

277

message=f'{request.method} {request.path}',

278

category='http.request',

279

level='info',

280

data={

281

'method': request.method,

282

'url': request.url,

283

'headers': dict(request.headers),

284

'query_string': request.query_string.decode()

285

}

286

)

287

288

@app.after_request

289

def after_request(response):

290

# Record response

291

sentry.client.captureBreadcrumb(

292

message=f'Response {response.status_code}',

293

category='http.response',

294

level='info' if response.status_code < 400 else 'warning',

295

data={

296

'status_code': response.status_code,

297

'content_length': response.content_length

298

}

299

)

300

return response

301

302

@app.route('/api/users/<int:user_id>')

303

def get_user(user_id):

304

# Record business logic steps

305

sentry.client.captureBreadcrumb(

306

message=f'Loading user {user_id}',

307

category='db.query',

308

level='info',

309

data={'user_id': user_id}

310

)

311

312

try:

313

user = User.query.get(user_id)

314

if not user:

315

sentry.client.captureBreadcrumb(

316

message='User not found',

317

category='business.logic',

318

level='warning',

319

data={'user_id': user_id}

320

)

321

return {'error': 'User not found'}, 404

322

323

return user.to_dict()

324

325

except DatabaseError:

326

# Exception includes all request breadcrumbs

327

sentry.captureException()

328

return {'error': 'Database error'}, 500

329

```

330

331

### Custom Breadcrumb Processors

332

333

```python

334

from raven import Client

335

import json

336

337

def sanitize_breadcrumb_data(data):

338

"""Remove sensitive data from breadcrumb data."""

339

if not isinstance(data, dict):

340

return data

341

342

sanitized = {}

343

for key, value in data.items():

344

if key.lower() in ('password', 'token', 'secret', 'key'):

345

sanitized[key] = '[FILTERED]'

346

elif isinstance(value, dict):

347

sanitized[key] = sanitize_breadcrumb_data(value)

348

else:

349

sanitized[key] = value

350

351

return sanitized

352

353

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

354

355

def api_call_breadcrumb(url, method, payload=None, response=None):

356

"""Record API call with sanitized data."""

357

breadcrumb_data = {

358

'url': url,

359

'method': method

360

}

361

362

if payload:

363

breadcrumb_data['payload'] = sanitize_breadcrumb_data(payload)

364

365

if response:

366

breadcrumb_data['response'] = {

367

'status': response.get('status'),

368

'size': len(str(response)) if response else 0

369

}

370

371

client.captureBreadcrumb(

372

message=f'{method} {url}',

373

category='api.call',

374

level='info',

375

data=breadcrumb_data,

376

processor=sanitize_breadcrumb_data

377

)

378

379

# Usage

380

api_call_breadcrumb(

381

'/api/auth/login',

382

'POST',

383

payload={'username': 'john', 'password': 'secret123'},

384

response={'status': 200, 'token': 'jwt_token_here'}

385

)

386

```

387

388

### Database Query Breadcrumbs

389

390

```python

391

from raven import Client

392

import time

393

394

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

395

396

class DatabaseLogger:

397

def __init__(self, client):

398

self.client = client

399

400

def log_query(self, query, params=None, duration=None):

401

# Sanitize query parameters

402

safe_params = self._sanitize_params(params) if params else None

403

404

self.client.captureBreadcrumb(

405

message=f'Database query: {query[:50]}...' if len(query) > 50 else query,

406

category='db.sql',

407

level='info',

408

data={

409

'query': query,

410

'params': safe_params,

411

'duration_ms': duration * 1000 if duration else None

412

}

413

)

414

415

def _sanitize_params(self, params):

416

if isinstance(params, (list, tuple)):

417

return [self._sanitize_value(p) for p in params]

418

elif isinstance(params, dict):

419

return {k: self._sanitize_value(v) for k, v in params.items()}

420

return params

421

422

def _sanitize_value(self, value):

423

if isinstance(value, str) and len(value) > 100:

424

return value[:97] + '...'

425

return value

426

427

db_logger = DatabaseLogger(client)

428

429

def get_user_orders(user_id):

430

start_time = time.time()

431

432

query = "SELECT * FROM orders WHERE user_id = %s ORDER BY created_at DESC"

433

434

try:

435

cursor.execute(query, (user_id,))

436

results = cursor.fetchall()

437

438

duration = time.time() - start_time

439

db_logger.log_query(query, (user_id,), duration)

440

441

return results

442

443

except DatabaseError:

444

duration = time.time() - start_time

445

db_logger.log_query(query, (user_id,), duration)

446

client.captureException() # Includes query breadcrumb

447

raise

448

```

449

450

### Breadcrumb Performance Optimization

451

452

```python

453

from raven import Client

454

from raven.breadcrumbs import BreadcrumbBuffer

455

456

class OptimizedBreadcrumbBuffer(BreadcrumbBuffer):

457

def __init__(self, max_buffer_size=100, max_data_size=1024):

458

super().__init__(max_buffer_size)

459

self.max_data_size = max_data_size

460

461

def record(self, **kwargs):

462

# Limit data size to prevent memory issues

463

if 'data' in kwargs and kwargs['data']:

464

kwargs['data'] = self._truncate_data(kwargs['data'])

465

466

# Skip duplicate consecutive breadcrumbs

467

if self._is_duplicate(kwargs):

468

return

469

470

super().record(**kwargs)

471

472

def _truncate_data(self, data):

473

if not isinstance(data, dict):

474

return data

475

476

truncated = {}

477

total_size = 0

478

479

for key, value in data.items():

480

value_str = str(value)

481

if total_size + len(value_str) > self.max_data_size:

482

truncated[key] = value_str[:self.max_data_size - total_size - 3] + '...'

483

break

484

485

truncated[key] = value

486

total_size += len(value_str)

487

488

return truncated

489

490

def _is_duplicate(self, new_breadcrumb):

491

if not self.buffer:

492

return False

493

494

last_breadcrumb = self.buffer[-1]

495

return (

496

last_breadcrumb.get('message') == new_breadcrumb.get('message') and

497

last_breadcrumb.get('category') == new_breadcrumb.get('category')

498

)

499

500

# Use optimized buffer

501

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

502

client.context.breadcrumbs = OptimizedBreadcrumbBuffer(max_buffer_size=50)

503

```

504

505

### Global Breadcrumb Recording

506

507

```python

508

from raven.breadcrumbs import record

509

510

# Record breadcrumbs globally (affects all active clients)

511

def track_user_action(action, details=None):

512

record(

513

message=f'User action: {action}',

514

category='user.action',

515

level='info',

516

data=details or {}

517

)

518

519

def track_system_event(event, level='info', details=None):

520

record(

521

message=f'System event: {event}',

522

category='system',

523

level=level,

524

data=details or {}

525

)

526

527

# Usage throughout application

528

track_user_action('login', {'username': 'john_doe'})

529

track_user_action('view_product', {'product_id': 123})

530

track_system_event('cache_miss', 'warning', {'key': 'user_123'})

531

track_system_event('background_job_completed', 'info', {'job_id': 'abc123'})

532

```