Logging & Debugging
Configure logging to debug SDK operations and monitor API calls. The SDK uses dealcloud_sdk loggers and intapp-rest-client on HTTPX; for transport-level detail see Logging and Tracing.
Basic Logging Setup
import logging
# Enable SDK logging
logging.basicConfig(level=logging.INFO)
# Or for more detail
logging.basicConfig(level=logging.DEBUG)Log Levels
| Level | Content |
|---|---|
DEBUG | All HTTP requests/responses, pagination details |
INFO | Operation summaries, record counts |
WARNING | Retries, rate limits, deprecation notices |
ERROR | Failed operations, API errors |
SDK Logger Configuration
import logging
# Get SDK-specific logger
sdk_logger = logging.getLogger("dealcloud_sdk")
sdk_logger.setLevel(logging.DEBUG)
# Add custom handler
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter(
"%(asctime)s [%(name)s] %(levelname)s: %(message)s"
))
sdk_logger.addHandler(handler)Log to File
import logging
# Configure file logging
logging.basicConfig(
filename="dealcloud.log",
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s"
)
# Separate file for errors
error_handler = logging.FileHandler("dealcloud_errors.log")
error_handler.setLevel(logging.ERROR)
logging.getLogger("dealcloud_sdk").addHandler(error_handler)HTTP request logging
Enable verbose HTTPX logs (the stack beneath RestClient):
import logging
logging.getLogger("httpx").setLevel(logging.DEBUG)
logging.getLogger("httpcore").setLevel(logging.DEBUG) # optional: connection detailsCustom transports are not required for normal debugging; prefer log levels and intapp REST Client logging for request/response policies.
Debugging Common Issues
Authentication Failures
import logging
logging.basicConfig(level=logging.DEBUG)
from dealcloud_sdk import DealCloud, DealCloudConfig
try:
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)
dc.get_objects() # Test call
except Exception as e:
print(f"Auth failed: {e}")
# Check logs for token request detailsSlow Operations
import logging
import time
class TimingLogger:
"""Log operation timing."""
def __init__(self, name):
self.name = name
self.start = None
def __enter__(self):
self.start = time.time()
logging.info(f"Starting: {self.name}")
return self
def __exit__(self, *args):
elapsed = time.time() - self.start
logging.info(f"Completed: {self.name} ({elapsed:.2f}s)")
# Usage
with TimingLogger("read_all_companies"):
data = dc.read_data("Company", output="pandas")API errors
Non-success HTTP responses are typically raised as intapp_rest_client.exceptions.HttpError (not always httpx.HTTPStatusError, because the client normalizes errors):
import logging
from intapp_rest_client.exceptions import HttpError
try:
data = dc.read_data("InvalidObject", output="list")
except HttpError as e:
logging.error("API error: %s", e.status_code)
logging.error("Body: %s", e.response_body)Structured Logging
For production environments:
import logging
import json
class JsonFormatter(logging.Formatter):
def format(self, record):
log_data = {
"timestamp": self.formatTime(record),
"level": record.levelname,
"logger": record.name,
"message": record.getMessage(),
}
if record.exc_info:
log_data["exception"] = self.formatException(record.exc_info)
return json.dumps(log_data)
# Apply formatter
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
logging.getLogger("dealcloud_sdk").addHandler(handler)Logging Decorator
import logging
import functools
import time
def log_operation(func):
"""Decorator to log function calls."""
@functools.wraps(func)
def wrapper(*args, **kwargs):
logger = logging.getLogger("dealcloud_sdk")
logger.info(f"Calling: {func.__name__}")
start = time.time()
try:
result = func(*args, **kwargs)
elapsed = time.time() - start
logger.info(f"Success: {func.__name__} ({elapsed:.2f}s)")
return result
except Exception as e:
elapsed = time.time() - start
logger.error(f"Failed: {func.__name__} ({elapsed:.2f}s) - {e}")
raise
return wrapper
# Usage
@log_operation
def sync_companies(dc):
return dc.read_data("Company", output="list")Suppressing Logs
For quiet operation:
import logging
# Suppress SDK logs
logging.getLogger("dealcloud_sdk").setLevel(logging.CRITICAL)
# Or suppress httpx logs
logging.getLogger("httpx").setLevel(logging.WARNING)Debug Mode Helper
import logging
import sys
def enable_debug_mode():
"""Enable comprehensive debug logging."""
# Root logger
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(name)s] %(levelname)s: %(message)s",
stream=sys.stdout
)
# SDK logger
logging.getLogger("dealcloud_sdk").setLevel(logging.DEBUG)
# HTTP client logger
logging.getLogger("httpx").setLevel(logging.DEBUG)
print("Debug mode enabled")
# In your script
if "--debug" in sys.argv:
enable_debug_mode()
from dealcloud_sdk import DealCloud, DealCloudConfig
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)Integration with Monitoring
Send to Datadog
from datadog import DogStatsd
statsd = DogStatsd()
class DatadogHandler(logging.Handler):
def emit(self, record):
if record.levelno >= logging.ERROR:
statsd.increment("dealcloud.errors", tags=[f"level:{record.levelname}"])
logging.getLogger("dealcloud_sdk").addHandler(DatadogHandler())Send to CloudWatch
import watchtower
import logging
# AWS CloudWatch handler
handler = watchtower.CloudWatchLogHandler(log_group="dealcloud-sdk")
logging.getLogger("dealcloud_sdk").addHandler(handler)Related
- Error Handling - Handling errors
- Configuration - SDK settings
- Tracing - OpenTelemetry integration