TraceRoot SDK for Python

A Python SDK for TraceRoot tracing and logging.

Introduction

This SDK allows you to trace functions and utilizes TraceRoot’s logger (built upon WatchTower) within the TraceRoot trace. It captures all the context designed for advanced debugging of AI agents.

OpenTelemetry

The trace is built upon OpenTelemetry, and the traces will be sent to TraceRoot’s own endpoint.

Installation

Please install the SDK with the latest version:
python3.11 -m venv venv
source venv/bin/activate
pip install traceroot
# or install the latest version from the source code
pip install -e .

Configuration

Cloud Mode

Cloud mode uses TraceRoot’s cloud service to store logs and traces.

Method 1: Code Configuration

You can configure TraceRoot directly in your Python code at the beginning of your entry file:
import traceroot

traceroot.init(
    token="traceroot-********************************",
    service_name="sdk-example-service",
    github_owner="traceroot-ai",
    github_repo_name="traceroot-sdk",
    github_commit_hash="main"
)

Method 2: YAML Configuration File

Create a .traceroot-config.yaml file in the root of your project:
token: "traceroot-********************************"
service_name: "sdk-example-service"
github_owner: "traceroot-ai"
github_repo_name: "traceroot-sdk"
github_commit_hash: "main"

Method 3: Environment Variables

You can also provide the configuration in the environment variables. The environment variables are the same as the configuration parameters, but with the prefix TRACEROOT_. For example, you can set the TRACEROOT_TOKEN environment variable to the token for the TraceRoot API. You can run following example to see how to use the environment variables:
TRACEROOT_TOKEN=traceroot-* TRACEROOT_SERVICE_NAME=new_name TRACEROOT_ENABLE_LOG_CLOUD_EXPORT=1 python3 examples/override_example.py

Priority of the Configuration

The priority of the configuration is as follows:
  1. Environment variables
  2. traceroot.init(...) parameters
  3. .traceroot-config.yaml file
For example, if you provide the configuration in the environment variables, the configuration in the .traceroot-config.yaml file will be overridden. Configuration Parameters:
  • token - The token for the TraceRoot API (required for cloud mode)
  • service_name - The name of the service or program you are tracking
  • github_owner - The owner of the GitHub repository (optional)
  • github_repo_name - The name of the GitHub repository (optional)
  • github_commit_hash - The commit hash of the GitHub repository (optional)
  • enable_span_cloud_export - Enable/disable cloud export of spans (default: true)
  • enable_log_cloud_export - Enable/disable cloud export of logs (default: true)
  • enable_span_console_export - Enable/disable console export of spans (default: false)
  • enable_log_console_export - Enable/disable console export of logs (default: true)
Notice that during the first import of the traceroot package, the SDK will automatically load the configuration from the .traceroot-config.yaml file if it exists. And then if you call traceroot.init(...) with any parameters, the parameters will override the configuration in the .traceroot-config.yaml file.

Local Mode

Local mode uses TraceRoot’s local database to store logs and traces using Jaeger.

Prerequisites

  1. Download and run the Jaeger Docker container:
docker run cr.jaegertracing.io/jaegertracing/jaeger:2.8.0 --help
  1. Start the Jaeger container:
docker stop jaeger || true && docker rm jaeger || true && docker run -d --name jaeger \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 14250:14250 \
  -p 4317:4317 \
  -p 4318:4318 \
  cr.jaegertracing.io/jaegertracing/jaeger:2.8.0

docker logs -f jaeger

Configuration

Method 1: Code Configuration
import traceroot

traceroot.init(
    service_name="sdk-example-service",
    github_owner="traceroot-ai",
    github_repo_name="traceroot-sdk",
    github_commit_hash="main",
    local_mode=True
)
Method 2: YAML Configuration File Create a .traceroot-config.yaml file:
service_name: "sdk-example-service"
github_owner: "traceroot-ai"
github_repo_name: "traceroot-sdk"
github_commit_hash: "main"
local_mode: true

Cloud and Console Export

You can control export behavior with these settings:
  • enable_span_cloud_export: If set to false, disables cloud export of spans (also disables cloud export of logs)
  • enable_log_cloud_export: If set to false, only disables cloud export of logs
  • enable_span_console_export: Enable to print spans to console
  • enable_log_console_export: Enable to print logs to console

Usage

Tracing Functions

Use the @traceroot.trace() decorator to trace your functions. You should at least trace the entry point of your application. Adding more @traceroot.trace() decorators to child functions creates a better tree structure for analysis.

Function Name

If you specify the name parameter in the decorator, it will be used as the span name shown in the TraceRoot.AI platform.

Logging

Within a traced function, you can use the traceroot logger with methods like logger.info, logger.error, logger.warn, logger.debug, and logger.critical. Logs within traced functions are properly tracked and visible in the TraceRoot.AI platform. Here is an example of how to use the @traceroot.trace() decorator and logger:
import traceroot
import asyncio

# Initialize TraceRoot
traceroot.init(
    token="traceroot-********************************",
    service_name="python-example"
)

logger = traceroot.get_logger()

@traceroot.trace(name="greet")
async def greet(name: str) -> str:
    logger.info(f"Greeting inside traced function: {name}")
    # Simulate some async work
    await asyncio.sleep(0.1)
    return f"Hello, {name}!"

async def main():
    result = await greet("world")
    logger.info(f"Greeting result: {result}")

if __name__ == "__main__":
    asyncio.run(main())

Synchronous Functions

The decorator also works with synchronous functions:
import traceroot

traceroot.init(
    token="traceroot-********************************",
    service_name="python-example"
)

logger = traceroot.get_logger()

@traceroot.trace(name="calculate")
def calculate(x: int, y: int) -> int:
    logger.info(f"Calculating {x} + {y}")
    result = x + y
    logger.info(f"Result: {result}")
    return result

def main():
    result = calculate(5, 3)
    print(f"Final result: {result}")

if __name__ == "__main__":
    main()

Class Methods

You can also trace class methods:
import traceroot

traceroot.init(
    token="traceroot-********************************",
    service_name="python-example"
)

logger = traceroot.get_logger()

class CalculatorService:
    @traceroot.trace(name="add")
    def add(self, x: int, y: int) -> int:
        logger.info(f"Adding {x} and {y}")
        return x + y

    @traceroot.trace(name="multiply")
    def multiply(self, x: int, y: int) -> int:
        logger.info(f"Multiplying {x} and {y}")
        return x * y

def main():
    calc = CalculatorService()
    result1 = calc.add(5, 3)
    result2 = calc.multiply(result1, 2)
    logger.info(f"Final result: {result2}")

if __name__ == "__main__":
    main()

Example