Skip to main content

Manual Tracing

While MLflow's automatic tracing provides instant observability for supported frameworks, manual tracing gives you complete control over how your GenAI applications are instrumented. This flexibility is essential for building production-ready applications that require detailed monitoring and debugging capabilities.

Mix of auto and manual tracing

Manual tracing is the right choice when you need:

  • 🔍 Fine-Grained Control: Define exactly which parts of your code to trace
  • ⚙️ Custom Frameworks: Instrument proprietary or internal frameworks
  • 🤖 Advanced Scenarios: Complex workflows, multi-threaded or async operations, streaming responses with custom aggregation, custom trace metadata and attributes

Manual Tracing Examples

The manual tracing APIs provide an intuitive way to add tracing with minimal code changes. They automatically handle trace lifecycle, exception tracking, and parent-child relationships.

Best for: Function-level tracing with minimal code changes

import mlflow
from mlflow.entities import SpanType


@mlflow.trace(span_type=SpanType.CHAIN)
def process_request(query: str) -> str:
# Your code here - automatically traced!
result = generate_response(query)
return result


@mlflow.trace(span_type=SpanType.LLM)
def generate_response(query: str) -> str:
# Nested function - parent-child relationship handled automatically
return llm.invoke(query)

Key Benefits:

  • One-line instrumentation for any function
  • Automatic exception handling
  • Works with async/generator functions

Learn more about decorators →

Next Steps

Ready to start instrumenting your code? Choose your approach:

Decorators & Fluent APIs - Start here for most use cases

Automatic Tracing - Combine manual and automatic tracing