Tracing & Telemetry
The Intapp REST Client supports distributed tracing via OpenTelemetry.
Overview
For distributed tracing, use the official opentelemetry-instrumentation-httpx (opens in a new tab) package. This automatically instruments all httpx requests, including those made by this client.
đź’ˇ
Since the client uses httpx internally, standard httpx instrumentation works automatically. No client-specific setup is required.
Installation
pip install opentelemetry-instrumentation-httpx opentelemetry-sdk
# For production exporters:
pip install opentelemetry-exporter-otlp # OTLP (Jaeger, Tempo, Honeycomb, Datadog, etc.)
pip install opentelemetry-exporter-jaeger # Jaeger specificBasic Setup
# 1. Configure OpenTelemetry (one-time application setup)
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.sdk.resources import Resource
resource = Resource.create({"service.name": "my-application"})
provider = TracerProvider(resource=resource)
# Use ConsoleSpanExporter for debugging
provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
# 2. Enable httpx instrumentation (instruments ALL httpx clients)
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
HTTPXClientInstrumentation().instrument()
# 3. Use the REST client normally - all requests are now traced!
from intapp_rest_client import RestClient
client = RestClient(
base_url="https://api.example.com",
api_key="your-key"
)
data = client.get("/api/users") # This request is automatically tracedProduction Setup with OTLP
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentation
# Configure with OTLP exporter (Jaeger, Tempo, Honeycomb, Datadog, etc.)
resource = Resource.create({
"service.name": "my-application",
"service.version": "1.0.0",
"deployment.environment": "production",
})
provider = TracerProvider(resource=resource)
provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317"))
)
trace.set_tracer_provider(provider)
# Enable instrumentation
HTTPXClientInstrumentation().instrument()
# All REST client requests are now traced with W3C trace context propagation
from intapp_rest_client import RestClient, OAuth2Config
client = RestClient(
base_url="https://api.example.com",
oauth2_config=OAuth2Config(...)
)
# Requests include trace context headers automatically
data = client.get("/api/resources")Async Support
The httpx instrumentation works with both sync and async clients:
import asyncio
from intapp_rest_client import RestClient
async def main():
async with RestClient(base_url="https://api.example.com", api_key="key") as client:
# Async requests are also traced
data = await client.aget("/api/users")
asyncio.run(main())Trace Context Propagation
When instrumented, the client automatically:
- Generates trace IDs: Each request gets a unique trace ID
- Propagates context: W3C Trace Context headers are added to requests
- Links spans: Related requests are linked in the trace
Headers added automatically:
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
tracestate: vendor=valueCustom Spans
Add custom spans around client operations:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def process_companies(client):
with tracer.start_as_current_span("process_companies") as span:
span.set_attribute("batch_size", 1000)
total = 0
for batch in client.get_paginated("/api/companies", 1000, "rows"):
with tracer.start_as_current_span("process_batch") as batch_span:
batch_span.set_attribute("batch_count", len(batch))
process_batch(batch)
total += len(batch)
span.set_attribute("total_processed", total)Integration with Cloud Providers
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.extension.aws.trace import AwsXRayIdGenerator
provider = TracerProvider(
resource=resource,
id_generator=AwsXRayIdGenerator()
)
provider.add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)Request ID Correlation
The client includes a request ID header for correlation:
client = RestClient(
base_url="https://api.example.com",
api_key="key",
enable_request_id=True,
request_id_header="X-Request-ID"
)This ID appears in:
- Request headers sent to the server
- Log entries
- Error messages
For full correlation, add it to your spans:
def make_request_with_span(client, endpoint):
with tracer.start_as_current_span("api_request") as span:
response = client.get_raw(endpoint)
request_id = response.request.headers.get("X-Request-ID")
span.set_attribute("request_id", request_id)
return response.json()Benefits of httpx Instrumentation
- Zero code changes - Works with any httpx-based client automatically
- Officially maintained - Part of the OpenTelemetry Python contrib packages
- Full feature set - Request/response attributes, error recording, context propagation
- Ecosystem compatible - Works with all OpenTelemetry exporters and tools
What Gets Traced
The instrumentation captures:
| Attribute | Description |
|---|---|
http.method | GET, POST, etc. |
http.url | Full request URL |
http.status_code | Response status |
http.request_content_length | Request body size |
http.response_content_length | Response body size |
http.host | Target host |
http.scheme | http or https |
Next Steps
- Logging - Combine with logging
- Error Handling - Trace errors
- Request Hooks - Custom instrumentation