You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was wondering... Why I don't see any OpenTelemetry related issue on Apache Beam? Is it because the runners already provide observability about their jobs?
I'm more interested in the Python side for now, but if there's no reason, would it make sense to create a opentelemetry-instrumentation-apache-beam package?
withlogfire.span("main"):
withPipeline() aspipeline:
text= [
"To be, or not to be: that is the question: ",
"Whether 'tis nobler in the mind to suffer ",
"The slings and arrows of outrageous fortune, ",
"Or to take arms against a sea of troubles, ",
]
pipeline= (
pipeline|"Create">>beam.Create(text)
|"Split">>AutoSpanTransform(beam.ParDo(Split()))
|"Filter">>AutoSpanTransform(beam.Filter(lambdax: x!="the"))
|"Print">>AutoSpanTransform(beam.Map(logfire_print))
)
With the lines above, I'm able to patch run and apply - I thought the transformers would run in the apply, so that's what I was trying to patch, but it looks like the important bit is the run. Although I see how nice having both instrumented gets:
Now I need to find where the PTransformers logic is executed.
EDIT: Okay, it seems that is the PipelineRunner who runs it... Which makes sense... 👀
This is becoming a great exercise to profile apache-beam itself 😅
Now I know how things run...
I've enabled logfire.install_auto_tracing("apache_beam", min_duration=0.00001) to see the above.
I'm now trying to find out the best places to add spans to get execution time. I know already that run_pipeline and run_stages from PipelineRunner are good places.
This looks interesting. I am wondering how this can work with remote Runners like Dataflow or Flink.
I'm going to run with Dataflow soon.
I still didn't find the what I wanted... I want to get the place where the Map function runs, for example... But I think that gets pickled or something, and then I'm having a hard time to find the right location (I think).
This is the code I use - it's not as clean as the snippets above:
I made it work, but not as smooth as I wanted - I can provide code in the next days... Mainly because the context, and the exporter configured don't survive the pickling.
Let me try to explain where I stand now, and I'm actually going to stop on my own, to ask advice.
I've been trying to make it work in Dataflow. This is the pipeline I have in hands (for testing purposes):
classSplit(beam.DoFn):
defprocess(self, element: str):
logfire.info(f"in split {element}")
returnelement.split(" ")
deflogfire_print(element: str):
withlogfire.span("Print"):
logfire.info(element)
logfire.info("{globals}", globals=globals())
logfire.info("{locals}", locals=locals())
logfire.info("{traceback}", traceback=traceback.format_stack())
pipeline_options=PipelineOptions()
withPipeline(options=pipeline_options) aspipeline:
text= [
"To be, or not to be: that is the question: ",
"Whether 'tis nobler in the mind to suffer ",
"The slings and arrows of outrageous fortune, ",
"Or to take arms against a sea of troubles, ",
]
pipeline= (
pipeline|"Create">>beam.Create(text)
|"Split">>beam.ParDo(Split())
|"Filter">>beam.Filter(lambdax: x!="the")
|"Print">>beam.Map(logfire_print)
)
What we want is to have a span that starts when we run the pipeline, i.e. on the machine that ran it:
And we want to have a span being created when each step runs e.g. when logfire_print is called for each element, we want to have the logfire_print wrapped, and then any logfire.info() will be contained on this automatic span that was created.
The problem is... Unfortunately, I can't monkeypatch anything on the worker side, because we actually pickle the function to send it to the worker.
Major challenge is extending WindowedValue and it's encoding. #34902 was prerequisite on Java to make it easier to modify WindowedValue #36373 is foundation work to pass any kind of metadata acros stages, starting with dataflow runner v1
Once merged we will add open telemetry SDK (we already tried that here - #34544 and #35227), drain and CDC features and start v2 and other SDK to come later
I haven't gone into the Python SDK yet. I expect that transparently adding metadata to be propagated everywhere is going to be a lot harder, because it was a massive whole-SDK type-system-assisted refactor. It will have to happen to support transparently passing the otel context everywhere - maybe the work you did can help @Kludex ?
I haven't gone into the Python SDK yet. I expect that transparently adding metadata to be propagated everywhere is going to be a lot harder, because it was a massive whole-SDK type-system-assisted refactor. It will have to happen to support transparently passing the otel context everywhere - maybe the work you did can help @Kludex ?
I was not very familiar with the tool, but what my experiment proved (at least for me) is that we need hooks, or do it internally.
Activity
liferoad commentedon Nov 20, 2024
This is a good idea. We do have a plan to investigate this idea. cc @Abacn
Meanwhile, you are welcome to work on this.
Kludex commentedon Dec 4, 2024
@liferoad @Abacn I was able to do what I want by manually creating a wrapper on the
PTransformers.And then, I can use it like this:
You can see the full code here: https://github.com/Kludex/logfire-apache-beam/blob/main/main.py
You can run it with
python main.py.This is what I see in Logfire (the observability platform we are developing):

Now... I need to be able to do it automatically. I tried to do some patching, like this:
But I keep getting recursive exception - I'm still debugging it. But... I would appreciate help in two things:
Pipeline()?Kludex commentedon Dec 4, 2024
I got something nice running. Although not there yet...
My understanding about this package is growing a bit more... 😅
With the lines above, I'm able to patch
runandapply- I thought the transformers would run in theapply, so that's what I was trying to patch, but it looks like the important bit is therun. Although I see how nice having both instrumented gets:Now I need to find where the
PTransformers logic is executed.EDIT: Okay, it seems that is the
PipelineRunnerwho runs it... Which makes sense... 👀Kludex commentedon Dec 4, 2024
This is becoming a great exercise to profile
apache-beamitself 😅Now I know how things run...
I've enabled
logfire.install_auto_tracing("apache_beam", min_duration=0.00001)to see the above.I'm now trying to find out the best places to add spans to get execution time. I know already that
run_pipelineandrun_stagesfromPipelineRunnerare good places.liferoad commentedon Dec 4, 2024
This looks interesting. I am wondering how this can work with remote Runners like Dataflow or Flink.
Kludex commentedon Dec 4, 2024
I'm going to run with
Dataflowsoon.I still didn't find the what I wanted... I want to get the place where the Map function runs, for example... But I think that gets pickled or something, and then I'm having a hard time to find the right location (I think).
This is the code I use - it's not as clean as the snippets above:
liferoad commentedon Dec 10, 2024
cc @Abacn PTAL.
Kludex commentedon Dec 10, 2024
BTW, I checked in Dataflow.
I made it work, but not as smooth as I wanted - I can provide code in the next days... Mainly because the context, and the exporter configured don't survive the pickling.
Kludex commentedon Dec 12, 2024
Okay... Hi there again... 👋
Let me try to explain where I stand now, and I'm actually going to stop on my own, to ask advice.
I've been trying to make it work in Dataflow. This is the pipeline I have in hands (for testing purposes):
What we want is to have a span that starts when we run the pipeline, i.e. on the machine that ran it:
uv run python main.py \ --region ... \ --runner DataflowRunner \ --project ... \ --temp_location ... \ --requirements_file ./requirements.txt \ --save_main_sessionAnd we want to have a span being created when each step runs e.g. when
logfire_printis called for each element, we want to have thelogfire_printwrapped, and then anylogfire.info()will be contained on this automatic span that was created.The problem is... Unfortunately, I can't monkeypatch anything on the worker side, because we actually pickle the function to send it to the worker.
This is what I got ☝️
I wanted
Printto be inside the first big span...liferoad commentedon Dec 12, 2024
Is it possible to redirect regular logs to logfire?
Kludex commentedon Dec 12, 2024
No, only OpenTelemetry data.
6 remaining items
Kludex commentedon Oct 2, 2025
That's a bit rude.
liferoad commentedon Oct 2, 2025
We can always reopen this. :)
Abacn commentedon Oct 3, 2025
I understand this is in progress, for example, OutputBuilder (#34902) is intended for element-wise tracing that needed for OpenTelemetry support
stankiewicz commentedon Oct 3, 2025
Major challenge is extending WindowedValue and it's encoding.
#34902 was prerequisite on Java to make it easier to modify WindowedValue
#36373 is foundation work to pass any kind of metadata acros stages, starting with dataflow runner v1
Once merged we will add open telemetry SDK (we already tried that here - #34544 and #35227), drain and CDC features and start v2 and other SDK to come later
kennknowles commentedon Oct 7, 2025
I haven't gone into the Python SDK yet. I expect that transparently adding metadata to be propagated everywhere is going to be a lot harder, because it was a massive whole-SDK type-system-assisted refactor. It will have to happen to support transparently passing the otel context everywhere - maybe the work you did can help @Kludex ?
Kludex commentedon Oct 8, 2025
I was not very familiar with the tool, but what my experiment proved (at least for me) is that we need hooks, or do it internally.
Update Beam website roadmap pages (#39899)