Label and scope queries¶
Label queries¶
A label names the queries a block of code runs, so you can find them again: in your tracing backend, in the console output, and in the viewer's search.
from polars_telemetry import label
with label("nightly"), label("revenue_by_region"):
report.collect()
Nested labels join with /, so this query is nightly/revenue_by_region.
| Where | How it appears |
|---|---|
| Span | polars.query.label |
| Profile | "label", the query's title in the viewer |
| Console | the header, in place of the query id |
| Metrics | never: a free-form value would make unbounded metric series |
Each thread has its own labels, so concurrent work does not mix them up. Labels need no exporter of their own and cost nothing when nothing is installed.
Not for collect_async() or collect_batches()
polars reports those queries from its own threads, where neither the label nor your call site is visible, so they arrive without both.
Scope a block of code¶
profile() collects the queries a block of code runs, without setting up an
exporter for the whole process. Useful in a test, a notebook cell, or around
one function you suspect:
from polars_telemetry import profile
with profile() as session:
report = build_report()
print(len(session), "queries,", session.wall_ms, "ms")
print(session.slowest.call_site)
session.write("profiles/report.jsonl") # open this in the viewer
| Member | Gives you |
|---|---|
for query in session |
every query, in the order they finished |
session.slowest |
the longest by wall time, or None |
session.wall_ms |
summed wall time; queries may overlap |
session.profiles() |
each query as a profile document |
session.write(path) |
a session file the viewer opens |
If nothing is installed, the block installs instrumentation and removes it afterwards. If an application has already installed exporters, they keep receiving every query; the block collects alongside them. Blocks may nest.
The scope is the process, not the thread
A block collects every query that finishes while it is open, including queries other threads ran.
Combine the two to find one part of a larger job:
with profile() as session, label("load"):
load_inputs()