RichiCoder1 / opentelemetry-sdk-workers

An Otel SDK for Cloudflare Workers
48 stars 14 forks source link

Arbitrary instrumentation #32

Open beanow-at-crabnebula opened 1 year ago

beanow-at-crabnebula commented 1 year ago

Just testing out the library :heart:

Wondering if I've missed a way to create custom spans.

The use case I've got a few examples for. One is, we're planning on using some of the bindings not yet supported, like KV, R2 and the caches object.

And better yet, we're not always calling it directly :joy: For instance with Workers Sites, https://developers.cloudflare.com/workers/platform/sites/start-from-worker/ There's the @cloudflare/kv-asset-handler utility which handles a ton of static site boilerplate for you.

So while a handler like this works fantastic for the root span:

export default {
    async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
        const sdk = WorkersSDK.fromEnv(request, env, ctx);

        const assetResponse = await getAssetFromKV(
            {
                request,
                waitUntil: ctx.waitUntil.bind(ctx),
            },
            {
                ASSET_NAMESPACE: env.__STATIC_CONTENT,
                ASSET_MANIFEST: env.__STATIC_CONTENT_MANIFEST,
            }
        );

        return sdk.sendResponse(assetResponse);
    },
};

There's no straightforward way to add child spans around getAssetFromKV. Not to mention, what would one contribute to instrument the different code paths within this utility?

Tried hacking a this.traceProvider.register(); in to set the SDK's provider as the global trace provider. Which did allow me to create new spans with the regular @opentelemetry/api calls and collect them. But they're independent spans. Not picking up the context as you'd want.

hansottowirtz commented 1 year ago

@beanow-at-crabnebula We do this now, which connects the spans:

import { Tracer, Context } from "@opentelemetry/api";

const context = (sdk as any).spanContext as Context;
const tracer = (sdk as any).requestTracer as Tracer;

const childSpan = tracer.startSpan(
  "db-query",
  {},
  context
);

Would be great if these fields were public :)