Tracer Module
The tracer module provides functionality for capturing responses from functions across multiple languages:
- Python: Using the
capture_response
decorator intracer.py
- Go: Using the
CaptureResponse
function in theclient
package - TypeScript: Using the
captureResponse
function
Go Usage
Installation
Prerequisites
- Go version 1.20 or higher
- Working Go environment (GOPATH configured)
- Task (optional, for development tasks)
Install using go get
go get github.com/tied-inc/eval-track/tracker-go
Install using Task (recommended for development)
# Install Task if not already installed
npm install -g @go-task/cli
# Install dependencies
task install-tracker
Basic Usage
package main
import (
"github.com/tied-inc/eval-track/tracker-go/pkg/client"
)
// Define your response struct
type Response struct {
Message string `json:"message"`
}
func main() {
// Create a new tracer client
tracer := client.NewTracerClient("http://localhost:8000")
// Wrap a function that returns (Response, error)
wrappedFn := tracer.CaptureResponse(func() (Response, error) {
return Response{Message: "Hello"}, nil
})
// Call the wrapped function
response, err := wrappedFn()
if err != nil {
// Handle error
}
}
Error Handling
// Function that may return an error
wrappedFn := tracer.CaptureResponse(func(x int) (Response, error) {
if x < 0 {
return Response{}, fmt.Errorf("negative input: %d", x)
}
return Response{Message: fmt.Sprintf("Input: %d", x)}, nil
})
// The error will be captured in the trace data
response, err := wrappedFn(-1)
Features
- Generates unique trace IDs using ULID
- Supports both successful responses and errors
- Preserves function signatures using Go's reflection
- Automatically serializes responses to JSON
- Thread-safe client implementation
TypeScript Usage
Installation
Prerequisites
- Node.js version 18 or higher
- pnpm (recommended), npm, or yarn
- Task (optional, for development tasks)
Install using package manager
# Using pnpm (recommended)
pnpm install @tied-inc/eval-track
# Or using npm
npm install @tied-inc/eval-track
# Or using yarn
yarn add @tied-inc/eval-track
Install using Task (recommended for development)
# Install Task if not already installed
npm install -g @go-task/cli
# Install dependencies
task install-tracker
Basic Usage
import { captureResponse } from '@tied-inc/eval-track';
// Define your response type
interface Response {
message: string;
}
// Basic async function
async function getData(): Promise<Response> {
return { message: "Hello from TypeScript!" };
}
// Wrap the function
const wrappedFn = captureResponse(getData);
// Use the wrapped function
const result = await wrappedFn();
console.log(result.message);
Error Handling
import { z } from 'zod';
import { captureResponse } from '@tied-inc/eval-track';
// Define schema for validation
const ResponseSchema = z.object({
data: z.string(),
timestamp: z.number(),
});
type Response = z.infer<typeof ResponseSchema>;
// Function that might throw
async function riskyOperation(): Promise<Response> {
throw new Error('Operation failed');
}
// Errors are captured in trace data
const wrapped = captureResponse(riskyOperation);
try {
await wrapped();
} catch (error) {
console.error(error);
}
Features
- Generates unique trace IDs using ULID
- Uses Zod for runtime type validation
- Supports both synchronous and asynchronous functions
- Preserves function signatures using TypeScript types
- Automatically serializes responses to JSON
Internal Operation
- When
captureResponse
is called, it creates a closure that wraps the original function - Each function call generates a unique trace ID using ULID
- The wrapped function executes the original function inside a try-catch block
- Response data or error is captured and sent to the trace server asynchronously
- The original return value or error is passed through unchanged
Limitations
- Return values should be JSON-serializable objects
- Error objects are stringified for trace storage
- Trace data storage is asynchronous and may not complete immediately
- Network errors during trace storage are logged but don't affect the wrapped function
For more detailed information and advanced usage examples, see the TypeScript tracer README.
Go Internal Operation
- When
CaptureResponse
is called, it uses reflection to analyze the function signature - A new function is created that matches the original signature exactly
- Each function call generates a unique trace ID using ULID
- The wrapped function executes the original function and captures its return values
- Response data or error is sent to the trace server asynchronously
- Original return values are passed through unchanged
Go Limitations
- Functions must return (T, error) where T is any type
- Return values must be JSON-serializable
- Reflection usage may impact performance on very hot code paths
- Trace data storage is asynchronous and may not complete immediately
- Network errors during trace storage are logged but don't affect the wrapped function
For more detailed information and advanced usage examples, see the Go tracer README.
Rust Usage
Installation
Prerequisites
- Rust with Cargo installed
- Task (optional, for development tasks)
Install using Cargo
cargo add eval-track-rust --git https://github.com/tied-inc/eval-track
Install using Task (recommended for development)
# Install Task if not already installed
npm install -g @go-task/cli
# Install dependencies
task install-tracker
Basic Usage
use tracker::{capture_response, init_tracer};
// Initialize the tracer
init_tracer("http://localhost:8000");
// Define your response type
#[derive(serde::Serialize, serde::Deserialize)]
struct Response {
message: String,
}
// Use the capture_response attribute
#[capture_response]
fn get_data() -> Response {
Response {
message: String::from("Hello from Rust!")
}
}
// Async function support
#[capture_response]
async fn get_data_async() -> Response {
Response {
message: String::from("Hello from async Rust!")
}
}
Error Handling
use tracker::{capture_response, TracerError};
#[capture_response]
fn risky_operation() -> Result<Response, TracerError> {
if some_condition {
Err(TracerError::OperationFailed("Operation failed".into()))
} else {
Ok(Response {
message: String::from("Success!")
})
}
}
Features
- Generates unique trace IDs using ULID
- Supports both synchronous and asynchronous functions via procedural macro
- Uses thiserror for robust error handling
- Thread-safe global tracer client
- Automatic serialization using serde
- Support for Result types and custom errors
Internal Operation
- The
capture_response
procedural macro generates wrapper code at compile time - Each function call generates a unique trace ID using ULID
- The function is executed and its return value or error is captured
- Trace data is sent to the server asynchronously
- Original return value or error is passed through unchanged
Limitations
- Return values must implement serde::Serialize
- Error types must implement std::error::Error
- Trace data storage is asynchronous and may not complete immediately
- Network errors during trace storage are logged but don't affect the wrapped function
For more detailed information and advanced usage examples, see the Rust tracer README.
Python Usage
Installation
Prerequisites
Install using uv
uv pip install "git+https://github.com/tied-inc/eval-track/tracker"
Install using Task (recommended for development)
# Install Task if not already installed
npm install -g @go-task/cli
# Install uv if not already installed
task setup-uv
# Install dependencies
task install-tracker
capture_response Decorator
A decorator that automatically records function return values as trace data. Supports both synchronous and asynchronous functions.
Usage
from tracker.tracer import capture_response
from pydantic import BaseModel
class Response(BaseModel):
message: str
@capture_response
async def async_function() -> Response:
return Response(message="Hello")
@capture_response
def sync_function() -> Response:
return Response(message="World")
Features
- Generates unique trace IDs using ULID
- Uses FastAPI's BackgroundTasks for asynchronous trace data storage
- Function return values must be Pydantic BaseModel instances
- Original function signatures and attributes are preserved using @wraps
Internal Operation
- When the decorator is applied, a unique trace ID is generated
- The function is executed and its return value is captured
- Trace data is stored asynchronously using BackgroundTasks
- The original return value is passed through unchanged
Supported Function Types
- Synchronous functions (defined with
def
) - Asynchronous functions (defined with
async def
)
Limitations
- Return values must be instances of classes that inherit from Pydantic's BaseModel
- Trace data storage is asynchronous and may not complete immediately