Skip to content

feat(mysql2): Instrument mysql2 >= 3.20.0 via native tracing channels#21824

Draft
logaretm wants to merge 5 commits into
developfrom
awad/instrument-mysql2-via-tc
Draft

feat(mysql2): Instrument mysql2 >= 3.20.0 via native tracing channels#21824
logaretm wants to merge 5 commits into
developfrom
awad/instrument-mysql2-via-tc

Conversation

@logaretm

@logaretm logaretm commented Jun 26, 2026

Copy link
Copy Markdown
Member

Instruments mysql2 >= 3.20.0 through its native diagnostics_channel tracing channels instead of monkey-patching, the same way we did for redis/ioredis and mongoose. mysql2 publishes on mysql2:query, mysql2:execute, mysql2:connect and mysql2:pool:connect.

The channel path emits the stable DB semconv (db.system.name, db.query.text, db.operation.name, db.namespace, server.address, server.port), so there's an attribute drift here. We could match the legacy attributes and drop them at v11 instead if that's what we want.

One mysql2-specific thing: the mysql2:query channel publishes the already-formatted SQL with values inlined, so I run it through the OTel db.query.text sanitizer.

Comment thread packages/server-utils/src/index.ts
@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 27.59 kB - -
@sentry/browser - with treeshaking flags 26.03 kB - -
@sentry/browser (incl. Tracing) 46.05 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 47.79 kB - -
@sentry/browser (incl. Tracing, Profiling) 50.81 kB - -
@sentry/browser (incl. Tracing, Replay) 85.28 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 74.89 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 89.97 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 102.64 kB - -
@sentry/browser (incl. Feedback) 44.77 kB - -
@sentry/browser (incl. sendFeedback) 32.39 kB - -
@sentry/browser (incl. FeedbackAsync) 37.52 kB - -
@sentry/browser (incl. Metrics) 28.67 kB - -
@sentry/browser (incl. Logs) 28.91 kB - -
@sentry/browser (incl. Metrics & Logs) 29.6 kB - -
@sentry/react 29.38 kB - -
@sentry/react (incl. Tracing) 48.35 kB - -
@sentry/vue 32.82 kB - -
@sentry/vue (incl. Tracing) 47.91 kB - -
@sentry/svelte 27.61 kB - -
CDN Bundle 30 kB - -
CDN Bundle (incl. Tracing) 47.98 kB - -
CDN Bundle (incl. Logs, Metrics) 31.57 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 49.32 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 70.77 kB - -
CDN Bundle (incl. Tracing, Replay) 85.48 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 86.76 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 91.29 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 92.53 kB - -
CDN Bundle - uncompressed 89.35 kB - -
CDN Bundle (incl. Tracing) - uncompressed 145.28 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 94.05 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 149.25 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 218.59 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 264.29 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 268.25 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 277.99 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 281.94 kB - -
@sentry/nextjs (client) 50.73 kB - -
@sentry/sveltekit (client) 46.44 kB - -
@sentry/core/server 77.75 kB - -
@sentry/core/browser 64.06 kB - -
@sentry/node-core 62.37 kB -0.01% -1 B 🔽
@sentry/node 121.48 kB +0.2% +238 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 69.95 kB - -
@sentry/node/light 50.46 kB - -
@sentry/node - without tracing 72.68 kB - -
@sentry/aws-serverless 83.52 kB -0.01% -1 B 🔽
@sentry/cloudflare (withSentry) - minified 180.62 kB - -
@sentry/cloudflare (withSentry) 446.93 kB - -

View base workflow run

@logaretm logaretm force-pushed the awad/instrument-mysql2-via-tc branch 2 times, most recently from bfe56a5 to 2dc47b7 Compare July 1, 2026 17:23
logaretm added 5 commits July 2, 2026 12:18
mysql2 >= 3.20.0 publishes its operations over node:diagnostics_channel
(mysql2:query / :execute / :connect / :pool:connect), so the SDK can
subscribe to those channels instead of monkey-patching, the same way we
did for redis/ioredis and mongoose.

The subscription lives in server-utils as mysql2Integration, and the node
mysql2Integration extends it (via extendIntegration) while keeping the
vendored OTel patcher for mysql2 < 3.20.0, which is now gated to that range
so the two paths never double-instrument.

The channel path emits the stable DB semconv (db.system.name,
db.query.text, db.operation.name, db.namespace, server.address,
server.port), so there's the same attribute drift we accepted for
redis/mongoose. mysql2 publishes already-formatted SQL, so db.query.text
is run through the OTel sanitizer and raw values are never attached.
The mysql2-tracing-channel docker-compose bound host port 3307, which
collides with the knex/mysql2 suite. When both run in parallel the second
container fails with 'port is already allocated'. Switch to 3308.
Replace the conditional-spread pattern for optional attributes with
`?? undefined` (and `|| undefined` for the database name, which keeps
dropping empty strings). Undefined-valued keys are dropped by the span
backends, so this is equivalent while keeping the attribute lines
consistent.
Replace the ad-hoc `void Promise.resolve().then(...)` deferral with the
shared `waitForTracingChannelBinding` util, matching the mongoose,
graphql, vercel-ai and redis integrations. It retries until the async
context binding is available, so it also handles custom OTel setups where
the binding isn't ready on the first tick.
The suite gated readiness on `mysqladmin ping`, which reports "alive"
even during MySQL 8's init bootstrap (it treats access-denied as alive).
So `docker compose up --wait` could return before the real server and
root password were ready, and the scenario's first connection was
dropped ("server closed the connection") — crashing the run and timing
out the test. Gate on an authenticated `SELECT 1` instead, mirroring the
knex/mysql2 sibling suite (#21868).
@logaretm logaretm force-pushed the awad/instrument-mysql2-via-tc branch from b8c0f1c to ba2bc18 Compare July 2, 2026 16:18
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.

1 participant