LangfuseLangfuse Python SDK 4.15.4 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
38 small wins to finish your pathNext lesson

Your first trace

A trace is the record of one piece of work: what went in, what came out, and every step between. Tracing the shop's support desk takes five lines.

The desk before any tracing, as plain Python: it reads a ticket, finds an order id in it, and looks the order up.

Exampleplain.py
import re

ORDERS = {"A17": "shipped on 3 March"}


def answer(ticket):
    order = re.search(r"[A-Z]\d{2}", ticket)
    if not order:
        return "Could you send your order number?"
    return f"Order {order.group()}: {ORDERS.get(order.group(), 'not found')}"


print(answer("Where is my order A17?"))
print(answer("Is B22 on its way?"))
Example
python plain.py

answer finds an order id, a capital letter and two digits, and looks it up. B22 is not in ORDERS, so it says so. Nothing about this run is recorded anywhere.

A Langfuse to send traces to

Langfuse is a server, and the SDK needs one to send to. Instead of signing up, run local_langfuse.py on your own machine: it answers what the SDK sends and keeps it, so every lesson can print what was exported. Copy it once from the appendix at the end, save it beside your lesson files, and leave it alone.

Examplefirst_trace.py
from langfuse import Langfuse

import local_langfuse

url = local_langfuse.start()
langfuse = Langfuse(public_key="pk-lf-local", secret_key="sk-lf-local", base_url=url)

start returns the address the server is listening on. The keys can be any strings, because this server does not check them, and base_url is what points the SDK at it instead of Langfuse's own servers.

Recording one piece of work

Examplefirst_trace.py, after the ORDERS and answer lines from plain.py
ticket = "Where is my order A17?"
with langfuse.start_as_current_observation(as_type="span", name="support-ticket", input=ticket) as span:
    span.update(output=answer(ticket))

langfuse.flush()
local_langfuse.tree("input", "output")
Example
python first_trace.py

start_as_current_observation opens an observation, a single recorded step, named support-ticket, with the ticket as its input. The with block closes it, and span.update sets its output. The SDK sends in the background, so flush pushes what is queued before the program prints.

tree is a helper in that file: it prints what the server received, here one observation, which is also the whole trace. Most lessons from here on end this way.

Where traces go when you forget base_url

Exampleno_url.py
from langfuse import Langfuse

import local_langfuse

url = local_langfuse.start()
langfuse = Langfuse(public_key="pk-lf-local", secret_key="sk-lf-local")

with langfuse.start_as_current_observation(as_type="span", name="support-ticket"):
    pass

langfuse.flush()
print(len(local_langfuse.SPANS), "observations reached the local server")
Example
python no_url.py

With no base_url and no LANGFUSE_BASE_URL, the SDK exports to cloud.langfuse.com. The local server received nothing, the attempt was blocked, and the SDK retried and gave up. The program carried on: the error was logged, never raised. With real keys those retries would have succeeded, and whatever the trace held would now sit on someone else's servers.

Know where your traces go
A trace holds the text your application handled. Before adding tracing to a system that handles customer data, find out which server the SDK sends to and who can read it; checking base_url takes a minute.
Try it yourself
  • Trace two tickets, one inside the other's with block, and print the tree.
  • Print local_langfuse.REQUESTS after flush to see what the SDK asked for.
  • Change the observation's name to ticket and run it again.

You understood something today that you didn't yesterday.