I noticed that the `llm.chat.*_tokens` attributes weren't in spans, and it turns out none of the attributes from the wrapped function make it in. only those added synchronously from within `wrapWithSpan` do.
A few things in play here:
1. Switch from `ZoneContextManager` (which doesn't work with native async/await) to `AsyncLocalStorageContextManager` (which does.)
2. (1) requires we use a pnpm patch, since wrangler requires that we import `async_hooks` statically, and the otel code `requires` it, and also requires that it's spelled `node:async_hooks`.
3. encode the payload we try to send _before_ doing the retry loop, so we don't re-encode for each attempt.
4. switch from `startActiveSpan` to `context.with` + `startSpan`. The latter allows us to wrap an async function. the former is for synchronous functions.
Running the prior code in wrangler (but _not_ `npm run dev`) was generating errors during otel initialization. I was ultimately unable to figure out why, or how to fix them:
```
(warn) Initializing OpenTelemetry
(error) Error initializing OpenTelemetry TypeError: Class constructor OTLPExporterBase2 cannot be invoked without 'new'
```
In the end, it was easier to just boil the ocean a little: With claude's help, write a custom otlp exporter and use that. Also use BasicTracerProvider instead of WebTracerProvider.
This version is enough to generate spans from within local wrangler.
found https://github.com/cloudflare/wrangler-action and figured that'd be a better thing than doing our own.
will need to iterate on this on main, I expect.
will need to add GH secrets `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID`
The log should contain a warning showing the following once at startup:
```
OpenTelemetry initialization skipped: HONEYCOMB_API_KEY and/or HONEYCOMB_DATASET not set
```
and every time a span would have been created:
```
OpenTelemetry not initialized, skipping span creation
```
Also sneak in a `service.version` attribute that is `${__APP_VERSION}; ${__COMMIT_HASH}`. e.g.:
