Spans
If you haven't already, we recommend reading OpenTelemetry first.
None of the tooling below requires LLMs. It is, however, very handy when working with them.
Lilypad implements a span
context manager that makes it easy to instrument a block of code:
import lilypad
lilypad.configure()
with lilypad.span("Something") as span:
span.log("Did something...")
This will automatically capture information such as the latency of the code run within the span, including any calls to log
that you make inside of the block.
Logging Levels
The span
context manager provides additional convenience methods for common logging levels:
log
— alias for theinfo
method.info
— log an informational message.debug
— log a debug message.warning
— log a warning message.error
— log an error message.critical
— log a critical message.
For example, you may want to catch and log and exception:
import lilypad
lilypad.configure()
with lilypad.span("Possible Failure") as span:
try:
# do something that could error
raise RuntimeError("For testing.")
except RuntimeError as e:
span.error(f"Runtime exception caught: {e}")
Metadata
You can also capture arbitrary structured metadata:
import lilypad
lilypad.configure()
with lilypad.span("Structured Metadata") as span:
span.metadata({"key": "value"})
Calling metadata
multiple times will merge the dictionaries.
Nested Spans
Lilypad will properly capture nested spans as what we call Traces, which are really just a collection of nested spans that share a single common parent.
import lilypad
lilypad.configure()
with lilypad.span("Parent Span") as parent_span:
parent_span.log("I'm the parent!")
with lilypad.span("Child span") as child_span:
child_span.log("I'm the child!")
The project home page will only display the parent in each row. You can click the dropdown to view the entire collection of spans contained within that trace: