Tracing requires keeping mappings for tracing identifiers per request. I don't know you do that without global state unless you want the tracing identifiers to pollute your own internal apis everywhere.
Many frameworks have the idea of a context" for this, that holds per-request state, following your reques through the system. Functions that don't care about the context just pass it on to whatever they call.
I think Go was smart to make this concept part of the standard library, as it encouraged frameworks to adopt it as well.
Big agree on Golang. I had colleagues working with 5-6 JS microservices and they really wanted to keep span IDs so they can have sub-spans and unify semantic requests together (they also included background jobs processing) and they had to bring up a Redis container just to keep mappings of pieces of data every microservice has access to (e.g. order_id) and the actual span ID. It worked well in the end but it needed to be fully manually taken care of.
I understand that but if you look at the Python implementation (or at least as it was 1-2 years ago), you have a lot of god objects that hack __new__ which leads to hidden flows when you create new instances of tracers for example. I'm not saying I have a better idea but when you put that together with the docs and the (at the time) very bare examples, it's just annoying.
I think Go was smart to make this concept part of the standard library, as it encouraged frameworks to adopt it as well.