or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-concurrency.mddebugging.mdgreen-stdlib.mdindex.mdmonkey-patching.mdnetworking.mdresource-pooling.mdsynchronization.mdthread-pools.mdweb-server.md

debugging.mddocs/

0

# Debugging

1

2

Tools for debugging, introspection, and monitoring eventlet applications including tracing, hub inspection, and performance analysis. These utilities help diagnose issues in concurrent greenthread applications.

3

4

## Capabilities

5

6

### Execution Tracing

7

8

Tools for tracing greenthread execution and function calls.

9

10

```python { .api }

11

def spew():

12

"""

13

Install a detailed tracing hook that prints every function call.

14

Useful for debugging greenthread execution flow.

15

16

Returns:

17

None

18

19

Note:

20

Produces very verbose output. Use unspew() to disable.

21

"""

22

23

def unspew():

24

"""

25

Remove the tracing hook installed by spew().

26

27

Returns:

28

None

29

"""

30

```

31

32

### Hub Inspection

33

34

Tools for inspecting the event hub's internal state.

35

36

```python { .api }

37

def format_hub_listeners():

38

"""

39

Format the current hub's file descriptor listeners as a string.

40

41

Returns:

42

str: formatted information about active listeners

43

"""

44

45

def format_hub_timers():

46

"""

47

Format the current hub's timers as a string.

48

49

Returns:

50

str: formatted information about scheduled timers

51

"""

52

53

def hub_listener_stacks(enabled):

54

"""

55

Toggle recording of stack traces for hub listeners.

56

57

Parameters:

58

- enabled: bool, whether to record listener stack traces

59

60

Returns:

61

None

62

"""

63

64

def hub_timer_stacks(enabled):

65

"""

66

Toggle recording of stack traces for hub timers.

67

68

Parameters:

69

- enabled: bool, whether to record timer stack traces

70

71

Returns:

72

None

73

"""

74

75

def hub_exceptions(enabled):

76

"""

77

Toggle printing of exceptions that occur in hub timers.

78

79

Parameters:

80

- enabled: bool, whether to print hub timer exceptions

81

82

Returns:

83

None

84

"""

85

86

def hub_prevent_multiple_readers(enabled):

87

"""

88

Toggle prevention of multiple readers on the same file descriptor.

89

90

Parameters:

91

- enabled: bool, whether to prevent multiple readers

92

93

Returns:

94

None

95

"""

96

97

def hub_blocking_detection(enabled, resolution=1):

98

"""

99

Toggle detection of blocking behavior in the hub.

100

101

Parameters:

102

- enabled: bool, whether to enable blocking detection

103

- resolution: float, detection resolution in seconds

104

105

Returns:

106

None

107

"""

108

```

109

110

### Thread Pool Debugging

111

112

Debug information for thread pool operations.

113

114

```python { .api }

115

def tpool_exceptions(enabled):

116

"""

117

Toggle printing of exceptions that occur in tpool operations.

118

119

Parameters:

120

- enabled: bool, whether to print tpool exceptions

121

122

Returns:

123

None

124

"""

125

```

126

127

### System Information

128

129

Functions for gathering system and runtime information.

130

131

```python { .api }

132

def format_asyncio_info():

133

"""

134

Format information about asyncio event loop and tasks.

135

136

Returns:

137

str: formatted asyncio debugging information

138

"""

139

140

def format_threads_info():

141

"""

142

Format information about active threads.

143

144

Returns:

145

str: formatted thread debugging information

146

"""

147

```

148

149

### Interactive Debugging

150

151

Backdoor server for interactive debugging of running applications.

152

153

```python { .api }

154

def backdoor_server(sock, locals=None):

155

"""

156

Run a backdoor server on the given socket for interactive debugging.

157

158

Parameters:

159

- sock: listening socket for backdoor connections

160

- locals: dict, local variables available in backdoor session

161

162

Returns:

163

None

164

"""

165

166

def backdoor(port, host='127.0.0.1', locals=None):

167

"""

168

Set up an interactive console backdoor on the specified port.

169

170

Parameters:

171

- port: int, port number for backdoor server

172

- host: str, host address to bind to

173

- locals: dict, local variables available in backdoor session

174

175

Returns:

176

None

177

"""

178

```

179

180

## Usage Examples

181

182

### Basic Debugging Setup

183

184

```python

185

import eventlet

186

import eventlet.debug

187

import time

188

189

def problematic_function():

190

"""Function that might have issues"""

191

print("Starting problematic function")

192

193

# Simulate some work

194

eventlet.sleep(1.0)

195

196

# Simulate a potential issue

197

for i in range(1000000):

198

if i % 100000 == 0:

199

eventlet.sleep(0) # Yield control

200

201

print("Problematic function completed")

202

203

def debug_basic_example():

204

"""Basic debugging example"""

205

206

print("=== Basic Debugging Example ===")

207

208

# Enable various debugging features

209

print("Enabling hub exception printing...")

210

eventlet.debug.hub_exceptions(True)

211

212

print("Enabling tpool exception printing...")

213

eventlet.debug.tpool_exceptions(True)

214

215

print("Enabling hub blocking detection...")

216

eventlet.debug.hub_blocking_detection(True, resolution=0.1)

217

218

# Run some potentially problematic code

219

def worker(worker_id):

220

"""Worker that might block"""

221

try:

222

print(f"Worker {worker_id} starting")

223

224

# This might cause blocking detection to trigger

225

time.sleep(0.2) # Intentional blocking call

226

227

# Some eventlet operations

228

eventlet.sleep(0.5)

229

230

print(f"Worker {worker_id} completed")

231

except Exception as e:

232

print(f"Worker {worker_id} error: {e}")

233

234

# Start workers

235

greenthreads = []

236

for i in range(3):

237

gt = eventlet.spawn(worker, i+1)

238

greenthreads.append(gt)

239

240

# Wait for completion

241

for gt in greenthreads:

242

gt.wait()

243

244

print("Basic debugging example completed")

245

246

if __name__ == "__main__":

247

debug_basic_example()

248

```

249

250

### Hub Inspection and Monitoring

251

252

```python

253

import eventlet

254

import eventlet.debug

255

import time

256

257

def hub_monitoring_example():

258

"""Example of monitoring hub state"""

259

260

print("=== Hub Monitoring Example ===")

261

262

# Enable stack trace recording

263

eventlet.debug.hub_listener_stacks(True)

264

eventlet.debug.hub_timer_stacks(True)

265

266

def network_worker(worker_id, host, port):

267

"""Worker that creates network listeners"""

268

try:

269

print(f"Network worker {worker_id} connecting to {host}:{port}")

270

271

# This creates a listener in the hub

272

sock = eventlet.connect((host, port))

273

274

# Send some data

275

sock.send(b"Hello from worker " + str(worker_id).encode())

276

277

# Receive response

278

response = sock.recv(1024)

279

print(f"Worker {worker_id} received: {response}")

280

281

sock.close()

282

283

except Exception as e:

284

print(f"Network worker {worker_id} error: {e}")

285

286

def timer_worker(worker_id, delays):

287

"""Worker that creates timers"""

288

print(f"Timer worker {worker_id} starting")

289

290

for delay in delays:

291

print(f"Timer worker {worker_id} sleeping for {delay}s")

292

eventlet.sleep(delay)

293

294

print(f"Timer worker {worker_id} completed")

295

296

def monitor_hub():

297

"""Monitor hub state periodically"""

298

for i in range(10):

299

eventlet.sleep(0.5)

300

301

print(f"\n--- Hub Status (iteration {i+1}) ---")

302

303

# Show hub listeners

304

listeners_info = eventlet.debug.format_hub_listeners()

305

if listeners_info.strip():

306

print("Active Listeners:")

307

print(listeners_info)

308

else:

309

print("No active listeners")

310

311

# Show hub timers

312

timers_info = eventlet.debug.format_hub_timers()

313

if timers_info.strip():

314

print("Active Timers:")

315

print(timers_info)

316

else:

317

print("No active timers")

318

319

# Start monitoring

320

eventlet.spawn(monitor_hub)

321

322

# Start some network workers (these will likely fail but create listeners)

323

for i in range(2):

324

eventlet.spawn(network_worker, i+1, 'httpbin.org', 80)

325

326

# Start timer workers

327

timer_delays = [[1.0, 0.5], [0.3, 1.2, 0.8]]

328

for i, delays in enumerate(timer_delays):

329

eventlet.spawn(timer_worker, i+1, delays)

330

331

# Let everything run

332

eventlet.sleep(6)

333

334

print("\nHub monitoring completed")

335

336

if __name__ == "__main__":

337

hub_monitoring_example()

338

```

339

340

### Performance Analysis with Tracing

341

342

```python

343

import eventlet

344

import eventlet.debug

345

import time

346

347

def performance_analysis_example():

348

"""Example of performance analysis with tracing"""

349

350

print("=== Performance Analysis Example ===")

351

352

def slow_function(duration):

353

"""Function that takes some time"""

354

print(f"Starting slow function ({duration}s)")

355

start = time.time()

356

357

# Mix of blocking and non-blocking operations

358

eventlet.sleep(duration / 2) # Non-blocking

359

360

# Simulate CPU work (this might show up in traces)

361

for i in range(int(duration * 100000)):

362

if i % 10000 == 0:

363

eventlet.sleep(0) # Yield occasionally

364

365

elapsed = time.time() - start

366

print(f"Slow function completed in {elapsed:.2f}s")

367

return elapsed

368

369

def traced_worker(worker_id):

370

"""Worker that we'll trace"""

371

print(f"Traced worker {worker_id} starting")

372

373

# Do some work that we want to trace

374

result1 = slow_function(0.5)

375

result2 = slow_function(0.3)

376

377

total = result1 + result2

378

print(f"Traced worker {worker_id} total time: {total:.2f}s")

379

380

return total

381

382

def untraced_worker(worker_id):

383

"""Worker that runs without tracing"""

384

print(f"Untraced worker {worker_id} starting")

385

386

result1 = slow_function(0.4)

387

result2 = slow_function(0.2)

388

389

total = result1 + result2

390

print(f"Untraced worker {worker_id} total time: {total:.2f}s")

391

392

return total

393

394

# Run without tracing first

395

print("Running workers without tracing...")

396

start_time = time.time()

397

398

untraced_gts = []

399

for i in range(2):

400

gt = eventlet.spawn(untraced_worker, i+1)

401

untraced_gts.append(gt)

402

403

for gt in untraced_gts:

404

gt.wait()

405

406

untraced_time = time.time() - start_time

407

print(f"Untraced execution took {untraced_time:.2f}s")

408

409

print("\n" + "="*50)

410

print("Now running with tracing enabled...")

411

print("WARNING: This will produce very verbose output!")

412

413

# Enable tracing for detailed analysis

414

eventlet.debug.spew()

415

416

start_time = time.time()

417

418

traced_gts = []

419

for i in range(1): # Fewer workers due to verbose output

420

gt = eventlet.spawn(traced_worker, i+1)

421

traced_gts.append(gt)

422

423

for gt in traced_gts:

424

gt.wait()

425

426

# Disable tracing

427

eventlet.debug.unspew()

428

429

traced_time = time.time() - start_time

430

print(f"Traced execution took {traced_time:.2f}s")

431

432

print("Performance analysis completed")

433

434

if __name__ == "__main__":

435

performance_analysis_example()

436

```

437

438

### Interactive Debugging Backdoor

439

440

```python

441

import eventlet

442

import eventlet.debug

443

import threading

444

import time

445

446

# Global application state for debugging

447

app_state = {

448

'active_connections': 0,

449

'total_requests': 0,

450

'errors': [],

451

'start_time': time.time()

452

}

453

454

def web_server_simulation():

455

"""Simulate a web server for debugging"""

456

457

def handle_request(request_id):

458

"""Simulate handling a web request"""

459

app_state['active_connections'] += 1

460

app_state['total_requests'] += 1

461

462

try:

463

# Simulate request processing

464

processing_time = eventlet.random.uniform(0.1, 2.0)

465

eventlet.sleep(processing_time)

466

467

# Occasionally simulate an error

468

if eventlet.random.random() < 0.1:

469

raise ValueError(f"Simulated error in request {request_id}")

470

471

print(f"Request {request_id} completed in {processing_time:.2f}s")

472

473

except Exception as e:

474

error_info = {

475

'request_id': request_id,

476

'error': str(e),

477

'timestamp': time.time()

478

}

479

app_state['errors'].append(error_info)

480

print(f"Request {request_id} failed: {e}")

481

482

finally:

483

app_state['active_connections'] -= 1

484

485

# Simulate incoming requests

486

request_id = 0

487

while True:

488

request_id += 1

489

eventlet.spawn(handle_request, request_id)

490

491

# Random delay between requests

492

eventlet.sleep(eventlet.random.uniform(0.1, 0.5))

493

494

def backdoor_debugging_example():

495

"""Example using backdoor for interactive debugging"""

496

497

print("=== Interactive Debugging Backdoor Example ===")

498

print("Starting web server simulation...")

499

500

# Start the simulated web server

501

eventlet.spawn(web_server_simulation)

502

503

# Set up debugging backdoor

504

backdoor_port = 9999

505

backdoor_locals = {

506

'app_state': app_state,

507

'eventlet': eventlet,

508

'debug': eventlet.debug,

509

'time': time

510

}

511

512

print(f"Starting debugging backdoor on port {backdoor_port}")

513

print("Connect with: telnet localhost 9999")

514

print("\nUseful debugging commands to try in the backdoor:")

515

print(" app_state # View application state")

516

print(" app_state['total_requests'] # Get request count")

517

print(" len(app_state['errors']) # Get error count")

518

print(" debug.format_hub_timers() # View hub timers")

519

print(" debug.format_hub_listeners() # View hub listeners")

520

print(" [error['error'] for error in app_state['errors'][-5:]] # Recent errors")

521

print("\nPress Ctrl+C to stop the server")

522

523

try:

524

# Start backdoor server

525

eventlet.debug.backdoor(backdoor_port, locals=backdoor_locals)

526

527

except KeyboardInterrupt:

528

print("\nShutting down server...")

529

530

# Print final statistics

531

uptime = time.time() - app_state['start_time']

532

print(f"\nFinal Statistics:")

533

print(f" Uptime: {uptime:.1f} seconds")

534

print(f" Total requests: {app_state['total_requests']}")

535

print(f" Active connections: {app_state['active_connections']}")

536

print(f" Total errors: {len(app_state['errors'])}")

537

538

if __name__ == "__main__":

539

# Note: This example requires manual interaction via telnet

540

# Run: python script.py

541

# Then in another terminal: telnet localhost 9999

542

backdoor_debugging_example()

543

```

544

545

### System Information and Diagnostics

546

547

```python

548

import eventlet

549

import eventlet.debug

550

import threading

551

import asyncio

552

import time

553

554

def system_diagnostics_example():

555

"""Example of gathering system diagnostic information"""

556

557

print("=== System Diagnostics Example ===")

558

559

def background_worker(worker_type, worker_id):

560

"""Background worker for diagnostics"""

561

if worker_type == 'greenthread':

562

for i in range(5):

563

print(f"Greenthread worker {worker_id} iteration {i+1}")

564

eventlet.sleep(1.0)

565

566

elif worker_type == 'thread':

567

for i in range(3):

568

print(f"Thread worker {worker_id} iteration {i+1}")

569

time.sleep(1.0) # Blocking sleep

570

571

def async_worker():

572

"""Asyncio worker (if available)"""

573

try:

574

import asyncio

575

576

async def async_task():

577

for i in range(3):

578

print(f"Async worker iteration {i+1}")

579

await asyncio.sleep(0.5)

580

581

loop = asyncio.new_event_loop()

582

asyncio.set_event_loop(loop)

583

loop.run_until_complete(async_task())

584

loop.close()

585

586

except Exception as e:

587

print(f"Async worker error: {e}")

588

589

def collect_diagnostics():

590

"""Collect comprehensive diagnostic information"""

591

print("\n--- Collecting System Diagnostics ---")

592

593

# Eventlet hub information

594

print("\n1. Eventlet Hub Status:")

595

listeners = eventlet.debug.format_hub_listeners()

596

timers = eventlet.debug.format_hub_timers()

597

598

if listeners.strip():

599

print("Hub Listeners:")

600

print(listeners)

601

else:

602

print("No active hub listeners")

603

604

if timers.strip():

605

print("Hub Timers:")

606

print(timers)

607

else:

608

print("No active hub timers")

609

610

# Thread information

611

print("\n2. Thread Information:")

612

thread_info = eventlet.debug.format_threads_info()

613

if thread_info.strip():

614

print(thread_info)

615

else:

616

print("No additional thread information available")

617

618

# Asyncio information (if applicable)

619

print("\n3. Asyncio Information:")

620

try:

621

asyncio_info = eventlet.debug.format_asyncio_info()

622

if asyncio_info.strip():

623

print(asyncio_info)

624

else:

625

print("No asyncio information available")

626

except Exception as e:

627

print(f"Error getting asyncio info: {e}")

628

629

# Python threading information

630

print("\n4. Python Threading:")

631

active_threads = threading.active_count()

632

thread_names = [t.name for t in threading.enumerate()]

633

print(f"Active threads: {active_threads}")

634

print(f"Thread names: {thread_names}")

635

636

# Greenlet information

637

print("\n5. Greenlet Information:")

638

try:

639

import greenlet

640

current = greenlet.getcurrent()

641

print(f"Current greenlet: {current}")

642

print(f"Greenlet parent: {current.parent}")

643

except Exception as e:

644

print(f"Error getting greenlet info: {e}")

645

646

# Start various types of workers

647

print("Starting background workers for diagnostics...")

648

649

# Greenthread workers

650

for i in range(2):

651

eventlet.spawn(background_worker, 'greenthread', i+1)

652

653

# Regular thread workers

654

for i in range(1):

655

thread = threading.Thread(target=background_worker, args=('thread', i+1))

656

thread.start()

657

658

# Asyncio worker in separate thread

659

async_thread = threading.Thread(target=async_worker)

660

async_thread.start()

661

662

# Collect diagnostics periodically

663

for i in range(3):

664

eventlet.sleep(2.0)

665

collect_diagnostics()

666

print("\n" + "="*60)

667

668

print("System diagnostics completed")

669

670

def memory_leak_detection():

671

"""Example of detecting potential memory leaks"""

672

673

print("=== Memory Leak Detection Example ===")

674

675

import gc

676

import sys

677

678

def leaky_function():

679

"""Function that might create memory leaks"""

680

# Create some objects that might not be cleaned up

681

data = list(range(10000))

682

683

def closure():

684

return sum(data) # Closure captures data

685

686

# Store closure somewhere it might persist

687

leaky_function.closures = getattr(leaky_function, 'closures', [])

688

leaky_function.closures.append(closure)

689

690

return closure()

691

692

def monitor_memory():

693

"""Monitor memory usage and object counts"""

694

print("Monitoring memory usage...")

695

696

initial_objects = len(gc.get_objects())

697

print(f"Initial object count: {initial_objects}")

698

699

for iteration in range(5):

700

# Run potentially leaky code

701

for i in range(100):

702

result = leaky_function()

703

eventlet.sleep(0.01)

704

705

# Force garbage collection

706

collected = gc.collect()

707

708

# Check object counts

709

current_objects = len(gc.get_objects())

710

object_growth = current_objects - initial_objects

711

712

print(f"Iteration {iteration+1}:")

713

print(f" Objects: {current_objects} (+{object_growth})")

714

print(f" Collected: {collected}")

715

716

if hasattr(leaky_function, 'closures'):

717

print(f" Closures: {len(leaky_function.closures)}")

718

719

eventlet.sleep(1.0)

720

721

# Show object types that have grown

722

print("\nObject type analysis:")

723

type_counts = {}

724

for obj in gc.get_objects():

725

obj_type = type(obj).__name__

726

type_counts[obj_type] = type_counts.get(obj_type, 0) + 1

727

728

# Show top object types

729

top_types = sorted(type_counts.items(), key=lambda x: x[1], reverse=True)[:10]

730

for obj_type, count in top_types:

731

print(f" {obj_type}: {count}")

732

733

monitor_memory()

734

735

if __name__ == "__main__":

736

print("Choose example to run:")

737

print("1. System Diagnostics")

738

print("2. Memory Leak Detection")

739

740

choice = input("Enter choice (1 or 2): ").strip()

741

742

if choice == "1":

743

system_diagnostics_example()

744

elif choice == "2":

745

memory_leak_detection()

746

else:

747

print("Running system diagnostics by default...")

748

system_diagnostics_example()

749

```

750

751

### Custom Debug Utilities

752

753

```python

754

import eventlet

755

import eventlet.debug

756

import time

757

import functools

758

759

class EventletProfiler:

760

"""Custom profiler for eventlet applications"""

761

762

def __init__(self):

763

self.call_counts = {}

764

self.call_times = {}

765

self.start_times = {}

766

767

def profile_function(self, func):

768

"""Decorator to profile function calls"""

769

@functools.wraps(func)

770

def wrapper(*args, **kwargs):

771

func_name = f"{func.__module__}.{func.__name__}"

772

773

# Update call count

774

self.call_counts[func_name] = self.call_counts.get(func_name, 0) + 1

775

776

# Record start time

777

start_time = time.time()

778

779

try:

780

result = func(*args, **kwargs)

781

return result

782

finally:

783

# Record total time

784

elapsed = time.time() - start_time

785

if func_name not in self.call_times:

786

self.call_times[func_name] = 0

787

self.call_times[func_name] += elapsed

788

789

return wrapper

790

791

def get_stats(self):

792

"""Get profiling statistics"""

793

stats = []

794

for func_name in self.call_counts:

795

stats.append({

796

'function': func_name,

797

'calls': self.call_counts[func_name],

798

'total_time': self.call_times.get(func_name, 0),

799

'avg_time': self.call_times.get(func_name, 0) / self.call_counts[func_name]

800

})

801

802

# Sort by total time

803

stats.sort(key=lambda x: x['total_time'], reverse=True)

804

return stats

805

806

def print_stats(self):

807

"""Print profiling statistics"""

808

stats = self.get_stats()

809

810

print("\n=== Profiling Statistics ===")

811

print(f"{'Function':<40} {'Calls':<8} {'Total':<10} {'Avg':<10}")

812

print("-" * 70)

813

814

for stat in stats[:10]: # Top 10

815

print(f"{stat['function']:<40} {stat['calls']:<8} "

816

f"{stat['total_time']:<10.3f} {stat['avg_time']:<10.3f}")

817

818

def custom_debug_example():

819

"""Example of custom debugging utilities"""

820

821

print("=== Custom Debug Utilities Example ===")

822

823

profiler = EventletProfiler()

824

825

@profiler.profile_function

826

def fast_operation():

827

"""Fast operation"""

828

eventlet.sleep(0.1)

829

return "fast result"

830

831

@profiler.profile_function

832

def slow_operation():

833

"""Slow operation"""

834

eventlet.sleep(0.5)

835

return "slow result"

836

837

@profiler.profile_function

838

def cpu_operation():

839

"""CPU-intensive operation"""

840

result = 0

841

for i in range(100000):

842

result += i

843

if i % 10000 == 0:

844

eventlet.sleep(0) # Yield

845

return result

846

847

def worker(worker_id, operations):

848

"""Worker that performs various operations"""

849

print(f"Worker {worker_id} starting")

850

851

for op_type in operations:

852

if op_type == 'fast':

853

result = fast_operation()

854

elif op_type == 'slow':

855

result = slow_operation()

856

elif op_type == 'cpu':

857

result = cpu_operation()

858

859

print(f"Worker {worker_id} completed {op_type} operation")

860

861

print(f"Worker {worker_id} finished")

862

863

# Define work for each worker

864

worker_operations = [

865

['fast', 'slow', 'cpu'],

866

['fast', 'fast', 'slow'],

867

['cpu', 'fast', 'cpu'],

868

['slow', 'cpu', 'fast']

869

]

870

871

print("Starting profiled workers...")

872

873

# Start workers

874

greenthreads = []

875

for i, operations in enumerate(worker_operations):

876

gt = eventlet.spawn(worker, i+1, operations)

877

greenthreads.append(gt)

878

879

# Wait for completion

880

for gt in greenthreads:

881

gt.wait()

882

883

# Print profiling results

884

profiler.print_stats()

885

886

if __name__ == "__main__":

887

custom_debug_example()

888

```

889

890

## Debugging Best Practices

891

892

### Enable Debugging Early

893

894

```python

895

import eventlet.debug

896

897

# Enable debugging at application startup

898

def setup_debugging():

899

"""Configure debugging for production use"""

900

901

# Enable exception printing (low overhead)

902

eventlet.debug.hub_exceptions(True)

903

eventlet.debug.tpool_exceptions(True)

904

905

# Enable blocking detection in development

906

if os.environ.get('DEBUG', '').lower() == 'true':

907

eventlet.debug.hub_blocking_detection(True, resolution=0.1)

908

eventlet.debug.hub_listener_stacks(True)

909

eventlet.debug.hub_timer_stacks(True)

910

911

# Call early in application initialization

912

setup_debugging()

913

```

914

915

### Conditional Tracing

916

917

```python

918

import eventlet.debug

919

import os

920

921

def debug_worker(worker_func, *args, **kwargs):

922

"""Run worker with conditional tracing"""

923

924

enable_tracing = os.environ.get('EVENTLET_TRACE', '').lower() == 'true'

925

926

if enable_tracing:

927

print("Enabling tracing for worker")

928

eventlet.debug.spew()

929

930

try:

931

return worker_func(*args, **kwargs)

932

finally:

933

if enable_tracing:

934

eventlet.debug.unspew()

935

```

936

937

### Safe Backdoor Setup

938

939

```python

940

import eventlet.debug

941

import os

942

943

def setup_backdoor():

944

"""Setup backdoor only in development"""

945

946

if os.environ.get('EVENTLET_BACKDOOR') == 'true':

947

backdoor_port = int(os.environ.get('EVENTLET_BACKDOOR_PORT', '9999'))

948

949

# Only bind to localhost for security

950

eventlet.spawn(eventlet.debug.backdoor, backdoor_port, host='127.0.0.1')

951

print(f"Debug backdoor available on localhost:{backdoor_port}")

952

```