much cleaner now, and simpler.
- `span` is an open sum type, so it can carry as much info as we want
from enter to exit. This means most collectors shouldn't even need a
global table for spans!
- merge manual spans and spans. It's just spans now. Keep old
Trace_core.xxx_manual_xxx functions but deprecate them
- add `extension_parameter` to carry additional info to collector (eg
OTEL span kind, TEF sync/async, maybe span links, etc)
- make the collector into a record of callbacks + a state, for
efficiency (but also to make it easier to extend in the future with
callbacks that have a default implementation
)
- in entering manual spans, we now pass an explicit span_ctx that
contains a trace_id (bytes) and the parent span id (int64).
- this makes compat with OTEL easier as we want this sort
of span_ctx to be passed around.
libraries and collectors can now define their own "events" that
collectors will handle (or not), without having to contribute them to
ocaml-trace at all.
After long discussions with @ELLIOTTCABLE, the collector should only
provide a `with_`-like function for regular spans. This allows
each concurrency library to use its native mechanism for local storage,
which is almost always based on such a scope function.
These spans require the user to pass the surrounding span, if any, when
entering a new span. They use the information inside (which is collector
specific) to track what asynchronous task is currently being executed.
Wrappers around `trace`, specific to an async library (e.g. Eio, lwt,
Async, etc.) can then smooth this over by providing a `with_async_span`
construct that uses some implicit contextual storage to carry the
`surrounding` scope around.
this way, we can actually use only `trace.core` when we also expect to
use compiler-libs.toplevel (which contains a naked `Trace` module, which
would cause .cmi collisions). The library `trace` still exists, and just
forwards to `trace.core`.