Skip to content
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

[mysql] Duplicate subsegments when using createPool().query #668

Open
dwickr opened this issue Jul 29, 2024 · 2 comments
Open

[mysql] Duplicate subsegments when using createPool().query #668

dwickr opened this issue Jul 29, 2024 · 2 comments

Comments

@dwickr
Copy link
Contributor

dwickr commented Jul 29, 2024

When using connection pools, the pool.query method can be called directly as a shortcut instead of calling pool.getConnection, then querying (doc):

[pool.query] is a shortcut for the pool.getConnection() -> connection.query() -> connection.release() code flow.

As a result, the subsegments for that query are duplicated because both pool.query and pool.getConnection().query have been captured to create subsegments, and both are called.

Here's an example:

const AWSXRay = require('aws-xray-sdk')

AWSXRay.captureMySQL(require('mysql2'))
const mysqlPromise = require('mysql2/promise')

const ns = AWSXRay.getNamespace()

async function testPromisePoolQuery() {
  try {
    const pool = mysqlPromise.createPool({
      host: 'localhost',
      user: 'user',
      password: 'password',
      database: 'test',
      connectionLimit: 10,
      queueLimit: 0,
    })

    await pool.query('SELECT 1')

    await pool.end()
  } catch (err) {
    console.error('Error connecting to database:', err)
  }
}

ns.run(async () => {
  let segment = new AWSXRay.Segment('testPromisePoolQuery')

  AWSXRay.setSegment(segment)
  await testPromisePoolQuery()
  console.log(
    `testPromisePoolQuery # of subsegments: ${AWSXRay.getSegment().subsegments?.length}`
  )
  segment.close()
})

The result printed from this is testPromisePoolQuery # of subsegments: 2, and if you view the subsegment you can see that the queries are the same, and timings are almost exactly the same.

@dwickr
Copy link
Contributor Author

dwickr commented Jul 30, 2024

I'm hacking around this by patching createPool before calling captureMySQL to prevent it from capturing pool.query and pool.execute. This way it only captures the connections returned from pool.getConnection within the query/execute calls.

function patchCreatePool(mysql: any) {
  mysql._createPool = mysql.createPool
  mysql.createPool = function (config: any) {
    const pool = mysql._createPool(config)

    pool.__query = () => {}
    pool.__execute = () => {}
    return pool
  }
  return mysql
}

@mxiamxia
Copy link
Contributor

mxiamxia commented Aug 1, 2024

Thanks for sharing the details and workaround. X-Ray team is prioritizing the support on OTel SDK where does not have the same problem. We currently not sure when/if we will fix this issue for the current SDK or not, sorry for the inconvenience.
https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/plugins/node/opentelemetry-instrumentation-mysql2/src/instrumentation.ts

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

No branches or pull requests

2 participants