Skip to content

feat: add bun sqlite auto instrumentation #16415

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

shyim
Copy link

@shyim shyim commented May 28, 2025

Adds auto instrumentation support for Bun Sqlite

image

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

Copy link
Member

@AbhiPrasad AbhiPrasad left a comment

Choose a reason for hiding this comment

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

Thank you for the PR @shyim. This is a good start!

I'd like us to follow the structure of https://github.com/getsentry/sentry-javascript/blob/develop/packages/cloudflare/src/d1.ts more closely here.

That means we need to

  1. Make sure we create breadcrumbs for SQL queries
  2. Link to bun docs wherever appropriate
  3. Extract out functions for createStartSpanOptions and createSpanAttributes

I understand thats a lot though (plus all of my review comments). Maybe we can start by creating a simple version of bunSqliteIntegration that just patches one method. Then we can implement the rest of the patching in a follow-up PR.

let hasPatchedBunSqlite = false;

export function _resetBunSqliteInstrumentation(): void {
hasPatchedBunSqlite = false;
Copy link
Member

Choose a reason for hiding this comment

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

We can remove this functionality, it doesn't actually reset the proxy implementation, so calling this will lead to the sql module getting patched multiple times.

construct(target, args) {
const instance = new target(...args);
if (args[0]) {
Object.defineProperty(instance, '_sentryDbName', {
Copy link
Member

Choose a reason for hiding this comment

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

Where is this being set?

It only seems to be defined, which would mean let dbName = this._sentryDbName || dbNameMap.get(this); would always evaluate dbNameMap.get(this)

op: `db.sql.statement.${method}`,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.bun.sqlite',
'db.system': 'sqlite',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
'db.system': 'sqlite',
'db.system.name': 'sqlite',

https://opentelemetry.io/docs/specs/semconv/registry/attributes/db/#db-system

Comment on lines +81 to +82
const inParentSpanMap = new WeakMap<any, boolean>();
const dbNameMap = new WeakMap<any, string>();
Copy link
Member

Choose a reason for hiding this comment

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

What do these maps do? Can we type them more stronger? Why are they WeakMap?

Comment on lines +93 to +98
let dbName = this._sentryDbName || dbNameMap.get(this);

if (!dbName && this.filename) {
dbName = this.filename;
dbNameMap.set(this, dbName);
}
Copy link
Member

Choose a reason for hiding this comment

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

Why do we have this logic?


return startSpan(
{
name: sql || 'db.sql.' + method,
Copy link
Member

Choose a reason for hiding this comment

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

In what cases is sql not defined? We should always try to make the span name the db statement.

op: `db.sql.${method}`,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.bun.sqlite',
'db.system': 'sqlite',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
'db.system': 'sqlite',
'db.system.name': 'sqlite',

https://opentelemetry.io/docs/specs/semconv/registry/attributes/db/#db-system

[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.bun.sqlite',
'db.system': 'sqlite',
'db.operation': method,
...(sql && { 'db.statement': sql }),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
...(sql && { 'db.statement': sql }),
...(sql && { 'db.query.text': sql }),

https://opentelemetry.io/docs/specs/semconv/registry/attributes/db/#db-statement

'db.system': 'sqlite',
'db.operation': method,
...(sql && { 'db.statement': sql }),
...(dbName && { 'db.name': dbName }),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
...(dbName && { 'db.name': dbName }),
...(dbName && { 'db.namespace': dbName }),

https://opentelemetry.io/docs/specs/semconv/registry/attributes/db/#db-name

return result;
} catch (error) {
span.setStatus({ code: 2, message: 'internal_error' });
captureException(error, {
Copy link
Member

Choose a reason for hiding this comment

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

We don't need to capture an error here, we can just let the error bubble up.

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