Skip to main content
GitHub

Configuration

Configure the Risicare SDK for your application.

Configure the Risicare SDK to connect to your project and customize tracing behavior.

JavaScript SDK?

For JavaScript/TypeScript configuration, see the JS Configuration guide.

Basic Setup

import risicare
 
risicare.init(
    api_key="rsk-...",              # Or use RISICARE_API_KEY env var
    service_name="my-agent",        # Identify your service
    environment="production",       # Environment name
)

API Key = Project

Your API key is scoped to the project it was created under (visible in Settings → General). No separate project_id is needed — the gateway resolves it from your key.

project_id is deprecated

Passing project_id to init() emits a DeprecationWarning in Python (or console.warn in JavaScript). The parameter is ignored by the gateway and will be removed in v1.0. Use service_name and environment for within-project organization instead.

Configuration Options

Required

OptionTypeDescription
api_keystrYour Risicare API key. Starts with rsk-. Each key is scoped to one project.

Optional

OptionTypeDefaultDescription
endpointstr"https://app.risicare.ai"Gateway endpoint URL
environmentstr"development"Environment name (development, staging, production)
service_namestrNoneService name for within-project organization
service_versionstrNoneService version for traces
enabledboolTrueEnable/disable tracing globally
trace_contentboolTrueCapture prompt/completion content
sample_ratefloat1.0Sampling rate (0.0-1.0, clamped)
batch_sizeint100Spans per batch export. Values outside [1, 10000] are clamped and a WARNING risicare.exporters.batch log line is emitted on each init() call that triggers a clamp.
batch_timeout_msint1000Milliseconds between batch exports
auto_patchboolTruePatch ThreadPoolExecutor, ProcessPoolExecutor, and asyncio.create_task for automatic context propagation
debugboolFalseEcho every span to stdout via a console exporter. Prints prompt/completion content unredacted — see the warning below before enabling.
exporterslist[SpanExporter]NoneCustom span exporters (default: HTTP exporter when api_key is provided)
metadatadict{}Global metadata attached to all spans
otlp_endpointstrNoneOTLP/HTTP export endpoint
otlp_headersdictNoneOTLP export headers
otel_bridgeboolFalseEnable OpenTelemetry bridge

Content truncation

When trace_content=True, captured prompt and completion text is truncated to 10,000 characters per field. Content exceeding this limit is cut with a "... [truncated]" marker. This limit is not configurable — it's a hardcoded safety bound to prevent oversized spans.

auto_patch monkey-patches at import time

When auto_patch=True (default), init() monkey-patches all detected LLM provider libraries (OpenAI, Anthropic, etc.) via import hooks. For precise control over which providers are instrumented, set auto_patch=False and call instrument_already_imported() or install_import_hooks() selectively.

What debug=True enables

  • Console exporter: Adds a ConsoleExporter that prints every span to stdout as it's exported — including span attributes
  • Orphan trace warnings: Logs a warning when an LLM call has no parent span (each call becomes its own trace — a common Tier 1 mistake)
  • Initialization logging: Reports patching status (ThreadPoolExecutor, asyncio.create_task), endpoint, and service name on startup

debug=True prints prompt and completion content unredacted

The console exporter writes span attributes to stdout verbatim, including gen_ai.prompt and gen_ai.completion. Any customer data in a prompt is printed to your terminal and container logs. Attribute values are truncated at ~80 characters, which is not redaction — a value that begins with an SSN or card number is printed in full.

Do not enable it against production traffic. init() also accepts a mask callable for redacting attribute values before export.

debug=True does not show export failures

debug=True does not print the HTTP status of a failed span export — it adds nothing on that path. If spans are not arriving, the SDK already emits a one-line warning naming the endpoint; to get the underlying HTTP status and error, raise the SDK logger:

import logging
logging.getLogger("risicare").setLevel(logging.DEBUG)

Span Delivery

When you pass an api_key, init() installs the HTTP exporter. This is the default path — if you have not configured exporters or an OTLP endpoint, this is what is sending your spans.

The exporter has a circuit breaker

After 5 consecutive export failures the exporter opens a circuit and stops attempting exports for a 60-second cooldown. Spans created during that window are dropped. This bounds the damage a gateway outage does to your application's latency, but it means a brief outage costs you more than the outage itself — delivery does not resume the moment the gateway returns.

Tracing never raises: an export failure is logged, not thrown. The SDK emits a rate-limited warning naming the endpoint when spans stop arriving. To see the underlying HTTP status, raise the SDK logger as shown above.

The OTLPExporter applies the same 5-failure / 60-second policy — see OpenTelemetry.

For the measured behaviour — how the threshold counts, which spans survive, and how long delivery really stays stopped — see Production & Failure Modes.

Environment Variables

All configuration can be set via environment variables:

export RISICARE_API_KEY="rsk-..."
export RISICARE_ENDPOINT="https://app.risicare.ai"
export RISICARE_ENVIRONMENT="production"
export RISICARE_SERVICE_NAME="my-agent"
export RISICARE_TRACING="true"
export RISICARE_TRACE_CONTENT="true"
export RISICARE_SAMPLE_RATE="1.0"
export RISICARE_SERVICE_NAME="my-service"
export RISICARE_SERVICE_VERSION="1.0.0"
export RISICARE_DEBUG="false"
export RISICARE_OTLP_ENDPOINT="https://otel-collector:4318"
export RISICARE_OTLP_HEADERS="key1=value1,key2=value2"
export RISICARE_OTEL_BRIDGE="false"
VariableMaps To
RISICARE_API_KEYapi_key
RISICARE_ENDPOINTendpoint
RISICARE_ENVIRONMENTenvironment
RISICARE_SERVICE_NAMEservice_name
RISICARE_SERVICE_VERSIONservice_version
RISICARE_TRACINGenabled
RISICARE_TRACE_CONTENTtrace_content
RISICARE_SAMPLE_RATEsample_rate
RISICARE_DEBUGdebug
RISICARE_OTLP_ENDPOINTotlp_endpoint
RISICARE_OTLP_HEADERSotlp_headers
RISICARE_OTEL_BRIDGEotel_bridge

Zero-Code Instrumentation

Set RISICARE_TRACING=true to enable auto-instrumentation without any code changes.

Advanced Configuration

Custom Endpoint

Override the default gateway endpoint (https://app.risicare.ai) — for example, to send spans through an outbound proxy your network requires:

risicare.init(
    api_key="rsk-...",
    endpoint="https://llm-egress-proxy.internal.example.com",
)

Risicare is a hosted service

Risicare runs as a managed service. There is no self-hosted or on-premise Risicare instance to point this at — endpoint retargets where the SDK sends spans (a proxy or a non-default gateway host), not where Risicare itself runs.

Sampling

Control trace sampling rate:

risicare.init(
    api_key="rsk-...",
    sample_rate=0.1,  # Sample 10% of traces
)

Programmatic Control

Check Status

if risicare.is_enabled():
    print("Tracing is active")

Flush Pending Spans

# Force export all pending spans
client = risicare.get_client()
client.flush()

Shutdown

# Graceful shutdown - flushes and closes connections
risicare.shutdown(timeout_ms=5000)  # default: 5000ms

shutdown() waits up to timeout_ms for the batch processor thread to drain, then performs a final flush and closes HTTP connections. An atexit handler calls shutdown() automatically on normal exit — explicit calls are only needed when you want to flush mid-process (e.g., serverless functions, before a long non-tracing phase).

Shutdown may block on network issues

If the exporter is mid-request when shutdown() runs, the thread join blocks for up to timeout_ms. In latency-sensitive paths, reduce the timeout: risicare.shutdown(timeout_ms=1000).

Auto-Instrumentation Management

Control which libraries are automatically instrumented:

from risicare import (
    install_import_hooks,
    remove_import_hooks,
    instrument_already_imported,
    is_instrumented,
    get_instrumented_modules,
    get_supported_modules,
)
 
# See which libraries can be auto-instrumented
get_supported_modules()
# {'openai', 'anthropic', 'cohere', 'google.generativeai', 'mistralai', ...}
 
# Check what's currently instrumented — returns a per-module state record
get_instrumented_modules()
# {'openai':    {'state': 'instrumented', 'hooks_landed': 2, ...},
#  'anthropic': {'state': 'instrumented', 'hooks_landed': 2, ...}}
# Gate health checks on state == "instrumented" (the only value that means
# the integration is actually on a live call path).
 
# Check a specific library. NOTE: is_instrumented() is attempt-based — it
# returns True once instrumentation was attempted, even if the wrapper landed
# inert. For a real liveness check use get_instrumented_modules()[name]["state"].
is_instrumented("openai")  # True
 
# Instrument libraries that were imported before risicare.init()
count = instrument_already_imported()
# Returns number of newly instrumented modules
 
# Remove all import hooks (stops future auto-instrumentation)
remove_import_hooks()
 
# Re-install import hooks
install_import_hooks()

Configuration Precedence

Configuration is resolved in this order (highest to lowest priority):

  1. Explicit init() parameters
  2. Environment variables
  3. Default values

Next Steps