Observability [Paid]

Tracing and tagging functions

BAML allows you to trace any function with the @trace decorator. This will make the function’s input and output show up in the Boundary dashboard. This works for any python function you define yourself. BAML LLM functions (or any other function declared in a .baml file) are already traced by default. Logs are only sent to the Dashboard if you setup your environment variables correctly.

Prerequisites

Make sure you setup the Boundary dashboard project before you start.

Make sure you also CTRL+S a .baml file to generate the baml_client

Example

In the example below, we trace each of the two functions pre_process_text and full_analysis:

1from baml_client import baml
2from baml_client.types import Book, AuthorInfo
3from baml_client.tracing import trace
4
5# You can also add a custom name with trace(name="my_custom_name")
6# By default, we use the function's name.
7@trace
8async def pre_process_text(text):
9 return text.replace("\n", " ")
10
11
12@trace
13async def full_analysis(book: Book):
14 sentiment = await baml.ClassifySentiment(
15 pre_process_text(book.content)
16 )
17 book_analysis = await baml.AnalyzeBook(book)
18 return book_analysis
19
20
21@trace
22async def test_book1():
23 content = """Before I could reply that he [Gatsby] was my neighbor...
24 """
25 processed_content = await pre_process_text(content)
26 return await full_analysis(
27 Book(
28 title="The Great Gatsby",
29 author=AuthorInfo(firstName="F. Scott", lastName="Fitzgerald"),
30 content=processed_content,
31 ),
32 )

This allows us to see each function invocation, as well as all its children in the dashboard:

See running tests for more information on how to run this test.

Adding custom tags

The dashboard view allows you to see custom tags for each of the function calls. This is useful for adding metadata to your traces and allow you to query your generated logs more easily.

To add a custom tag, you can import set_tags(..) as below:

1from baml_client.tracing import set_tags, trace
2import typing
3
4@trace
5async def pre_process_text(text):
6 set_tags(userId="1234")
7
8 # You can also create a dictionary and pass it in
9 tags_dict: typing.Dict[str, str] = {"userId": "1234"}
10 set_tags(**tags_dict) # "**" unpacks the dictionary
11 return text.replace("\n", " ")