dd-trace-js icon indicating copy to clipboard operation
dd-trace-js copied to clipboard

Express hook not called when using ES modules

Open AlexMetroDigital opened this issue 3 years ago • 7 comments

Describe the bug

When using esm the express request hook is not getting called. Whereas when using CommonJS the hook gets called as expected.

Minimal example for reproduction

index.ts

import './tracer.js'
import express from 'express'

const app = express()

app.get(
    '/foo',
    (req, res) => {
        (req as any).foo = 'bar'
        return res.send('bar')
    }
)

app.listen(8080, () => {
    console.log('App started at port 8080')
})

tracer.ts

import tracer from 'dd-trace'

tracer.init()

tracer.use('express', {
    hooks: {
        request: (span, req, _) => {
            console.log(`express hook: ${(req as any)?.foo}`)
            span?.setTag('test', (req as any)?.foo)
        },
    },
})

export default tracer

tsconfig.json

{
    "compilerOptions": {
        "module": "ESNext",
        "moduleResolution": "node",
        "strict": true,
        "esModuleInterop": true,
    }
}

package.json

{
  "name": "ddtrace-hook",
  "version": "0.1",
  "main": "index.ts",
  "private": true,
  "type": "module",
  "engines": {
    "node": "^16.0.0"
  },
  "scripts": {
    "server": "node --loader ts-node/esm ./index.ts"
  },
  "dependencies": {
    "dd-trace": "^2.2.0",
    "express": "^4.17.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.13",
    "ts-node": "^10.4.0",
    "typescript": "^4.5.4"
  }
}

Use Case

I want to use the hook to add request specific tags to every request. I also tried to create an express middleware for this, but it seems there is no public api to get the local root span (express.request)

Environment

  • Operation system: macOs BigSur
  • Node version: 16.13.2
  • Tracer version: 2.2.0

AlexMetroDigital avatar Feb 22 '22 12:02 AlexMetroDigital

Support for ESM requires using our loader on the CLI instead of ts-node/esm. It's also worth noting that it's currently experimental and has known issues with some libraries.

rochdev avatar Feb 22 '22 20:02 rochdev

You can use our experimental ESM support by using the following command-line flag:

--loader=dd-trace/loader-hook.mjs

Please let us know in this thread if that resolves this for you.

bengl avatar Feb 23 '22 19:02 bengl

Hi, thanks for your feedback! I tried adding the the hook, unfortunately without success. I also switched to plain JavaScript to avoid the need for the ts-node loader altogether.

AlexMetroDigital avatar Feb 24 '22 10:02 AlexMetroDigital

Can you share the new code without TypeScript and with our loader hook? Also, depending on the Node version, the option can be --experimental-loader instead of --loader, although I doubt this would be the issue since you were already using a loader hook.

rochdev avatar Feb 24 '22 22:02 rochdev

Sure, I am using node v16.13.2, here is my JS code: index.js

import './tracer.js'
import express from 'express'

const app = express()

app.get(
    '/foo',
    (req, res) => {
        req.foo = 'bar'
        return res.send('bar')
    }
)

app.listen(8080, () => {
    console.log('App started at port 8080')
})

tracer.ts

import tracer from 'dd-trace'

tracer.init()

tracer.use('express', {
    hooks: {
        request: (span, req, _) => {
            console.log(`express hook: ${req?.foo}`)
            span?.setTag('test', req?.foo)
        },
    },
})

export default tracer

package.json

{
  "name": "ddtrace-hook",
  "version": "0.1",
  "main": "index.js",
  "private": true,
  "type": "module",
  "engines": {
    "node": "^16.0.0"
  },
  "scripts": {
    "server": "node --loader dd-trace/loader-hook.mjs ./index.js"
  },
  "dependencies": {
    "dd-trace": "^2.2.0",
    "express": "^4.17.2"
  }
}

I also tried using --experimental-loader to be sure, but without effect.

AlexMetroDigital avatar Feb 28 '22 09:02 AlexMetroDigital

Tried this locally and there is definitely a bug. A workaround for now is to put tracer.use() above tracer.init() which seems to fix it at least in the above code.

rochdev avatar Mar 01 '22 23:03 rochdev

Thanks a lot for the workaround! Tried it out also in our actual projects and it seems to work now :)

AlexMetroDigital avatar Mar 02 '22 10:03 AlexMetroDigital

Hi @AlexMetroDigital I've just retested the provided .ts and .js code and everything seems to be working, so I'am going to close the issue. Please feel free to reopen another issue if your issue still persists

khanayan123 avatar Aug 30 '23 14:08 khanayan123

Can you add this in the README? Because it seems like the loader still is required for projects using ESM. May be related to https://github.com/DataDog/dd-trace-js/issues/4037 but very hard to trace to this as the root cause when all you get is a cryptic error like 2024-02-08 00:24:32 [server] error: TypeError: Cannot read properties of undefined (reading 'length').

suhjohn avatar Feb 08 '24 01:02 suhjohn

Actually, doesn't work. --loader dd-trace/loader-hook.mjs crashes the application for express 4.18 on node 18.

suhjohn avatar Feb 08 '24 01:02 suhjohn