Skip to content

feat(webapp): tag Prisma spans with db.datasource attribute#3422

Merged
ericallam merged 1 commit intomainfrom
feat/prisma-span-datasource-attribute
Apr 21, 2026
Merged

feat(webapp): tag Prisma spans with db.datasource attribute#3422
ericallam merged 1 commit intomainfrom
feat/prisma-span-datasource-attribute

Conversation

@ericallam
Copy link
Copy Markdown
Member

@ericallam ericallam commented Apr 21, 2026

Summary

Stamp every Prisma span with db.datasource: "writer" | "replica" so traces can distinguish which client the query went through.

Both PrismaClient instances share the same global @prisma/instrumentation, so their spans come out with identical names and attributes today. This makes them trivially filterable.

How

Two pieces in apps/webapp/app/:

  1. v3/tracer.server.ts — a DatasourceAttributeSpanProcessor reads an OTel context key in onStart and calls span.setAttribute("db.datasource", value). Registered as the first span processor.
  2. db.server.tstagDatasource(datasource, client) wraps each PrismaClient with $extends({ query: { $allOperations } }). The middleware sets the context key around the query and directly tags the active span (to catch prisma:client:operation, which Prisma creates before the middleware fires).

Context-propagation gotcha

PrismaPromise is lazy — query(args) returns a thenable that only starts when someone .then()s it. The naive context.with(ctx, () => query(args)) restores ALS synchronously, so when Prisma's internal code awaits the thenable later, the engine spans fire with the original ALS. Wrapping as async () => await query(args) forces the .then() inside the context.with callback, so ALS stays on our context for the engine spans.

Coverage

  • Tagged: all prisma:engine:* (connection, db_query, serialize, query, etc.), prisma:client:operation, prisma:client:serialize, prisma:client:connect
  • Not tagged: prisma:client:load_engine — one-time startup, fires before any query

Concurrent Promise.all([writer.x, replica.y]) correctly tags each pool separately (ALS isolates per-Promise chain).

Performance

One context.with (~200ns) and one setAttribute per span (effectively free per OTel JS benchmarks) per Prisma op. Negligible against a query path measured in milliseconds.

Test plan

  • Verify db.datasource appears on prisma:engine:connection spans after the webapp is restarted
  • Spot-check a handful of real traces carry the attribute

Wrap the writer and replica Prisma clients with a $extends middleware
that sets an OTel context key around each operation, and a span
processor that reads the key and stamps 'db.datasource' = 'writer' |
'replica' on every span created in that scope.

Also directly tags the prisma:client:operation span via
trace.getActiveSpan() since that outer span is created before the
extension middleware runs and would otherwise miss the context.

Motivation: writer and replica emit identical span names through the
same global instrumentation, so pool-saturation monitors on
prisma:engine:connection could not distinguish the two pools. With this
change, monitors can filter by the new attribute.

Context propagation note: PrismaPromise is lazy, so wrapping query(args)
directly with context.with leaves the thenable unstarted and Prisma's
.then() fires outside the scope. The inner 'async () => await query(args)'
forces the .then() inside the context.with callback so engine spans
see the correct active context.

Not tagged: prisma:client:load_engine (one-time startup, irrelevant).
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 21, 2026

⚠️ No Changeset found

Latest commit: 7bd7398

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cd545daa-95dc-49be-833a-1adeaa1b7c88

📥 Commits

Reviewing files that changed from the base of the PR and between b570586 and 7bd7398.

⛔ Files ignored due to path filters (1)
  • references/hello-world/src/trigger/example.ts is excluded by !references/**
📒 Files selected for processing (3)
  • .server-changes/prisma-span-datasource-attribute.md
  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Add crumbs as you write code using // @Crumbs comments or `// `#region` `@crumbs blocks. These are temporary debug instrumentation and must be stripped using agentcrumbs strip before merge.

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from @trigger.dev/sdk when writing Trigger.dev tasks. Never use @trigger.dev/sdk/v3 or deprecated client.defineJob.

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: Access environment variables through the env export of env.server.ts instead of directly accessing process.env
Use subpath exports from @trigger.dev/core package instead of importing from the root @trigger.dev/core path

Use named constants for sentinel/placeholder values (e.g. const UNSET_VALUE = '__unset__') instead of raw string literals scattered across comparisons

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
apps/webapp/**/*.server.ts

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

apps/webapp/**/*.server.ts: Never use request.signal for detecting client disconnects. Use getRequestAbortSignal() from app/services/httpAsyncStorage.server.ts instead, which is wired directly to Express res.on('close') and fires reliably
Access environment variables via env export from app/env.server.ts. Never use process.env directly
Always use findFirst instead of findUnique in Prisma queries. findUnique has an implicit DataLoader that batches concurrent calls and has active bugs even in Prisma 6.x (uppercase UUIDs returning null, composite key SQL correctness issues, 5-10x worse performance). findFirst is never batched and avoids this entire class of issues

Files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: internal-packages/database/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:17.177Z
Learning: Applies to internal-packages/database/**/{app,src,webapp}/**/*.{ts,tsx,js,jsx} : Use `$replica` from `~/db.server` for read-heavy queries in the webapp instead of the primary database connection
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3368
File: apps/webapp/app/services/taskIdentifierRegistry.server.ts:24-67
Timestamp: 2026-04-13T21:44:00.032Z
Learning: In `apps/webapp/app/services/taskIdentifierRegistry.server.ts`, the sequential upsert/updateMany/findMany writes in `syncTaskIdentifiers` are intentionally NOT wrapped in a Prisma transaction. This function runs only during deployment-change events (low-concurrency path), and any partial `isInLatestDeployment` state is acceptable because it self-corrects on the next deployment. Do not flag this as a missing-transaction/atomicity issue in future reviews.
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL

Applied to files:

  • .server-changes/prisma-span-datasource-attribute.md
  • apps/webapp/app/db.server.ts
📚 Learning: 2026-03-02T12:43:17.177Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: internal-packages/database/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:17.177Z
Learning: Applies to internal-packages/database/**/{app,src,webapp}/**/*.{ts,tsx,js,jsx} : Use `$replica` from `~/db.server` for read-heavy queries in the webapp instead of the primary database connection

Applied to files:

  • .server-changes/prisma-span-datasource-attribute.md
  • apps/webapp/app/db.server.ts
📚 Learning: 2026-03-24T10:42:43.111Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3255
File: apps/webapp/app/routes/api.v1.runs.$runId.spans.$spanId.ts:100-100
Timestamp: 2026-03-24T10:42:43.111Z
Learning: In `apps/webapp/app/routes/api.v1.runs.$runId.spans.$spanId.ts` (and related span-handling code in trigger.dev), `span.entity` is a required (non-optional) field on the `SpanDetail` type and is always present. Do not flag `span.entity.type` as a potential null pointer / suggest optional chaining (`span.entity?.type`) in this context.

Applied to files:

  • .server-changes/prisma-span-datasource-attribute.md
📚 Learning: 2026-04-13T21:44:00.032Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3368
File: apps/webapp/app/services/taskIdentifierRegistry.server.ts:24-67
Timestamp: 2026-04-13T21:44:00.032Z
Learning: In `apps/webapp/app/services/taskIdentifierRegistry.server.ts`, the sequential upsert/updateMany/findMany writes in `syncTaskIdentifiers` are intentionally NOT wrapped in a Prisma transaction. This function runs only during deployment-change events (low-concurrency path), and any partial `isInLatestDeployment` state is acceptable because it self-corrects on the next deployment. Do not flag this as a missing-transaction/atomicity issue in future reviews.

Applied to files:

  • apps/webapp/app/db.server.ts
📚 Learning: 2026-03-02T12:43:25.254Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: internal-packages/run-engine/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:25.254Z
Learning: Use Prisma for data persistence with support for read-only replica queries via `readOnlyPrisma`

Applied to files:

  • apps/webapp/app/db.server.ts
📚 Learning: 2026-04-15T15:39:06.868Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-04-15T15:39:06.868Z
Learning: Use Prisma 6.14.0 from `internal-packages/database` for database operations. This is the pinned version for the monorepo.

Applied to files:

  • apps/webapp/app/db.server.ts
📚 Learning: 2026-04-16T13:45:18.782Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3368
File: apps/webapp/test/engine/taskIdentifierRegistry.test.ts:3-19
Timestamp: 2026-04-16T13:45:18.782Z
Learning: In `apps/webapp/test/engine/taskIdentifierRegistry.test.ts`, the `vi.mock` calls for `~/services/taskIdentifierCache.server` (stubbing `getTaskIdentifiersFromCache` and `populateTaskIdentifierCache`), `~/models/task.server` (stubbing `getAllTaskIdentifiers`), and `~/db.server` (stubbing `prisma` and `$replica`) are intentional. The suite uses real Postgres via testcontainers for all `TaskIdentifier` DB operations, but isolates the Redis cache layer and legacy query fallback as separate concerns not exercised in this test file. Do not flag these mocks as violations of the no-mocks policy in future reviews.

Applied to files:

  • apps/webapp/app/db.server.ts
📚 Learning: 2026-03-22T13:26:12.060Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/code/TextEditor.tsx:81-86
Timestamp: 2026-03-22T13:26:12.060Z
Learning: In the triggerdotdev/trigger.dev codebase, do not flag `navigator.clipboard.writeText(...)` calls for `missing-await`/`unhandled-promise` issues. These clipboard writes are intentionally invoked without `await` and without `catch` handlers across the project; keep that behavior consistent when reviewing TypeScript/TSX files (e.g., usages like in `apps/webapp/app/components/code/TextEditor.tsx`).

Applied to files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
📚 Learning: 2026-03-22T19:24:14.403Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:200-204
Timestamp: 2026-03-22T19:24:14.403Z
Learning: In the triggerdotdev/trigger.dev codebase, webhook URLs are not expected to contain embedded credentials/secrets (e.g., fields like `ProjectAlertWebhookProperties` should only hold credential-free webhook endpoints). During code review, if you see logging or inclusion of raw webhook URLs in error messages, do not automatically treat it as a credential-leak/secrets-in-logs issue by default—first verify the URL does not contain embedded credentials (for example, no username/password in the URL, no obvious secret/token query params or fragments). If the URL is credential-free per this project’s conventions, allow the logging.

Applied to files:

  • apps/webapp/app/db.server.ts
  • apps/webapp/app/v3/tracer.server.ts
📚 Learning: 2026-03-02T12:43:25.254Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: internal-packages/run-engine/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:25.254Z
Learning: Applies to internal-packages/run-engine/src/engine/systems/**/*.ts : Integrate OpenTelemetry tracer and meter instrumentation in RunEngine systems for observability

Applied to files:

  • apps/webapp/app/v3/tracer.server.ts
📚 Learning: 2026-03-29T19:16:28.864Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 3291
File: apps/webapp/app/v3/featureFlags.ts:53-65
Timestamp: 2026-03-29T19:16:28.864Z
Learning: When reviewing TypeScript code that uses Zod v3, treat `z.coerce.*()` schemas as their direct Zod type (e.g., `z.coerce.boolean()` returns a `ZodBoolean` with `_def.typeName === "ZodBoolean"`) rather than a `ZodEffects`. Only `.preprocess()`, `.refine()`/`.superRefine()`, and `.transform()` are expected to wrap schemas in `ZodEffects`. Therefore, in reviewers’ logic like `getFlagControlType`, do not flag/unblock failures that require unwrapping `ZodEffects` when the input schema is a `z.coerce.*` schema.

Applied to files:

  • apps/webapp/app/v3/tracer.server.ts
🔇 Additional comments (5)
.server-changes/prisma-span-datasource-attribute.md (1)

1-6: LGTM — scope matches implementation.

The enumerated span coverage (prisma:engine:*, prisma:engine:connection, outer prisma:client:operation) lines up with how DatasourceAttributeSpanProcessor + tagDatasource actually tag spans. Good to have this contract written down for future monitor/dashboard authors.

apps/webapp/app/v3/tracer.server.ts (2)

65-81: Span processor is correctly ordered and minimal.

onStart reads the key from parentContext (not the span's own context), which is the right choice: the processor runs synchronously at span creation time, and any descendant created while tagDatasource's context.with is active will inherit the key via its parent context. The typeof ds === "string" guard keeps it safe against unrelated context pollution. No concerns.


227-227: Good call registering as the first SpanProcessor.

Placing DatasourceAttributeSpanProcessor before BatchSpanProcessor/SimpleSpanProcessor guarantees the attribute is set before any exporter processes onEnd (processors run in registration order). Attribute propagation to exported spans is deterministic.

apps/webapp/app/db.server.ts (2)

119-124: Replica fallback tags correctly.

When DATABASE_READ_REPLICA_URL is unset, $replica resolves to the writer-wrapped prisma, so $replica.* calls accurately emit db.datasource="writer" — that's the honest answer for monitoring (the query really did hit the writer). Nice.


101-117: Dual-tagging approach is sound; transaction span gap warrants clarification in migration doc.

The trace.getActiveSpan()?.setAttribute(...) + context.with(... DATASOURCE_CONTEXT_KEY ...) combo correctly handles Prisma's ordering quirk (outer prisma:client:operation is created before the middleware runs, so only the active-span path tags it; child engine/serialize/connect spans then get picked up by DatasourceAttributeSpanProcessor). Wrapping as async () => await query(args) rather than returning the PrismaPromise directly is also necessary to keep ALS active when the lazy thenable starts.

The .server-changes/prisma-span-datasource-attribute.md migration doc currently lists only prisma:engine:*, prisma:engine:connection, and prisma:client:operation as tagged spans. The prisma:client:transaction span generated by prisma.$transaction(...) is not routed through $allOperations, so neither the setAttribute line nor the context.with runs for it—meaning the outer transaction span won't carry db.datasource (its inner prisma:client:operation children still will). Update the migration doc to explicitly note this exclusion and confirm whether production monitors filtering on transaction spans require extending tagging to the $transaction path or whether child-span coverage is sufficient.


Walkthrough

The changes implement OpenTelemetry instrumentation to automatically tag Prisma database operation spans with a db.datasource attribute indicating whether the operation targets a "writer" or "replica" datasource. The implementation introduces a DatasourceAttributeSpanProcessor that reads the datasource from context and applies it to spans, a tagDatasource wrapper function that manages the context during Prisma operations, and updates the client initialization to apply the wrapper to both writer and replica clients. Documentation is added describing the feature's scope and behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description provides comprehensive technical detail about the implementation, but it is missing key template sections including the Closes issue reference, testing steps checklist, and changelog. Complete the PR description template by adding Closes #issue, marking checklist items, documenting testing steps, and including a changelog summary section.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding db.datasource attribute tagging to Prisma spans to distinguish between writer and replica clients.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/prisma-span-datasource-attribute

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ericallam ericallam marked this pull request as ready for review April 21, 2026 15:48
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@ericallam ericallam merged commit 7c95ee4 into main Apr 21, 2026
43 checks passed
@ericallam ericallam deleted the feat/prisma-span-datasource-attribute branch April 21, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants