Advanced
Tracing & Telemetry

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 specific

Basic 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 traced

Production 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:

  1. Generates trace IDs: Each request gets a unique trace ID
  2. Propagates context: W3C Trace Context headers are added to requests
  3. Links spans: Related requests are linked in the trace

Headers added automatically:

traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
tracestate: vendor=value

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

AttributeDescription
http.methodGET, POST, etc.
http.urlFull request URL
http.status_codeResponse status
http.request_content_lengthRequest body size
http.response_content_lengthResponse body size
http.hostTarget host
http.schemehttp or https

Next Steps