Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PingOps SDK for Python

A production-grade Python SDK for HTTP tracing and export to PingOps. Built on OpenTelemetry for maximum compatibility and reliability.

Features

  • Automatic HTTP Instrumentation - Automatically captures outgoing HTTP requests from requests, urllib3, httpx, and aiohttp
  • Manual Tracing - Start traces with custom attributes like userId, sessionId, tags, and metadata
  • Flexible Configuration - Configure via code, YAML/JSON files, or environment variables
  • Domain Filtering - Allow/deny lists to control which requests are traced
  • Header Redaction - Automatically redact sensitive headers (Authorization, API keys, etc.)
  • Body Capture - Optionally capture request/response bodies with size limits
  • Batched Export - Efficient batch export with configurable size and timeout

Installation

pip install pingops-sdk

Quick Start

Basic Usage

from pingops import initialize_pingops, start_trace, StartTraceOptions, PingopsTraceAttributes

# Initialize the SDK
initialize_pingops({
    "baseUrl": "https://api.pingops.com",
    "serviceName": "my-service",
    "apiKey": "your-api-key",
})

# Create a trace with custom attributes
options = StartTraceOptions(
    attributes=PingopsTraceAttributes(
        user_id="user-123",
        session_id="session-456",
        tags=["api-call", "important"],
    )
)

# All HTTP calls within this trace will be captured
result = start_trace(options, lambda: make_api_calls())

Async Support

from pingops import start_trace_async, StartTraceOptions

async def main():
    options = StartTraceOptions(
        attributes=PingopsTraceAttributes(user_id="user-123")
    )

    result = await start_trace_async(options, async_api_call)

Configuration from File

from pingops import initialize_pingops

# Load from YAML or JSON file
initialize_pingops("config/pingops.yaml")

Example pingops.yaml:

apiKey: your-api-key
baseUrl: https://api.pingops.com
serviceName: my-service
debug: false

# Only trace these domains
domainAllowList:
  - domain: api.example.com
    paths: ["/v1/", "/v2/"]
  - domain: ".internal.company.com"
    captureRequestBody: true
    captureResponseBody: true

# Block these domains from tracing
domainDenyList:
  - domain: analytics.example.com

# Header handling
headersAllowList:
  - content-type
  - accept
  - x-request-id

headerRedaction:
  strategy: partial
  visibleChars: 4
  sensitivePatterns:
    - authorization
    - x-api-key

Environment Variables

The SDK reads these environment variables:

Variable Description
PINGOPS_API_KEY API key for authentication
PINGOPS_BASE_URL PingOps backend URL
PINGOPS_SERVICE_NAME Service name for spans
PINGOPS_DEBUG Enable debug logging ("true" to enable)
PINGOPS_BATCH_SIZE Batch size for export (default: 50)
PINGOPS_BATCH_TIMEOUT Batch timeout in ms (default: 5000)
PINGOPS_EXPORT_MODE "batched" or "immediate"
PINGOPS_CONFIG_FILE Path to config file

Environment variables override config file values.

API Reference

initialize_pingops(config)

Initialize the SDK. Idempotent - calling multiple times is safe.

# From config object
initialize_pingops(PingopsProcessorConfig(
    base_url="https://api.pingops.com",
    service_name="my-service",
))

# From file path
initialize_pingops("config/pingops.yaml")

# From dict
initialize_pingops({
    "baseUrl": "https://api.pingops.com",
    "serviceName": "my-service",
})

# From environment variables
initialize_pingops()

shutdown_pingops() / shutdown_pingops_sync()

Gracefully shut down the SDK, flushing pending spans.

# Async
await shutdown_pingops()

# Sync
shutdown_pingops_sync()

start_trace(options, fn)

Start a new trace and run a callback within it.

from pingops import start_trace, StartTraceOptions, PingopsTraceAttributes

options = StartTraceOptions(
    seed="deterministic-seed",  # For deterministic trace IDs
    attributes=PingopsTraceAttributes(
        trace_id="custom-trace-id",  # Override trace ID
        user_id="user-123",
        session_id="session-456",
        tags=["tag1", "tag2"],
        metadata={"key": "value"},
        capture_request_body=True,  # Override body capture
        capture_response_body=True,
    ),
)

result = start_trace(options, lambda: do_work())

start_trace_async(options, fn)

Async version of start_trace.

result = await start_trace_async(options, async_function)

get_active_trace_id() / get_active_span_id()

Get the current trace or span ID.

from pingops import get_active_trace_id, get_active_span_id

def handler():
    trace_id = get_active_trace_id()  # "abc123..."
    span_id = get_active_span_id()    # "def456..."

Configuration Options

PingopsProcessorConfig

Field Type Required Default Description
api_key str No - API key for backend
base_url str Yes - PingOps backend URL
service_name str Yes - Service name for resource
debug bool No False Enable debug logging
headers_allow_list list[str] No - Only include these headers
headers_deny_list list[str] No - Exclude these headers
capture_request_body bool No False Capture request bodies
capture_response_body bool No False Capture response bodies
max_request_body_size int No 4096 Max request body bytes
max_response_body_size int No 4096 Max response body bytes
domain_allow_list list[DomainRule] No - Only trace these domains
domain_deny_list list[DomainRule] No - Never trace these domains
header_redaction HeaderRedactionConfig No - Header redaction settings
batch_size int No 50 Spans per batch
batch_timeout int No 5000 Batch timeout (ms)
export_mode str No "batched" "batched" or "immediate"

DomainRule

DomainRule(
    domain="api.example.com",  # Exact match
    # or domain=".example.com"  # Suffix match
    paths=["/api/", "/v2/"],   # Optional path prefixes
    headers_allow_list=["x-custom"],  # Override headers
    capture_request_body=True,  # Override capture
)

HeaderRedactionConfig

HeaderRedactionConfig(
    sensitive_patterns=["x-custom-secret"],
    strategy=HeaderRedactionStrategy.PARTIAL,  # REPLACE, PARTIAL, PARTIAL_END, REMOVE
    redaction_string="[REDACTED]",
    visible_chars=4,
    enabled=True,
)

OpenTelemetry Compatibility

This SDK is built on OpenTelemetry and is fully compatible with the OpenTelemetry ecosystem. The SDK:

  • Uses OpenTelemetry API for context propagation
  • Creates CLIENT spans with standard HTTP semantic conventions
  • Exports via OTLP HTTP protocol
  • Works alongside other OpenTelemetry instrumentations

License

MIT License - see LICENSE for details.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages