Skip to content

Debugging and Introspection

The Pulse SDK includes comprehensive debugging and introspection tools to help you troubleshoot issues, monitor performance, and understand the SDK's behavior. These tools provide detailed insights into HTTP requests, authentication status, cache performance, and more.

Quick Start

Enable debug mode by setting the PULSE_DEBUG environment variable:

export PULSE_DEBUG=true
python your_script.py

Or enable it programmatically:

from pulse.debug import enable_debug

enable_debug()

Debug Configuration

Basic Configuration

from pulse.debug import enable_debug, disable_debug, get_debug_config

# Enable with default settings
enable_debug()

# Check current configuration
config = get_debug_config()
print(f"Debug enabled: {config.enabled}")
print(f"Mask credentials: {config.mask_credentials}")

# Disable debug mode
disable_debug()

Advanced Configuration

enable_debug(
    log_requests=True,          # Log HTTP requests
    log_responses=True,         # Log HTTP responses
    log_timing=True,            # Log request timing
    log_cache_stats=True,       # Log cache hit/miss events
    log_auth_status=True,       # Log authentication events
    mask_credentials=True,      # Mask sensitive data in logs
    max_body_size=10000,        # Max characters for request/response bodies
    log_level="DEBUG",          # Logging level
    categories=["all"]          # Debug categories to enable
)

Features

1. HTTP Request/Response Logging

When enabled, the debug system logs detailed information about all HTTP requests and responses:

from pulse.core.client import CoreClient
from pulse.debug import enable_debug

enable_debug()

client = CoreClient.with_client_credentials()
# This will log the request and response details
response = client.create_embeddings(...)

Example output:

DEBUG [2024-01-15 10:30:15] pulse.debug - → POST https://pulse.researchwiseai.com/v1/embeddings
DEBUG [2024-01-15 10:30:15] pulse.debug -   Headers: {'Authorization': 'Bearer ***MASKED***', 'Content-Type': 'application/json'}
DEBUG [2024-01-15 10:30:15] pulse.debug -   Body: {"inputs": ["Hello world"], "fast": true}
DEBUG [2024-01-15 10:30:16] pulse.debug - ← 200 OK
DEBUG [2024-01-15 10:30:16] pulse.debug -   Body: {"results": [...], "usage": {...}}
DEBUG [2024-01-15 10:30:16] pulse.debug - ⏱️  POST https://pulse.researchwiseai.com/v1/embeddings completed in 0.847s

2. Authentication Token Inspection

Monitor authentication token status and lifecycle:

from pulse.debug import inspect_token

client = CoreClient.with_client_credentials()
token_info = client.debug_auth_status()

print(f"Has token: {token_info.has_token}")
print(f"Token type: {token_info.token_type}")
print(f"Is valid: {token_info.is_valid}")
print(f"Is expired: {token_info.is_expired}")
print(f"Expires in: {token_info.expires_in} seconds")
print(f"Masked token: {token_info.masked_token}")

Token refresh events are automatically logged:

DEBUG [2024-01-15 10:30:20] pulse.debug - 🔄 Authentication token refreshed

3. Performance Timing

Track request performance and identify bottlenecks:

from pulse.debug import get_debug_stats

# After making some requests
stats = get_debug_stats()
print(f"Total requests: {stats.total_requests}")
print(f"Average request time: {stats.average_request_time:.3f}s")
print(f"Success rate: {stats.success_rate:.1f}%")

# View individual request timings
for timing in stats.request_timings[-5:]:  # Last 5 requests
    print(f"{timing.method} {timing.url} - {timing.duration:.3f}s")

4. Cache Hit/Miss Statistics

Monitor cache performance when using the Analyzer:

from pulse.analysis.analyzer import Analyzer
from pulse.debug import enable_debug, get_debug_stats

enable_debug()

with Analyzer(dataset=texts, cache_dir=".pulse_cache") as analyzer:
    results = analyzer.run()  # First run - cache misses
    results = analyzer.run()  # Second run - cache hits

stats = get_debug_stats()
cache_stats = stats.cache_stats
print(f"Cache hit rate: {cache_stats.hit_rate:.1f}%")
print(f"Total cache requests: {cache_stats.total_requests}")
print(f"Cache hits: {cache_stats.hits}")
print(f"Cache misses: {cache_stats.misses}")

Cache events are logged:

DEBUG [2024-01-15 10:30:25] pulse.debug - 💾 Cache MISS: sentiment_process_abc123
DEBUG [2024-01-15 10:30:30] pulse.debug - 💾 Cache HIT: sentiment_process_abc123

5. Credential Masking

Sensitive information is automatically masked in logs:

from pulse.debug import mask_credentials

# Automatically masks sensitive fields
sensitive_data = {
    "client_secret": "my_secret_key",
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "safe_field": "this_is_safe"
}

masked = mask_credentials(sensitive_data)
# Result: {"client_secret": "***MASKED***", "access_token": "***MASKED***", "safe_field": "this_is_safe"}

Masked patterns include: - client_secret, client_id - access_token, refresh_token - code, code_verifier (PKCE) - Bearer tokens in Authorization headers - URL-encoded credentials

6. Granular Logging Categories

Control which types of debug information are logged:

# Enable only specific categories
enable_debug(categories=["requests", "timing"])

# Available categories:
# - "all": Enable all logging (default)
# - "requests": HTTP request logging
# - "responses": HTTP response logging
# - "timing": Request timing information
# - "cache": Cache hit/miss events
# - "auth": Authentication events
# - "errors": Error logging

7. Error Tracking

Failed requests and errors are automatically tracked:

stats = get_debug_stats()
print(f"Failed requests: {stats.failed_requests}")
print(f"Success rate: {stats.success_rate:.1f}%")

Environment Variable Activation

The debug system can be automatically enabled via environment variables:

# Enable debug mode
export PULSE_DEBUG=true

# Alternative values that enable debug mode
export PULSE_DEBUG=1
export PULSE_DEBUG=yes
export PULSE_DEBUG=on

Statistics Management

from pulse.debug import get_debug_stats, clear_debug_stats

# Get current statistics
stats = get_debug_stats()

# Clear all statistics
clear_debug_stats()

Integration with Core Components

The debug system is automatically integrated with:

  • CoreClient: All HTTP requests are monitored
  • Authentication: Token refresh events are logged
  • Analyzer: Cache operations are tracked
  • Retry Logic: Failed requests are counted

Best Practices

Development

# Enable comprehensive debugging during development
enable_debug(
    log_requests=True,
    log_responses=True,
    log_timing=True,
    log_cache_stats=True,
    categories=["all"]
)

Production Monitoring

# Enable minimal debugging for production monitoring
enable_debug(
    log_requests=False,
    log_responses=False,
    log_timing=True,
    log_auth_status=True,
    categories=["timing", "auth", "errors"]
)

Testing

# Enable specific debugging for tests
enable_debug(
    log_requests=True,
    log_responses=False,  # Avoid cluttering test output
    mask_credentials=True,
    categories=["requests", "errors"]
)

Performance Impact

The debug system is designed to have minimal performance impact:

  • Disabled by default: No overhead when not enabled
  • Lazy evaluation: Debug information is only computed when needed
  • Configurable verbosity: Control the amount of logged information
  • Efficient masking: Credential masking uses optimized regex patterns

Troubleshooting Common Issues

Authentication Problems

# Check token status
client = CoreClient.with_client_credentials()
token_info = client.debug_auth_status()

if not token_info.is_valid:
    if not token_info.has_token:
        print("No authentication token available")
    elif token_info.is_expired:
        print("Authentication token has expired")

Performance Issues

# Analyze request timing
stats = get_debug_stats()
slow_requests = [t for t in stats.request_timings if t.duration > 5.0]

for timing in slow_requests:
    print(f"Slow request: {timing.method} {timing.url} - {timing.duration:.3f}s")

Cache Issues

# Check cache performance
stats = get_debug_stats()
if stats.cache_stats.hit_rate < 50:
    print("Low cache hit rate - consider cache configuration")

Example: Complete Debug Session

from pulse.debug import enable_debug, get_debug_stats, clear_debug_stats
from pulse.core.client import CoreClient
from pulse.analysis.analyzer import Analyzer

# Enable comprehensive debugging
enable_debug(
    log_requests=True,
    log_responses=True,
    log_timing=True,
    log_cache_stats=True,
    log_auth_status=True
)

# Clear previous statistics
clear_debug_stats()

try:
    # Create client and check auth status
    client = CoreClient.with_client_credentials()
    token_info = client.debug_auth_status()
    print(f"Authentication: {token_info.is_valid}")

    # Run analysis with caching
    texts = ["Sample text for analysis"]
    with Analyzer(dataset=texts, cache_dir=".pulse_cache") as analyzer:
        results = analyzer.run()

    # Review statistics
    stats = get_debug_stats()
    print(f"Total requests: {stats.total_requests}")
    print(f"Average time: {stats.average_request_time:.3f}s")
    print(f"Cache hit rate: {stats.cache_stats.hit_rate:.1f}%")

finally:
    client.close()

This comprehensive debugging system helps you understand exactly what's happening inside the Pulse SDK, making it easier to optimize performance, troubleshoot issues, and monitor your application's behavior.