What is Laminar Tracing?

Laminar offers comprehensive observability for your LLM applications, capturing the entire execution flow with minimal setup. This allows you to:

  • Debug complex LLM workflows by seeing exactly how data flows through your application
  • Monitor performance with detailed execution time and token usage metrics
  • Track costs across different models and components
  • Analyze user sessions to understand and improve the end-user experience

Key Concepts

Span

A single operation in your application’s execution flow, such as a function call or an API request. Spans include:

  • Attributes: Input parameters, return values, and other metadata
  • Path: Hierarchical location in your code (e.g., get_user.validate.api_call)
  • Duration: How long the operation took to execute

Trace

A collection of spans that form a complete execution path. Traces show parent-child relationships between operations, helping you understand how your code executes.

Session

A group of related traces belonging to the same user interaction or conversation, allowing you to analyze complete user journeys.

Visualization Example

The tree view on the left shows a trace of an LLM application. The hierarchy displays how functions call each other:

  • answer_question calls fetch_page_and_check
  • which calls check_presence
  • which calls OpenAI

Each node in this tree is a span, giving you a complete picture of your application’s execution.

What Laminar Captures

For every execution of your application, Laminar automatically records:

Performance Metrics

  • Total execution time
  • Per-span execution times
  • Bottlenecks and slow operations

LLM-Specific Data

  • Token counts (input and output)
  • Model information
  • Cost calculations

Inputs & Outputs

  • Function parameters
  • Return values
  • Prompts and completions

Execution Flow

  • Parent-child relationships
  • Complete call hierarchy
  • Cross-service transactions

Getting Started in 2 Minutes

1. Get Your Project API Key

To get the project API key, go to the Laminar dashboard, click the project settings, and generate a project API key.

Specify the key at Laminar initialization. If not specified, Laminar will look for the key in the LMNR_PROJECT_API_KEY environment variable.

2. Initialize Laminar in Your Application

Adding just two lines to your application enables comprehensive tracing:

from lmnr import Laminar
Laminar.initialize(project_api_key="LMNR_PROJECT_API_KEY")

Laminar should be initialized once in your application. This could be at the server startup, or in the entry point of your application.

This will automatically instrument all major LLM provider SDKs, LLM frameworks including LangChain and LlamaIndex, and calls to vector databases.

In some Node JS setups, you may need to manually pass the modules you want to instrument, such as OpenAI. See the section on manual instrumentation.

For more information, refer to the instrumentation docs.

3. That’s it! Your LLM API Calls Are Now Traced

Once initialized, Laminar automatically traces LLM API calls. For example, after initialization, this standard OpenAI call:

from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
)

Will automatically create a span in your Laminar dashboard:

Laminar automatically captures important LLM metrics including latency, token usage, and cost calculations based on the specific model used.

Advanced Tracing Capabilities

Tracing Custom Functions

Beyond automatic LLM tracing, you can use the observe decorator/wrapper to trace specific functions in your application:

You can instrument specific functions by adding the @observe() decorator. This is especially helpful when you want to trace functions, or group separate functions into a single trace.

from lmnr import observe

@observe()  # annotate all functions you want to trace
def my_function():
    res = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": "What is the capital of France?"}],
    )
    return res.choices[0].message.content

my_function()

We are now recording my_function and the OpenAI call, which is nested inside it, in the same trace. Notice that the OpenAI span is a child of my_function. Parent-child relationships are automatically detected and visualized with tree hierarchy.

You can nest as many spans as you want inside each other. By observing both the functions and the LLM/vector DB calls you can have better visualization of execution flow which is useful for debugging and better understanding of the application.

Input arguments to the function are automatically recorded as inputs of the span. The return value is automatically recorded as the output of the span.

Passing arguments to the function in TypeScript is slightly non-obvious. Example:

const myFunction = async () => observe(
  { name: 'myFunction'}, 
  async (param1, param2) => {
    // ...
  }
  'argValue1',
  'argValue2'
);

Self-Hosting Laminar

While Laminar Cloud (api.lmnr.ai) is the default target for traces, you can also send data to your own self-hosted instance:

from lmnr import Laminar
Laminar.initialize(
    project_api_key="<your-project-api-key>",
    base_url="http://localhost", # do not include ports or trailing slash here
    http_port=8000,
    grpc_port=8001
)

OpenTelemetry Integration

Laminar builds on the industry-standard OpenTelemetry protocol, providing:

  • Compatibility with existing OpenTelemetry instrumentation
  • High-performance trace ingestion through gRPC
  • Specialized support for LLM and vector DB operations via OpenLLMetry

If you already use OpenTelemetry in your stack, you can send those traces to Laminar with minimal configuration. Learn more in our OpenTelemetry integration guide.

Next Steps

Now that you understand the basics of Laminar tracing: