Advanced
Logging & Debugging

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

LevelContent
DEBUGAll HTTP requests/responses, pagination details
INFOOperation summaries, record counts
WARNINGRetries, rate limits, deprecation notices
ERRORFailed 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 details

Custom 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 details

Slow 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