Apache Burr (tracing)

Apache Burr is a Python framework for building state-machine applications. Respan attaches a Burr lifecycle adapter when an ApplicationBuilder builds an application, preserving Burr’s application, action, state, custom-span, and stream concepts.

Create an account at platform.respan.ai and grab an API key.

Run npx @respan/cli setup to set up with your coding agent.

Setup

1

Install packages

$pip install respan-ai respan-instrumentation-burr apache-burr
2

Set your API key

$export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
3

Initialize and run

Initialize Respan before calling ApplicationBuilder.build().

Python
1from burr.core import ApplicationBuilder, Result, State, action, default, expr
2from respan import Respan
3from respan_instrumentation_burr import BurrInstrumentor
4
5respan = Respan(
6 instrumentations=[BurrInstrumentor()],
7)
8
9
10@action(reads=["count"], writes=["count"])
11def increment(state: State) -> State:
12 return state.update(count=state["count"] + 1)
13
14
15result = Result("count").with_name("result")
16
17app = (
18 ApplicationBuilder()
19 .with_identifiers(app_id="counter-app", partition_key="user-42")
20 .with_actions(increment, result)
21 .with_transitions(("increment", "increment", expr("count < 2")))
22 .with_transitions(("increment", "result", default))
23 .with_entrypoint("increment")
24 .with_state(count=0)
25 .build()
26)
27
28try:
29 _, _, state = app.run(halt_after=["result"])
30 print(state["count"])
31finally:
32 respan.shutdown()
4

View your trace

Open the Traces page to inspect the application workflow and its action spans.

What gets traced

Burr lifecycleRespan representationBurr details
Application executionworkflow spanExecution method, initial/final state, application ID, partition key
Action steptask spanAction name, reads, writes, tags, declared inputs, sequence ID, result, state
ActionSpanNested task spanCustom span name, action, sequence ID, dependencies
Stream lifecycleSpan eventsStart, each item index, and end
TracerFactory.log_attributes()Span metadataLogged values and tags

Burr application IDs are mapped to Respan trace groups. Partition keys are mapped to thread identifiers, allowing executions for the same logical partition to be correlated.

Custom spans and attributes

Burr actions that accept __tracer: TracerFactory keep their native custom spans and dependencies:

Python
1from burr.core import State, action
2from burr.visibility import TracerFactory
3
4
5@action(reads=["payload"], writes=["result"])
6def process_payload(state: State, __tracer: TracerFactory) -> State:
7 with __tracer("parse_payload") as span:
8 words = state["payload"].split()
9 span.log_attributes(word_count=len(words), parser="split")
10
11 with __tracer("build_result", span_dependencies=["parse_payload"]):
12 result = {"word_count": len(words)}
13
14 return state.update(result=result)

Content controls

Set capture_content=False to omit state, action inputs and results, stream items, and logged attribute values:

1respan = Respan(
2 instrumentations=[BurrInstrumentor(capture_content=False)]
3)

Application/action identity, state-machine structure, custom span names and dependencies, stream item indexes, identifiers, and status remain available.

Lifecycle

The instrumentor patches ApplicationBuilder.build() and appends one Respan lifecycle adapter. Applications built before activation are not retrofitted. Duplicate adapters are avoided when other Burr lifecycle adapters are already present.

Call respan.shutdown() to flush telemetry and deactivate instrumentation. Applications built while the instrumentor was active retain their adapter object, but it is disabled after the last active instrumentor is deactivated.