or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

abi-processing.mdaddress-operations.mdcrypto-functions.mdcurrency-units.mddata-conversions.mddata-formatting.mdfunctional-programming.mdhexadecimal-utilities.mdindex.mdlogging-debugging.mdnetwork-information.mdtype-checking.md

logging-debugging.mddocs/

0

# Logging and Debugging

1

2

Enhanced logging capabilities with DEBUG2 level support and environment introspection tools for development and troubleshooting.

3

4

## Capabilities

5

6

### Enhanced Logging

7

8

Get loggers with extended debugging capabilities.

9

10

```python { .api }

11

def get_logger(name: str, logger_class=None) -> Logger:

12

"""

13

Get standard or custom logger instance.

14

15

Args:

16

name (str): Logger name (typically __name__)

17

logger_class: Optional logger class (defaults to standard Logger)

18

19

Returns:

20

Logger: Configured logger instance

21

"""

22

23

def get_extended_debug_logger(name: str) -> ExtendedDebugLogger:

24

"""

25

Get logger with DEBUG2 level support.

26

27

Args:

28

name (str): Logger name

29

30

Returns:

31

ExtendedDebugLogger: Logger with debug2() method

32

"""

33

34

def setup_DEBUG2_logging():

35

"""Configure DEBUG2 logging level in logging system."""

36

```

37

38

### Logger Classes and Mixins

39

40

Enhanced logger classes and mixins for automatic logger setup.

41

42

```python { .api }

43

class ExtendedDebugLogger(logging.Logger):

44

"""Logger class with DEBUG2 level support."""

45

46

def debug2(self, message, *args, **kwargs):

47

"""Log at DEBUG2 level (more verbose than DEBUG)."""

48

49

class HasLogger:

50

"""Mixin class providing logger property."""

51

52

@property

53

def logger(self) -> Logger:

54

"""Get logger for this class."""

55

56

class HasExtendedDebugLogger:

57

"""Mixin class providing extended debug logger property."""

58

59

@property

60

def logger(self) -> ExtendedDebugLogger:

61

"""Get extended debug logger for this class."""

62

63

class HasLoggerMeta(type):

64

"""Metaclass for automatic logger setup."""

65

66

class HasExtendedDebugLoggerMeta(type):

67

"""Metaclass for automatic extended logger setup."""

68

```

69

70

### Environment Debugging

71

72

Environment introspection tools for troubleshooting.

73

74

```python { .api }

75

def get_environment_summary() -> str:

76

"""

77

Get comprehensive environment information.

78

79

Returns:

80

str: Detailed environment summary including Python version,

81

platform info, installed packages, and system details

82

"""

83

84

def python_version() -> str:

85

"""Get Python version information."""

86

87

def platform_info() -> str:

88

"""Get detailed platform information."""

89

90

def pip_freeze() -> str:

91

"""Get pip freeze output for dependency tracking."""

92

```

93

94

### Logging Constants

95

96

```python { .api }

97

DEBUG2_LEVEL_NUM = 8 # Numeric value for DEBUG2 logging level

98

```

99

100

## Usage Examples

101

102

### Basic Logging Setup

103

104

```python

105

from eth_utils import get_logger, get_extended_debug_logger

106

107

# Standard logger

108

logger = get_logger(__name__)

109

logger.info("Application started")

110

logger.debug("Debug information")

111

112

# Extended debug logger

113

debug_logger = get_extended_debug_logger(__name__)

114

debug_logger.info("Application started")

115

debug_logger.debug("Standard debug info")

116

debug_logger.debug2("Very detailed debug info") # More verbose than debug

117

```

118

119

### Logger Mixins

120

121

```python

122

from eth_utils import HasLogger, HasExtendedDebugLogger

123

124

class EthereumClient(HasLogger):

125

"""Ethereum client with automatic logging."""

126

127

def connect(self, url):

128

self.logger.info(f"Connecting to {url}")

129

try:

130

# Connection logic here

131

self.logger.info("Connected successfully")

132

except Exception as e:

133

self.logger.error(f"Connection failed: {e}")

134

135

class DetailedEthereumClient(HasExtendedDebugLogger):

136

"""Ethereum client with detailed debugging."""

137

138

def send_transaction(self, tx):

139

self.logger.info("Sending transaction")

140

self.logger.debug(f"Transaction data: {tx}")

141

self.logger.debug2(f"Raw transaction bytes: {tx.raw_data}")

142

143

# Send logic here

144

self.logger.debug2("Transaction sent, waiting for receipt")

145

146

# Usage

147

client = EthereumClient()

148

client.connect("https://mainnet.infura.io/v3/...")

149

150

detailed_client = DetailedEthereumClient()

151

detailed_client.send_transaction(some_transaction)

152

```

153

154

### DEBUG2 Level Configuration

155

156

```python

157

from eth_utils import setup_DEBUG2_logging, get_extended_debug_logger

158

import logging

159

160

# Setup DEBUG2 level

161

setup_DEBUG2_logging()

162

163

# Configure logging level

164

logging.basicConfig(level=8) # DEBUG2_LEVEL_NUM

165

166

# Use extended logger

167

logger = get_extended_debug_logger(__name__)

168

169

logger.info("Info level message") # Always shown

170

logger.debug("Debug level message") # Shown if level <= DEBUG

171

logger.debug2("Debug2 level message") # Shown if level <= DEBUG2 (8)

172

```

173

174

### Environment Debugging

175

176

```python

177

from eth_utils import get_environment_summary, python_version, platform_info, pip_freeze

178

179

def diagnose_environment():

180

"""Generate comprehensive environment diagnostic."""

181

print("=== Environment Diagnostic ===")

182

183

# Complete environment summary

184

print("Full Environment Summary:")

185

print(get_environment_summary())

186

print()

187

188

# Specific components

189

print(f"Python Version: {python_version()}")

190

print(f"Platform: {platform_info()}")

191

192

print("\nInstalled Packages:")

193

print(pip_freeze())

194

195

# Run diagnostic

196

diagnose_environment()

197

```

198

199

### Development Logging Patterns

200

201

```python

202

from eth_utils import get_extended_debug_logger

203

import json

204

205

class TransactionProcessor(HasExtendedDebugLogger):

206

"""Transaction processor with comprehensive logging."""

207

208

def process_transaction(self, tx_hash):

209

self.logger.info(f"Processing transaction {tx_hash}")

210

211

try:

212

# Fetch transaction

213

self.logger.debug(f"Fetching transaction data for {tx_hash}")

214

tx_data = self.fetch_transaction(tx_hash)

215

self.logger.debug2(f"Raw transaction data: {json.dumps(tx_data, indent=2)}")

216

217

# Validate transaction

218

self.logger.debug("Validating transaction")

219

if not self.validate_transaction(tx_data):

220

self.logger.warning(f"Transaction validation failed: {tx_hash}")

221

return False

222

223

# Process transaction

224

self.logger.debug("Processing validated transaction")

225

result = self.execute_transaction(tx_data)

226

self.logger.debug2(f"Transaction execution result: {result}")

227

228

self.logger.info(f"Successfully processed transaction {tx_hash}")

229

return True

230

231

except Exception as e:

232

self.logger.error(f"Error processing transaction {tx_hash}: {e}", exc_info=True)

233

return False

234

235

def fetch_transaction(self, tx_hash):

236

"""Fetch transaction with detailed logging."""

237

self.logger.debug2(f"Making RPC call for transaction {tx_hash}")

238

# RPC call logic here

239

return {"hash": tx_hash, "value": "0x1"}

240

241

def validate_transaction(self, tx_data):

242

"""Validate transaction with debug logging."""

243

self.logger.debug2(f"Validating fields: {list(tx_data.keys())}")

244

# Validation logic here

245

return True

246

247

def execute_transaction(self, tx_data):

248

"""Execute transaction with detailed tracing."""

249

self.logger.debug2("Starting transaction execution")

250

# Execution logic here

251

return {"status": "success"}

252

253

# Usage

254

processor = TransactionProcessor()

255

processor.process_transaction("0x123...")

256

```

257

258

### Custom Logger Configuration

259

260

```python

261

from eth_utils import get_logger, get_extended_debug_logger, setup_DEBUG2_logging

262

import logging

263

264

def setup_application_logging(log_level="INFO", enable_debug2=False):

265

"""Setup application-wide logging configuration."""

266

267

# Configure basic logging

268

logging.basicConfig(

269

level=getattr(logging, log_level.upper()),

270

format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',

271

handlers=[

272

logging.StreamHandler(),

273

logging.FileHandler('application.log')

274

]

275

)

276

277

# Enable DEBUG2 if requested

278

if enable_debug2:

279

setup_DEBUG2_logging()

280

if log_level.upper() == "DEBUG2":

281

logging.getLogger().setLevel(8) # DEBUG2_LEVEL_NUM

282

283

# Create application loggers

284

app_logger = get_logger("application")

285

286

if enable_debug2:

287

debug_logger = get_extended_debug_logger("application.debug")

288

return app_logger, debug_logger

289

else:

290

return app_logger, None

291

292

# Setup logging

293

app_logger, debug_logger = setup_application_logging(log_level="DEBUG", enable_debug2=True)

294

295

app_logger.info("Application logging configured")

296

if debug_logger:

297

debug_logger.debug2("Extended debugging enabled")

298

```

299

300

### Error Tracking and Reporting

301

302

```python

303

from eth_utils import get_logger, get_environment_summary

304

import traceback

305

306

class ErrorReporter(HasLogger):

307

"""Error reporting with environment context."""

308

309

def report_error(self, error, context=None):

310

"""Report error with full context."""

311

error_id = f"ERR_{hash(str(error)) % 10000:04d}"

312

313

self.logger.error(f"Error {error_id}: {error}")

314

315

if context:

316

self.logger.error(f"Error context: {context}")

317

318

# Log full traceback

319

self.logger.error(f"Traceback:\n{traceback.format_exc()}")

320

321

# Log environment for debugging

322

self.logger.debug(f"Environment at error time:\n{get_environment_summary()}")

323

324

return error_id

325

326

def report_transaction_error(self, tx_hash, error):

327

"""Report transaction-specific error."""

328

context = {

329

"transaction_hash": tx_hash,

330

"error_type": type(error).__name__,

331

"timestamp": "2024-01-01T00:00:00Z" # Would use actual timestamp

332

}

333

334

return self.report_error(error, context)

335

336

# Usage

337

reporter = ErrorReporter()

338

339

try:

340

# Some operation that might fail

341

process_transaction("0x123...")

342

except Exception as e:

343

error_id = reporter.report_transaction_error("0x123...", e)

344

print(f"Error reported with ID: {error_id}")

345

```

346

347

### Performance Logging

348

349

```python

350

from eth_utils import get_extended_debug_logger

351

import time

352

from functools import wraps

353

354

def log_performance(logger_name=None):

355

"""Decorator to log function performance."""

356

def decorator(func):

357

@wraps(func)

358

def wrapper(*args, **kwargs):

359

logger = get_extended_debug_logger(logger_name or func.__module__)

360

361

start_time = time.time()

362

logger.debug2(f"Starting {func.__name__} with args={args}, kwargs={kwargs}")

363

364

try:

365

result = func(*args, **kwargs)

366

execution_time = time.time() - start_time

367

368

logger.debug(f"{func.__name__} completed in {execution_time:.4f}s")

369

logger.debug2(f"{func.__name__} result: {result}")

370

371

return result

372

373

except Exception as e:

374

execution_time = time.time() - start_time

375

logger.error(f"{func.__name__} failed after {execution_time:.4f}s: {e}")

376

raise

377

378

return wrapper

379

return decorator

380

381

# Usage

382

class BlockchainAnalyzer(HasExtendedDebugLogger):

383

384

@log_performance("blockchain.analyzer")

385

def analyze_transaction(self, tx_hash):

386

"""Analyze transaction with performance logging."""

387

self.logger.info(f"Analyzing transaction {tx_hash}")

388

389

# Simulate analysis work

390

time.sleep(0.1)

391

392

return {"status": "analyzed", "gas_used": 21000}

393

394

# Usage

395

analyzer = BlockchainAnalyzer()

396

result = analyzer.analyze_transaction("0x123...")

397

```