Tracing & Telemetry
dealcloud-sdk does not embed OpenTelemetry APIs. It performs HTTP through HTTPX (via intapp-rest-client), so you enable distributed tracing by installing OpenTelemetry and instrumenting HTTPX—then every RestClient request from the SDK can emit spans. That gives you visibility into API calls, latency, and errors.
How it works: opentelemetry-instrumentation-httpx patches HTTPX. Configure a tracer provider and exporters in your process, call HTTPXClientInstrumentation().instrument() before you construct DealCloud, then use the SDK as usual.
dealcloud-sdk[telemetry] only installs dependencies (opentelemetry-sdk and opentelemetry-instrumentation-httpx). It does not enable tracing by itself—you still need the setup code in Basic Setup. For a full install of all optional extras, use dealcloud-sdk[all] (includes telemetry).
Quick Start
Installation
Use the telemetry optional extra to pull the same OpenTelemetry packages the docs use, or install them by name.
pip install "dealcloud-sdk[telemetry]"Production exporters (e.g. OTLP, Jaeger) are not included in the telemetry extra—add opentelemetry-exporter-otlp or the exporter you need separately.
Basic Setup
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
# 1. Set up tracer provider
trace.set_tracer_provider(TracerProvider())
# 2. Add span processor (console output for demo)
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(ConsoleSpanExporter())
)
# 3. Instrument HTTPX (used by DealCloud SDK)
HTTPXClientInstrumentation().instrument()
# 4. Create SDK client normally
from dealcloud_sdk import DealCloud, DealCloudConfig
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)
# All HTTP calls are now traced
data = dc.read_data("Company", output="pandas")Production Configuration
Export to Jaeger
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
# Configure Jaeger exporter
jaeger_exporter = JaegerExporter(
agent_host_name="jaeger.internal",
agent_port=6831,
)
# Set up provider with Jaeger
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(jaeger_exporter))
trace.set_tracer_provider(provider)
# Instrument HTTPX
HTTPXClientInstrumentation().instrument()Export to OTLP (OpenTelemetry Collector)
Install an OTLP exporter package, for example:
pip install opentelemetry-exporter-otlpfrom opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
# Configure OTLP exporter
otlp_exporter = OTLPSpanExporter(
endpoint="http://otel-collector:4317",
insecure=True # Use False with TLS
)
# Set up provider
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
trace.set_tracer_provider(provider)
# Instrument HTTPX
HTTPXClientInstrumentation().instrument()Adding Custom Spans
Create additional spans for application-level tracing:
from opentelemetry import trace
from dealcloud_sdk import DealCloud, DealCloudConfig
tracer = trace.get_tracer("my-app")
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)
def sync_companies():
with tracer.start_as_current_span("sync_companies") as span:
span.set_attribute("operation", "full_sync")
# This will create child spans for HTTP calls
companies = dc.read_data("Company", output="list")
span.set_attribute("company_count", len(companies))
for company in companies:
with tracer.start_as_current_span("process_company") as child:
child.set_attribute("entry_id", company["EntryId"])
process_company(company)Span Attributes
The HTTPX instrumentation automatically captures:
| Attribute | Example | Description |
|---|---|---|
http.method | GET, POST | HTTP method |
http.url | https://site.dealcloud.com/... | Full URL |
http.status_code | 200, 429 | Response status |
http.request_content_length | 1234 | Request body size |
http.response_content_length | 56789 | Response body size |
Application metrics (OpenTelemetry)
The SDK does not emit built-in OpenTelemetry metrics. You can record your own business or sync metrics with the OpenTelemetry Metrics API—for example, counting rows after read_data:
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import ConsoleMetricExporter, PeriodicExportingMetricReader
# Set up metrics pipeline (your application)
reader = PeriodicExportingMetricReader(ConsoleMetricExporter())
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)
meter = metrics.get_meter("dealcloud-sync")
records_synced = meter.create_counter(
"records_synced",
description="Number of records synchronized"
)
# Example: increment after a read
from dealcloud_sdk import DealCloud, DealCloudConfig
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)
companies = dc.read_data("Company", output="list")
records_synced.add(len(companies), {"object": "Company"})Trace Context Propagation
For distributed systems, propagate trace context:
from opentelemetry import trace
from opentelemetry.propagate import inject, extract
# Inject context into outgoing requests (automatic with HTTPX instrumentation)
# Extract context from incoming requests (e.g., in a web framework)
from flask import request
from dealcloud_sdk import DealCloud, DealCloudConfig
@app.route("/sync")
def sync_endpoint():
# Extract trace context from incoming request
ctx = extract(request.headers)
with trace.get_tracer("my-app").start_as_current_span(
"handle_sync",
context=ctx
):
config = DealCloudConfig(
siteUrl="yoursite.dealcloud.com",
clientId=12345,
clientSecret="your-secret",
)
dc = DealCloud.from_config_object(config)
# This span will be linked to the incoming trace
return dc.read_data("Company", output="list")Configuration via Environment
Configure OpenTelemetry via environment variables:
# Service name
export OTEL_SERVICE_NAME=dealcloud-integration
# OTLP endpoint
export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317
# Sampling (1.0 = 100%, 0.1 = 10%)
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.1Disabling Tracing
To disable tracing in specific environments:
import os
if os.getenv("ENVIRONMENT") == "development":
# Skip instrumentation
pass
else:
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
HTTPXClientInstrumentation().instrument()Troubleshooting
No Spans Appearing
- Verify instrumentation is called before creating
DealCloudclient - Check exporter configuration (endpoint, network access)
- Enable debug logging:
import logging
logging.getLogger("opentelemetry").setLevel(logging.DEBUG)Missing HTTP Details
Ensure you're using the HTTPX instrumentation, not requests:
# Correct - instruments the SDK's HTTP client
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
HTTPXClientInstrumentation().instrument()
# Wrong - won't capture SDK calls
from opentelemetry.instrumentation.requests import RequestsInstrumentationRelated Resources
- Installation — optional extras including
telemetryandall - OpenTelemetry Python Documentation (opens in a new tab)
- HTTPX Instrumentation (opens in a new tab)
- Jaeger Tracing (opens in a new tab)