From 179da70e845a9a09e8d27b550eb4b04cc3f0e96d Mon Sep 17 00:00:00 2001 From: Maarten Ackermans <4571935+mackermans@users.noreply.github.com> Date: Fri, 15 Jul 2022 15:52:27 +0200 Subject: [PATCH 1/8] add neo4j plugin --- .github/workflows/plugins.yml | 23 ++++ docker-compose.yml | 7 + docs/API.md | 4 + docs/test.ts | 1 + index.d.ts | 6 + .../datadog-instrumentations/src/neo4j.js | 100 ++++++++++++++ packages/datadog-plugin-neo4j/src/index.js | 49 +++++++ .../datadog-plugin-neo4j/test/index.spec.js | 125 ++++++++++++++++++ packages/dd-trace/src/plugins/index.js | 1 + .../dd-trace/test/setup/services/neo4j.js | 24 ++++ 10 files changed, 340 insertions(+) create mode 100644 packages/datadog-instrumentations/src/neo4j.js create mode 100644 packages/datadog-plugin-neo4j/src/index.js create mode 100644 packages/datadog-plugin-neo4j/test/index.spec.js create mode 100644 packages/dd-trace/test/setup/services/neo4j.js diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 2739b09a7e1..0af70a6baae 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -734,6 +734,29 @@ jobs: uses: ./.github/actions/testagent/logs - uses: codecov/codecov-action@v2 + neo4j: + runs-on: ubuntu-latest + services: + neo4j: + image: neo4j:4.2.3 + env: + NEO4J_AUTH: 'neo4j/test' + ports: + - 7474:7474 + - 11011:7687 + env: + PLUGINS: neo4j + SERVICES: neo4j + steps: + - uses: actions/checkout@v2 + - uses: ./.github/actions/node/setup + - run: yarn install + - uses: ./.github/actions/node/oldest + - run: yarn test:plugins:ci + - uses: ./.github/actions/node/latest + - run: yarn test:plugins:ci + - uses: codecov/codecov-action@v2 + net: runs-on: ubuntu-latest env: diff --git a/docker-compose.yml b/docker-compose.yml index ef86aab2730..eae2d97017e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,6 +82,13 @@ services: image: ghcr.io/ridedott/pubsub-emulator ports: - "127.0.0.1:8081:8081" + neo4j: + image: neo4j:4.2.3 + environment: + - NEO4J_AUTH=neo4j/test + ports: + - "7474:7474" + - "11011:7687" localstack: # TODO: Figure out why SNS doesn't work in >=1.2 # https://github.com/localstack/localstack/issues/7479 diff --git a/docs/API.md b/docs/API.md index 5902b284e60..105d9b8e462 100644 --- a/docs/API.md +++ b/docs/API.md @@ -76,6 +76,9 @@ tracer.use('pg', {
+
+
+
@@ -131,6 +134,7 @@ tracer.use('pg', { * [mongodb-core](./interfaces/plugins.mongodb_core.html) * [mysql](./interfaces/plugins.mysql.html) * [mysql2](./interfaces/plugins.mysql2.html) +* [neo4j](./interfaces/plugins.neo4j.html) * [net](./interfaces/plugins.net.html) * [next](./interfaces/plugins.next.html) * [opensearch](./interfaces/plugins.opensearch.html) diff --git a/docs/test.ts b/docs/test.ts index 1c81f92173b..2e260fa522f 100644 --- a/docs/test.ts +++ b/docs/test.ts @@ -315,6 +315,7 @@ tracer.use('mysql'); tracer.use('mysql', { service: () => `my-custom-mysql` }); tracer.use('mysql2'); tracer.use('mysql2', { service: () => `my-custom-mysql2` }); +tracer.use('neo4j'); tracer.use('net'); tracer.use('next'); tracer.use('next', nextOptions); diff --git a/index.d.ts b/index.d.ts index c0f4fabd964..b2376e53eab 100644 --- a/index.d.ts +++ b/index.d.ts @@ -827,6 +827,7 @@ interface Plugins { "mongoose": plugins.mongoose; "mysql": plugins.mysql; "mysql2": plugins.mysql2; + "neo4j": plugins.neo4j; "net": plugins.net; "next": plugins.next; "opensearch": plugins.opensearch; @@ -1483,6 +1484,11 @@ declare namespace plugins { * [mysql2](https://github.com/sidorares/node-mysql2) module. */ interface mysql2 extends mysql {} + /** + * This plugin automatically instruments the + * [neo4j](https://github.com/neo4j/neo4j-javascript-driver) module. + */ + interface neo4j extends Instrumentation {} /** * This plugin automatically instruments the diff --git a/packages/datadog-instrumentations/src/neo4j.js b/packages/datadog-instrumentations/src/neo4j.js new file mode 100644 index 00000000000..531c3584183 --- /dev/null +++ b/packages/datadog-instrumentations/src/neo4j.js @@ -0,0 +1,100 @@ +'use strict' + +const { + channel, + addHook, + AsyncResource +} = require('./helpers/instrument') +const shimmer = require('../../datadog-shimmer') + +const startCh = channel('apm:neo4j:query:start') +const finishCh = channel('apm:neo4j:query:finish') +const errorCh = channel('apm:neo4j:query:error') + +addHook({ name: 'neo4j-driver-core', file: 'lib/session.js', versions: ['>=4.3.0'] }, exports => { + const Session = exports.default + shimmer.wrap(Session.prototype, 'run', wrapRun) + return Session +}) + +addHook({ name: 'neo4j-driver-core', file: 'lib/transaction.js', versions: ['>=4.3.0'] }, exports => { + const Transaction = exports.default + shimmer.wrap(Transaction.prototype, 'run', wrapRun) + return Transaction +}) + +addHook({ name: 'neo4j-driver', file: 'lib/session.js', versions: ['<4.3.0', '>=4.0.0'] }, exports => { + const Session = exports.default + shimmer.wrap(Session.prototype, 'run', wrapRun) + return Session +}) +exports +addHook({ name: 'neo4j-driver', file: 'lib/transaction.js', versions: ['<4.3.0', '>=4.0.0'] }, exports => { + const Transaction = exports.default + shimmer.wrap(Transaction.prototype, 'run', wrapRun) + return Transaction +}) + +function wrapRun (run) { + return function (query) { + if (!startCh.hasSubscribers) { + return run.apply(this, arguments) + } + + if (!query) return run.apply(this, arguments) + + const asyncResource = new AsyncResource('bound-anonymous-fn') + const attributes = getAttributesFromNeo4jSession(this) + + return asyncResource.runInAsyncScope(() => { + startCh.publish({ attributes, query }) + + try { + const promise = run.apply(this, arguments) + if (promise && typeof promise.then === 'function') { + const onResolve = asyncResource.bind(() => finish()) + const onReject = asyncResource.bind(e => finish(e)) + + promise.then(onResolve, onReject) + } else { + finish() + } + return promise + } catch (err) { + err.stack // trigger getting the stack at the original throwing point + errorCh.publish(err) + + throw err + } + }) + } +} + +function finish (error) { + if (error) { + errorCh.publish(error) + } + finishCh.publish() +} + +function getAttributesFromNeo4jSession (session) { + const connectionHolder = + (session._mode === 'WRITE' ? session._writeConnectionHolder : session._readConnectionHolder) || + session._connectionHolder || + {} + const connectionProvider = connectionHolder._connectionProvider || {} + + // seedRouter is used when connecting to a url that starts with "neo4j", usually aura + const address = connectionProvider._address || connectionProvider._seedRouter + const auth = connectionProvider._authToken || {} + + const attributes = {} + if (address) { + attributes.host = address._host + attributes.port = address._port + } + if (auth.principal) { + attributes.user = auth.principal + } + return attributes +} diff --git a/packages/datadog-plugin-neo4j/src/index.js b/packages/datadog-plugin-neo4j/src/index.js new file mode 100644 index 00000000000..2a7fcd4802a --- /dev/null +++ b/packages/datadog-plugin-neo4j/src/index.js @@ -0,0 +1,49 @@ +'use strict' + +const Plugin = require('../../dd-trace/src/plugins/plugin') +const { storage } = require('../../datadog-core') +const analyticsSampler = require('../../dd-trace/src/analytics_sampler') + +class Neo4jPlugin extends Plugin { + static get name () { + return 'neo4j' + } + + constructor (...args) { + super(...args) + + this.addSub('apm:neo4j:query:start', ({ attributes, query }) => { + const store = storage.getStore() + const childOf = store ? store.span : store + const operation = query.trim().split(/\s+/)[0] + const span = this.tracer.startSpan('neo4j.query', { + childOf, + tags: { + 'service.name': this.config.service || `${this.tracer._service}-neo4j`, + 'span.kind': 'client', + 'span.type': 'cypher', + 'db.type': 'neo4j', + 'db.user': attributes.user, + 'out.host': attributes.host, + 'out.port': attributes.port, + 'neo4j.operation': operation, + 'neo4j.statement': query + } + }) + analyticsSampler.sample(span, this.config.measured) + this.enter(span, store) + }) + + this.addSub('apm:neo4j:query:error', err => { + const span = storage.getStore().span + span.setTag('error', err) + }) + + this.addSub('apm:neo4j:query:finish', () => { + const span = storage.getStore().span + span.finish() + }) + } +} + +module.exports = Neo4jPlugin diff --git a/packages/datadog-plugin-neo4j/test/index.spec.js b/packages/datadog-plugin-neo4j/test/index.spec.js new file mode 100644 index 00000000000..221330462f2 --- /dev/null +++ b/packages/datadog-plugin-neo4j/test/index.spec.js @@ -0,0 +1,125 @@ +'use strict' + +const agent = require('../../dd-trace/test/plugins/agent') + +describe('Plugin', () => { + let neo4j + let tracer + + withVersions('neo4j', ['neo4j-driver'], (version, moduleName) => { + const metaModule = require(`../../../versions/${moduleName}@${version}`) + + describe('neo4j', () => { + beforeEach(async () => { + tracer = await require('../../dd-trace') + }) + + describe('driver', () => { + let driver + + before(() => { + return agent.load('neo4j') + }) + + after(() => { + return agent.close({ ritmReset: false }) + }) + + beforeEach(async () => { + neo4j = metaModule.get() + + driver = neo4j.driver('bolt://localhost:11011', neo4j.auth.basic('neo4j', 'test'), { + disableLosslessIntegers: true + }) + + await driver.verifyConnectivity() + }) + + afterEach(async () => { + await driver.session().run('MATCH (n) DETACH DELETE n') + await driver.close() + }) + + describe('session', () => { + let session + + beforeEach(() => { + session = driver.session() + }) + + afterEach(async () => { + await session.close() + }) + + it('should set the correct tags', done => { + const statement = 'CREATE (n:Person { name: $name }) RETURN n.name' + + agent + .use(traces => { + const span = traces[0][0] + + expect(span).to.have.property('name', 'neo4j.query') + expect(span).to.have.property('service', 'test-neo4j') + expect(span).to.have.property('resource', 'neo4j.query') + expect(span).to.have.property('type', 'cypher') + expect(span.meta).to.have.property('span.kind', 'client') + expect(span.meta).to.have.property('db.type', 'neo4j') + expect(span.meta).to.have.property('db.user', 'neo4j') + expect(span.meta).to.have.property('out.host', 'localhost') + expect(span.meta).to.have.property('neo4j.operation', 'CREATE') + expect(span.meta).to.have.property('neo4j.statement', statement) + expect(span.metrics).to.have.property('out.port', 11011) + }) + .then(done) + .catch(done) + + session.run(statement, { name: 'Alice' }) + }) + + it('should propagate context', async () => { + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] + + expect(span).to.include({ + name: 'test-context', + service: 'test' + }) + + expect(span.parent_id).to.not.be.null + }) + + const span = tracer.startSpan('test-context') + + await tracer.scope().activate(span, async () => { + await session.run('MATCH (n) return n LIMIT 1') + await span.finish() + }) + await expectedSpanPromise + }) + + it('should handle errors', async () => { + let error + + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] + + expect(span.meta).to.have.property('error.type', error.name) + expect(span.meta).to.have.property('error.msg', error.message) + expect(span.meta).to.have.property('error.stack', error.stack) + }) + + try { + await session.run('NOT_EXISTS_OPERATION') + } catch (err) { + error = err + } + + await expectedSpanPromise + }) + }) + }) + }) + }) +}) diff --git a/packages/dd-trace/src/plugins/index.js b/packages/dd-trace/src/plugins/index.js index 979208dacfb..708cfb338e5 100644 --- a/packages/dd-trace/src/plugins/index.js +++ b/packages/dd-trace/src/plugins/index.js @@ -57,6 +57,7 @@ module.exports = { get 'mysql' () { return require('../../../datadog-plugin-mysql/src') }, get 'mysql2' () { return require('../../../datadog-plugin-mysql2/src') }, get 'net' () { return require('../../../datadog-plugin-net/src') }, + get 'neo4j' () {return require('../../../datadog-plugin-neo4j/src') }, get 'next' () { return require('../../../datadog-plugin-next/src') }, get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') }, get 'openai' () { return require('../../../datadog-plugin-openai/src') }, diff --git a/packages/dd-trace/test/setup/services/neo4j.js b/packages/dd-trace/test/setup/services/neo4j.js new file mode 100644 index 00000000000..e54014de4f6 --- /dev/null +++ b/packages/dd-trace/test/setup/services/neo4j.js @@ -0,0 +1,24 @@ +'use strict' + +const neo4j = require('../../../../../versions/neo4j-driver').get() +const RetryOperation = require('../operation') + +function waitForNeo4j () { + return new Promise((resolve, reject) => { + const operation = new RetryOperation('neo4j') + + operation.attempt(currentAttempt => { + const driver = neo4j.driver('bolt://localhost:11011', neo4j.auth.basic('neo4j', 'test')) + + driver.verifyConnectivity().then(() => { + driver.close() + resolve() + }).catch(err => { + if (operation.retry(err)) return + reject(err) + }) + }) + }) +} + +module.exports = waitForNeo4j From 7192b9aedbd32ea1b564d5a54d20b5d427f4f078 Mon Sep 17 00:00:00 2001 From: Maarten Ackermans <4571935+mackermans@users.noreply.github.com> Date: Tue, 26 Jul 2022 16:31:39 +0200 Subject: [PATCH 2/8] make neo4j tags more generic, set resource to query statement --- packages/datadog-instrumentations/src/neo4j.js | 15 +++++++++------ packages/datadog-plugin-neo4j/src/index.js | 15 +++++++-------- packages/datadog-plugin-neo4j/test/index.spec.js | 15 +++++++-------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/packages/datadog-instrumentations/src/neo4j.js b/packages/datadog-instrumentations/src/neo4j.js index 531c3584183..89b26db3892 100644 --- a/packages/datadog-instrumentations/src/neo4j.js +++ b/packages/datadog-instrumentations/src/neo4j.js @@ -28,7 +28,7 @@ addHook({ name: 'neo4j-driver', file: 'lib/session.js', versions: ['<4.3.0', '>= shimmer.wrap(Session.prototype, 'run', wrapRun) return Session }) -exports + addHook({ name: 'neo4j-driver', file: 'lib/transaction.js', versions: ['<4.3.0', '>=4.0.0'] }, exports => { const Transaction = exports.default shimmer.wrap(Transaction.prototype, 'run', wrapRun) @@ -36,18 +36,18 @@ addHook({ name: 'neo4j-driver', file: 'lib/transaction.js', versions: ['<4.3.0', }) function wrapRun (run) { - return function (query) { + return function (statement) { if (!startCh.hasSubscribers) { return run.apply(this, arguments) } - if (!query) return run.apply(this, arguments) + if (!statement) return run.apply(this, arguments) const asyncResource = new AsyncResource('bound-anonymous-fn') const attributes = getAttributesFromNeo4jSession(this) return asyncResource.runInAsyncScope(() => { - startCh.publish({ attributes, query }) + startCh.publish({ attributes, statement }) try { const promise = run.apply(this, arguments) @@ -88,13 +88,16 @@ function getAttributesFromNeo4jSession (session) { const address = connectionProvider._address || connectionProvider._seedRouter const auth = connectionProvider._authToken || {} - const attributes = {} + const attributes = { + // "neo4j" is the default database name. When used, "session._database" is an empty string + dbName: session._database ? session._database : 'neo4j' + } if (address) { attributes.host = address._host attributes.port = address._port } if (auth.principal) { - attributes.user = auth.principal + attributes.dbUser = auth.principal } return attributes } diff --git a/packages/datadog-plugin-neo4j/src/index.js b/packages/datadog-plugin-neo4j/src/index.js index 2a7fcd4802a..8296b47142e 100644 --- a/packages/datadog-plugin-neo4j/src/index.js +++ b/packages/datadog-plugin-neo4j/src/index.js @@ -12,22 +12,21 @@ class Neo4jPlugin extends Plugin { constructor (...args) { super(...args) - this.addSub('apm:neo4j:query:start', ({ attributes, query }) => { + this.addSub('apm:neo4j:query:start', ({ attributes, statement }) => { const store = storage.getStore() const childOf = store ? store.span : store - const operation = query.trim().split(/\s+/)[0] const span = this.tracer.startSpan('neo4j.query', { childOf, tags: { - 'service.name': this.config.service || `${this.tracer._service}-neo4j`, - 'span.kind': 'client', - 'span.type': 'cypher', + 'db.name': attributes.dbName, 'db.type': 'neo4j', - 'db.user': attributes.user, + 'db.user': attributes.dbUser, 'out.host': attributes.host, 'out.port': attributes.port, - 'neo4j.operation': operation, - 'neo4j.statement': query + 'resource.name': statement, + 'service.name': this.config.service || `${this.tracer._service}-neo4j`, + 'span.kind': 'client', + 'span.type': 'cypher' } }) analyticsSampler.sample(span, this.config.measured) diff --git a/packages/datadog-plugin-neo4j/test/index.spec.js b/packages/datadog-plugin-neo4j/test/index.spec.js index 221330462f2..a2a7256ab6f 100644 --- a/packages/datadog-plugin-neo4j/test/index.spec.js +++ b/packages/datadog-plugin-neo4j/test/index.spec.js @@ -51,29 +51,28 @@ describe('Plugin', () => { await session.close() }) - it('should set the correct tags', done => { + it('should set the correct tags', async () => { const statement = 'CREATE (n:Person { name: $name }) RETURN n.name' - agent + const expectedTagsPromise = agent .use(traces => { const span = traces[0][0] expect(span).to.have.property('name', 'neo4j.query') expect(span).to.have.property('service', 'test-neo4j') - expect(span).to.have.property('resource', 'neo4j.query') + expect(span).to.have.property('resource', statement) expect(span).to.have.property('type', 'cypher') expect(span.meta).to.have.property('span.kind', 'client') + expect(span.meta).to.have.property('db.name', 'neo4j') expect(span.meta).to.have.property('db.type', 'neo4j') expect(span.meta).to.have.property('db.user', 'neo4j') expect(span.meta).to.have.property('out.host', 'localhost') - expect(span.meta).to.have.property('neo4j.operation', 'CREATE') - expect(span.meta).to.have.property('neo4j.statement', statement) expect(span.metrics).to.have.property('out.port', 11011) }) - .then(done) - .catch(done) - session.run(statement, { name: 'Alice' }) + await session.run(statement, { name: 'Alice' }) + + await expectedTagsPromise }) it('should propagate context', async () => { From 128660701ec38f24528ecf693d3fb39720447839 Mon Sep 17 00:00:00 2001 From: Maarten Ackermans <4571935+mackermans@users.noreply.github.com> Date: Tue, 26 Jul 2022 16:32:29 +0200 Subject: [PATCH 3/8] add neo4j transaction tests --- .../datadog-plugin-neo4j/test/index.spec.js | 88 ++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/packages/datadog-plugin-neo4j/test/index.spec.js b/packages/datadog-plugin-neo4j/test/index.spec.js index a2a7256ab6f..f2deb169f31 100644 --- a/packages/datadog-plugin-neo4j/test/index.spec.js +++ b/packages/datadog-plugin-neo4j/test/index.spec.js @@ -33,10 +33,10 @@ describe('Plugin', () => { }) await driver.verifyConnectivity() + await driver.session().run('MATCH (n) DETACH DELETE n') }) afterEach(async () => { - await driver.session().run('MATCH (n) DETACH DELETE n') await driver.close() }) @@ -118,6 +118,92 @@ describe('Plugin', () => { await expectedSpanPromise }) }) + + describe('transaction', () => { + let session + + beforeEach(() => { + session = driver.session() + }) + + afterEach(async () => { + await session.close() + }) + + it('should set the correct tags', async () => { + const statement = 'MATCH (m:Movie { name: $name }) RETURN m.name' + + const expectedTagsPromise = agent + .use(traces => { + const span = traces[0][0] + + expect(span).to.have.property('name', 'neo4j.query') + expect(span).to.have.property('service', 'test-neo4j') + expect(span).to.have.property('resource', statement) + expect(span).to.have.property('type', 'cypher') + expect(span.meta).to.have.property('span.kind', 'client') + expect(span.meta).to.have.property('db.name', 'neo4j') + expect(span.meta).to.have.property('db.type', 'neo4j') + expect(span.meta).to.have.property('db.user', 'neo4j') + expect(span.meta).to.have.property('out.host', 'localhost') + expect(span.metrics).to.have.property('out.port', 11011) + }) + + const transaction = session.beginTransaction() + await transaction.run(statement, { name: 'Alice in Wonderland' }) + await transaction.commit() + + await expectedTagsPromise + }) + + it('should propagate context', async () => { + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] + + expect(span).to.include({ + name: 'test-context', + service: 'test' + }) + + expect(span.parent_id).to.not.be.null + }) + + const span = tracer.startSpan('test-context') + + await tracer.scope().activate(span, async () => { + const transaction = session.beginTransaction() + await transaction.run('MATCH (n) return n LIMIT 1') + await transaction.commit() + await span.finish() + }) + + await expectedSpanPromise + }) + + it('should handle errors', async () => { + let error + + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] + + expect(span.meta).to.have.property('error.type', error.name) + expect(span.meta).to.have.property('error.msg', error.message) + expect(span.meta).to.have.property('error.stack', error.stack) + }) + + try { + const transaction = session.beginTransaction() + await transaction.run('NOT_EXISTS_OPERATION') + await transaction.commit() + } catch (err) { + error = err + } + + await expectedSpanPromise + }) + }) }) }) }) From accd9f7d9095caddd4f6d815726a800141c7ba22 Mon Sep 17 00:00:00 2001 From: Atte Huhtakangas Date: Fri, 1 Sep 2023 09:26:28 +0100 Subject: [PATCH 4/8] fix: add missing neo4j hook --- packages/datadog-instrumentations/src/helpers/hooks.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/datadog-instrumentations/src/helpers/hooks.js b/packages/datadog-instrumentations/src/helpers/hooks.js index 4370822f18b..59bf4db0414 100644 --- a/packages/datadog-instrumentations/src/helpers/hooks.js +++ b/packages/datadog-instrumentations/src/helpers/hooks.js @@ -71,6 +71,7 @@ module.exports = { 'mongoose': () => require('../mongoose'), 'mysql': () => require('../mysql'), 'mysql2': () => require('../mysql2'), + 'neo4j': () => require('../neo4j'), 'net': () => require('../net'), 'next': () => require('../next'), 'oracledb': () => require('../oracledb'), From 5cf276dfec7c87bfeba5225e21634eba147b6725 Mon Sep 17 00:00:00 2001 From: Atte Huhtakangas Date: Fri, 1 Sep 2023 09:26:35 +0100 Subject: [PATCH 5/8] fix: formatting --- packages/dd-trace/src/plugins/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dd-trace/src/plugins/index.js b/packages/dd-trace/src/plugins/index.js index 708cfb338e5..cc2a971b5c3 100644 --- a/packages/dd-trace/src/plugins/index.js +++ b/packages/dd-trace/src/plugins/index.js @@ -57,7 +57,7 @@ module.exports = { get 'mysql' () { return require('../../../datadog-plugin-mysql/src') }, get 'mysql2' () { return require('../../../datadog-plugin-mysql2/src') }, get 'net' () { return require('../../../datadog-plugin-net/src') }, - get 'neo4j' () {return require('../../../datadog-plugin-neo4j/src') }, + get 'neo4j' () { return require('../../../datadog-plugin-neo4j/src') }, get 'next' () { return require('../../../datadog-plugin-next/src') }, get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') }, get 'openai' () { return require('../../../datadog-plugin-openai/src') }, From be89c3d9f7fda1a17753891f46d3843cb0d48b52 Mon Sep 17 00:00:00 2001 From: Atte Huhtakangas Date: Fri, 1 Sep 2023 09:28:57 +0100 Subject: [PATCH 6/8] fix: use storageplugin as base class --- packages/datadog-plugin-neo4j/src/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/datadog-plugin-neo4j/src/index.js b/packages/datadog-plugin-neo4j/src/index.js index 8296b47142e..7920fa5f9d4 100644 --- a/packages/datadog-plugin-neo4j/src/index.js +++ b/packages/datadog-plugin-neo4j/src/index.js @@ -1,10 +1,12 @@ 'use strict' -const Plugin = require('../../dd-trace/src/plugins/plugin') +const StoragePlugin = require('../../dd-trace/src/plugins/storage') const { storage } = require('../../datadog-core') const analyticsSampler = require('../../dd-trace/src/analytics_sampler') -class Neo4jPlugin extends Plugin { +class Neo4jPlugin extends StoragePlugin { + static get id () { return 'neo4j' } + static get system () { return 'neo4j' } static get name () { return 'neo4j' } From 34b31bc29ca3385255d8b436c80f17bbae68764e Mon Sep 17 00:00:00 2001 From: Maarten Ackermans <4571935+mackermans@users.noreply.github.com> Date: Wed, 13 Sep 2023 15:58:54 +0200 Subject: [PATCH 7/8] feat(plugin-neo4j): support for neo4j-driver up to 5.12.0 --- .github/workflows/plugins.yml | 6 +- docker-compose.yml | 6 +- .../src/helpers/hooks.js | 3 +- .../datadog-instrumentations/src/neo4j.js | 83 +++-- .../datadog-plugin-neo4j/test/index.spec.js | 298 +++++++++--------- packages/dd-trace/src/plugins/index.js | 3 +- packages/dd-trace/test/plugins/externals.json | 204 ++++++++---- .../dd-trace/test/setup/services/neo4j.js | 2 +- 8 files changed, 370 insertions(+), 235 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 0af70a6baae..11a8bff3d18 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -738,12 +738,12 @@ jobs: runs-on: ubuntu-latest services: neo4j: - image: neo4j:4.2.3 + image: neo4j:5.11.0 env: - NEO4J_AUTH: 'neo4j/test' + NEO4J_AUTH: 'neo4j/test-password' ports: - 7474:7474 - - 11011:7687 + - 7687:7687 env: PLUGINS: neo4j SERVICES: neo4j diff --git a/docker-compose.yml b/docker-compose.yml index eae2d97017e..cf58ab7776f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,12 +83,12 @@ services: ports: - "127.0.0.1:8081:8081" neo4j: - image: neo4j:4.2.3 + image: neo4j:5.11.0 environment: - - NEO4J_AUTH=neo4j/test + - NEO4J_AUTH=neo4j/test-password ports: - "7474:7474" - - "11011:7687" + - "7687:7687" localstack: # TODO: Figure out why SNS doesn't work in >=1.2 # https://github.com/localstack/localstack/issues/7479 diff --git a/packages/datadog-instrumentations/src/helpers/hooks.js b/packages/datadog-instrumentations/src/helpers/hooks.js index 59bf4db0414..ead2883fe3d 100644 --- a/packages/datadog-instrumentations/src/helpers/hooks.js +++ b/packages/datadog-instrumentations/src/helpers/hooks.js @@ -71,7 +71,8 @@ module.exports = { 'mongoose': () => require('../mongoose'), 'mysql': () => require('../mysql'), 'mysql2': () => require('../mysql2'), - 'neo4j': () => require('../neo4j'), + 'neo4j-driver': () => require('../neo4j'), + 'neo4j-driver-core': () => require('../neo4j'), 'net': () => require('../net'), 'next': () => require('../next'), 'oracledb': () => require('../oracledb'), diff --git a/packages/datadog-instrumentations/src/neo4j.js b/packages/datadog-instrumentations/src/neo4j.js index 89b26db3892..b6f09ab397e 100644 --- a/packages/datadog-instrumentations/src/neo4j.js +++ b/packages/datadog-instrumentations/src/neo4j.js @@ -11,29 +11,53 @@ const startCh = channel('apm:neo4j:query:start') const finishCh = channel('apm:neo4j:query:finish') const errorCh = channel('apm:neo4j:query:error') -addHook({ name: 'neo4j-driver-core', file: 'lib/session.js', versions: ['>=4.3.0'] }, exports => { - const Session = exports.default - shimmer.wrap(Session.prototype, 'run', wrapRun) - return Session -}) - -addHook({ name: 'neo4j-driver-core', file: 'lib/transaction.js', versions: ['>=4.3.0'] }, exports => { - const Transaction = exports.default - shimmer.wrap(Transaction.prototype, 'run', wrapRun) - return Transaction -}) - -addHook({ name: 'neo4j-driver', file: 'lib/session.js', versions: ['<4.3.0', '>=4.0.0'] }, exports => { - const Session = exports.default - shimmer.wrap(Session.prototype, 'run', wrapRun) - return Session -}) - -addHook({ name: 'neo4j-driver', file: 'lib/transaction.js', versions: ['<4.3.0', '>=4.0.0'] }, exports => { - const Transaction = exports.default - shimmer.wrap(Transaction.prototype, 'run', wrapRun) - return Transaction -}) +addHook( + { + name: 'neo4j-driver-core', + file: 'lib/session.js', + versions: ['>=4.3.0'] + }, + (exports) => { + shimmer.wrap(exports.default.prototype, 'run', wrapRun) + return exports + } +) + +addHook( + { + name: 'neo4j-driver-core', + file: 'lib/transaction.js', + versions: ['>=4.3.0'] + }, + (exports) => { + shimmer.wrap(exports.default.prototype, 'run', wrapRun) + return exports + } +) + +addHook( + { + name: 'neo4j-driver', + file: 'lib/session.js', + versions: ['>=4.0.0 <4.3.0'] + }, + (exports) => { + shimmer.wrap(exports.default.prototype, 'run', wrapRun) + return exports + } +) + +addHook( + { + name: 'neo4j-driver', + file: 'lib/transaction.js', + versions: ['>=4.0.0 <4.3.0'] + }, + (exports) => { + shimmer.wrap(exports.default.prototype, 'run', wrapRun) + return exports + } +) function wrapRun (run) { return function (statement) { @@ -86,7 +110,6 @@ function getAttributesFromNeo4jSession (session) { // seedRouter is used when connecting to a url that starts with "neo4j", usually aura const address = connectionProvider._address || connectionProvider._seedRouter - const auth = connectionProvider._authToken || {} const attributes = { // "neo4j" is the default database name. When used, "session._database" is an empty string @@ -96,8 +119,20 @@ function getAttributesFromNeo4jSession (session) { attributes.host = address._host attributes.port = address._port } + + // neo4j-driver <5.12.0 + const auth = connectionProvider._authToken || {} if (auth.principal) { attributes.dbUser = auth.principal } + + // neo4j-driver >=5.12.0 + const authProvider = connectionProvider._authenticationProvider || {} + const authTokenManager = authProvider._authTokenManager || {} + const authToken = authTokenManager._authToken || {} + if (authToken.principal) { + attributes.dbUser = authToken.principal + } + return attributes } diff --git a/packages/datadog-plugin-neo4j/test/index.spec.js b/packages/datadog-plugin-neo4j/test/index.spec.js index f2deb169f31..c3019f403c5 100644 --- a/packages/datadog-plugin-neo4j/test/index.spec.js +++ b/packages/datadog-plugin-neo4j/test/index.spec.js @@ -1,208 +1,212 @@ 'use strict' const agent = require('../../dd-trace/test/plugins/agent') +const { ERROR_MESSAGE, ERROR_STACK, ERROR_TYPE } = require('../../dd-trace/src/constants') describe('Plugin', () => { - let neo4j - let tracer - - withVersions('neo4j', ['neo4j-driver'], (version, moduleName) => { + withVersions('neo4j', ['neo4j-driver', 'neo4j-driver-core'], (version, moduleName) => { const metaModule = require(`../../../versions/${moduleName}@${version}`) describe('neo4j', () => { + let driver + let neo4j + let tracer + beforeEach(async () => { tracer = await require('../../dd-trace') - }) - describe('driver', () => { - let driver + await agent.load('neo4j') - before(() => { - return agent.load('neo4j') - }) + if (moduleName === 'neo4j-driver-core') { + neo4j = proxyquire(`../../../versions/neo4j-driver@${version}`, { + 'neo4j-driver-core': metaModule.get() + }).get() + } else { + neo4j = metaModule.get() + } - after(() => { - return agent.close({ ritmReset: false }) + driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'test-password'), { + disableLosslessIntegers: true }) - beforeEach(async () => { - neo4j = metaModule.get() + await driver.verifyConnectivity() + }) - driver = neo4j.driver('bolt://localhost:11011', neo4j.auth.basic('neo4j', 'test'), { - disableLosslessIntegers: true - }) + afterEach(async () => { + await driver.close() + await agent.close({ ritmReset: false }) + }) + + describe('session', () => { + let session - await driver.verifyConnectivity() - await driver.session().run('MATCH (n) DETACH DELETE n') + beforeEach(() => { + session = driver.session() }) afterEach(async () => { - await driver.close() + await session.close() }) - describe('session', () => { - let session + it('should set the correct tags', async () => { + const statement = 'CREATE (n:Person { name: $name }) RETURN n.name' - beforeEach(() => { - session = driver.session() - }) - - afterEach(async () => { - await session.close() - }) + const expectedTagsPromise = agent + .use(traces => { + const span = traces[0][0] - it('should set the correct tags', async () => { - const statement = 'CREATE (n:Person { name: $name }) RETURN n.name' - - const expectedTagsPromise = agent - .use(traces => { - const span = traces[0][0] - - expect(span).to.have.property('name', 'neo4j.query') - expect(span).to.have.property('service', 'test-neo4j') - expect(span).to.have.property('resource', statement) - expect(span).to.have.property('type', 'cypher') - expect(span.meta).to.have.property('span.kind', 'client') - expect(span.meta).to.have.property('db.name', 'neo4j') - expect(span.meta).to.have.property('db.type', 'neo4j') - expect(span.meta).to.have.property('db.user', 'neo4j') - expect(span.meta).to.have.property('out.host', 'localhost') - expect(span.metrics).to.have.property('out.port', 11011) + expect(span).to.include({ + name: 'neo4j.query', + service: 'test-neo4j', + resource: statement, + type: 'cypher' }) + expect(span.meta).to.include({ + 'span.kind': 'client', + 'db.name': 'neo4j', + 'db.type': 'neo4j', + 'db.user': 'neo4j', + 'out.host': 'localhost' + }) + expect(span.metrics).to.have.property('out.port', 7687) + }) - await session.run(statement, { name: 'Alice' }) - - await expectedTagsPromise - }) + await session.run(statement, { name: 'Alice' }) - it('should propagate context', async () => { - const expectedSpanPromise = agent - .use(traces => { - const span = traces[0][0] + await expectedTagsPromise + }) - expect(span).to.include({ - name: 'test-context', - service: 'test' - }) + it('should propagate context', async () => { + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] - expect(span.parent_id).to.not.be.null + expect(span).to.include({ + name: 'test-context', + service: 'test' }) - const span = tracer.startSpan('test-context') - - await tracer.scope().activate(span, async () => { - await session.run('MATCH (n) return n LIMIT 1') - await span.finish() + expect(span.parent_id).to.not.be.null }) - await expectedSpanPromise + + const span = tracer.startSpan('test-context') + + await tracer.scope().activate(span, async () => { + await session.run('MATCH (n) return n LIMIT 1') + await span.finish() }) + await expectedSpanPromise + }) - it('should handle errors', async () => { - let error + it('should handle errors', async () => { + let error - const expectedSpanPromise = agent - .use(traces => { - const span = traces[0][0] + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] - expect(span.meta).to.have.property('error.type', error.name) - expect(span.meta).to.have.property('error.msg', error.message) - expect(span.meta).to.have.property('error.stack', error.stack) - }) + expect(span.meta).to.have.property(ERROR_TYPE, error.name) + expect(span.meta).to.have.property(ERROR_MESSAGE, error.message) + expect(span.meta).to.have.property(ERROR_STACK, error.stack) + }) - try { - await session.run('NOT_EXISTS_OPERATION') - } catch (err) { - error = err - } + try { + await session.run('NOT_EXISTS_OPERATION') + } catch (err) { + error = err + } - await expectedSpanPromise - }) + await expectedSpanPromise }) + }) - describe('transaction', () => { - let session + describe('transaction', () => { + let session - beforeEach(() => { - session = driver.session() - }) + beforeEach(() => { + session = driver.session() + }) - afterEach(async () => { - await session.close() - }) + afterEach(async () => { + await session.close() + }) - it('should set the correct tags', async () => { - const statement = 'MATCH (m:Movie { name: $name }) RETURN m.name' - - const expectedTagsPromise = agent - .use(traces => { - const span = traces[0][0] - - expect(span).to.have.property('name', 'neo4j.query') - expect(span).to.have.property('service', 'test-neo4j') - expect(span).to.have.property('resource', statement) - expect(span).to.have.property('type', 'cypher') - expect(span.meta).to.have.property('span.kind', 'client') - expect(span.meta).to.have.property('db.name', 'neo4j') - expect(span.meta).to.have.property('db.type', 'neo4j') - expect(span.meta).to.have.property('db.user', 'neo4j') - expect(span.meta).to.have.property('out.host', 'localhost') - expect(span.metrics).to.have.property('out.port', 11011) - }) + it('should set the correct tags', async () => { + const statement = 'MATCH (m:Movie { name: $name }) RETURN m.name' - const transaction = session.beginTransaction() - await transaction.run(statement, { name: 'Alice in Wonderland' }) - await transaction.commit() + const expectedTagsPromise = agent + .use(traces => { + const span = traces[0][0] - await expectedTagsPromise - }) + expect(span).to.include({ + name: 'neo4j.query', + service: 'test-neo4j', + resource: statement, + type: 'cypher' + }) + expect(span.meta).to.include({ + 'span.kind': 'client', + 'db.name': 'neo4j', + 'db.type': 'neo4j', + 'db.user': 'neo4j', + 'out.host': 'localhost' + }) + expect(span.metrics).to.have.property('out.port', 7687) + }) - it('should propagate context', async () => { - const expectedSpanPromise = agent - .use(traces => { - const span = traces[0][0] + const transaction = session.beginTransaction() + await transaction.run(statement, { name: 'Alice in Wonderland' }) + await transaction.commit() - expect(span).to.include({ - name: 'test-context', - service: 'test' - }) + await expectedTagsPromise + }) - expect(span.parent_id).to.not.be.null - }) + it('should propagate context', async () => { + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] - const span = tracer.startSpan('test-context') + expect(span).to.include({ + name: 'test-context', + service: 'test' + }) - await tracer.scope().activate(span, async () => { - const transaction = session.beginTransaction() - await transaction.run('MATCH (n) return n LIMIT 1') - await transaction.commit() - await span.finish() + expect(span.parent_id).to.not.be.null }) - await expectedSpanPromise + const span = tracer.startSpan('test-context') + + await tracer.scope().activate(span, async () => { + const transaction = session.beginTransaction() + await transaction.run('MATCH (n) return n LIMIT 1') + await transaction.commit() + await span.finish() }) - it('should handle errors', async () => { - let error + await expectedSpanPromise + }) + + it('should handle errors', async () => { + let error - const expectedSpanPromise = agent - .use(traces => { - const span = traces[0][0] + const expectedSpanPromise = agent + .use(traces => { + const span = traces[0][0] - expect(span.meta).to.have.property('error.type', error.name) - expect(span.meta).to.have.property('error.msg', error.message) - expect(span.meta).to.have.property('error.stack', error.stack) - }) + expect(span.meta).to.have.property(ERROR_TYPE, error.name) + expect(span.meta).to.have.property(ERROR_MESSAGE, error.message) + expect(span.meta).to.have.property(ERROR_STACK, error.stack) + }) - try { - const transaction = session.beginTransaction() - await transaction.run('NOT_EXISTS_OPERATION') - await transaction.commit() - } catch (err) { - error = err - } + try { + const transaction = session.beginTransaction() + await transaction.run('NOT_EXISTS_OPERATION') + await transaction.commit() + } catch (err) { + error = err + } - await expectedSpanPromise - }) + await expectedSpanPromise }) }) }) diff --git a/packages/dd-trace/src/plugins/index.js b/packages/dd-trace/src/plugins/index.js index cc2a971b5c3..aa837dbbf18 100644 --- a/packages/dd-trace/src/plugins/index.js +++ b/packages/dd-trace/src/plugins/index.js @@ -56,8 +56,9 @@ module.exports = { get 'mongodb-core' () { return require('../../../datadog-plugin-mongodb-core/src') }, get 'mysql' () { return require('../../../datadog-plugin-mysql/src') }, get 'mysql2' () { return require('../../../datadog-plugin-mysql2/src') }, + get 'neo4j-driver' () { return require('../../../datadog-plugin-neo4j/src') }, + get 'neo4j-driver-core' () { return require('../../../datadog-plugin-neo4j/src') }, get 'net' () { return require('../../../datadog-plugin-net/src') }, - get 'neo4j' () { return require('../../../datadog-plugin-neo4j/src') }, get 'next' () { return require('../../../datadog-plugin-next/src') }, get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') }, get 'openai' () { return require('../../../datadog-plugin-openai/src') }, diff --git a/packages/dd-trace/test/plugins/externals.json b/packages/dd-trace/test/plugins/externals.json index 4284b1272e8..6f8cdb04317 100644 --- a/packages/dd-trace/test/plugins/externals.json +++ b/packages/dd-trace/test/plugins/externals.json @@ -2,173 +2,252 @@ "aws-sdk": [ { "name": "@aws-sdk/client-lambda", - "versions": [">=3"] + "versions": [ + ">=3" + ] }, { "name": "@aws-sdk/client-kinesis", - "versions": [">=3"] + "versions": [ + ">=3" + ] }, { "name": "@aws-sdk/client-s3", - "versions": [">=3"] + "versions": [ + ">=3" + ] }, { "name": "@aws-sdk/client-sns", - "versions": [">=3"] + "versions": [ + ">=3" + ] }, { "name": "@aws-sdk/client-sqs", - "versions": [">=3"] + "versions": [ + ">=3" + ] }, { "name": "@aws-sdk/node-http-handler", - "versions": [">=3"] + "versions": [ + ">=3" + ] } ], "cypress": [ { "name": "cypress", - "versions": [">=6.7.0"] + "versions": [ + ">=6.7.0" + ] } ], "express": [ { "name": "loopback", - "versions": [">=2.38.1"] + "versions": [ + ">=2.38.1" + ] }, { "name": "cookie-parser", - "versions": [">=1.4.6"] + "versions": [ + ">=1.4.6" + ] } ], "fastify": [ { "name": "fastify", - "versions": ["2.15.0", "3.0.0", "3.9.2"] + "versions": [ + "2.15.0", + "3.0.0", + "3.9.2" + ] }, { "name": "middie", - "versions": ["5.1.0"] + "versions": [ + "5.1.0" + ] } ], "generic-pool": [ { "name": "generic-pool", - "versions": [">=3"] + "versions": [ + ">=3" + ] } ], "google-cloud-pubsub": [ { "name": "google-gax", - "versions": ["3.5.7"] + "versions": [ + "3.5.7" + ] } ], "graphql": [ { "name": "apollo-server-core", - "versions": ["1.3.6"] + "versions": [ + "1.3.6" + ] }, { "name": "graphql-tools", - "versions": ["3.1.1"] + "versions": [ + "3.1.1" + ] } ], "grpc": [ { "name": "@grpc/proto-loader", - "versions": ["0.5.0"] + "versions": [ + "0.5.0" + ] } ], "hapi": [ { "name": "@hapi/boom", - "versions": ["9.1.4"] + "versions": [ + "9.1.4" + ] } ], "jest": [ { "name": "jest", - "versions": [">=24.8.0"] + "versions": [ + ">=24.8.0" + ] }, { "name": "jest-environment-jsdom", - "versions": [">=24.8.0"] + "versions": [ + ">=24.8.0" + ] }, { "name": "jest-environment-node", - "versions": [">=24.8.0"] + "versions": [ + ">=24.8.0" + ] }, { "name": "jest-circus", - "versions": [">=24.8.0"] + "versions": [ + ">=24.8.0" + ] }, { "name": "@jest/globals", - "versions": [">=26.5.0"] + "versions": [ + ">=26.5.0" + ] } ], "knex": [ { "name": "pg", - "versions": ["8.7.3"] + "versions": [ + "8.7.3" + ] } ], "koa": [ { "name": "koa-route", - "versions": [">=3.2"] + "versions": [ + ">=3.2" + ] }, { "name": "koa-websocket", - "versions": ["5.0.1"] + "versions": [ + "5.0.1" + ] }, { "name": "ws", - "versions": ["6.1.0"] + "versions": [ + "6.1.0" + ] } ], "ldapjs": [ { "name": "ldapjs", - "versions": [">= 2"] + "versions": [ + ">= 2" + ] }, { "name": "ldapjs-promise", - "versions": [">=2"] + "versions": [ + ">=2" + ] } ], "mariadb": [ { "name": "mariadb", - "versions": ["2.5.6", "3.0.0"] + "versions": [ + "2.5.6", + "3.0.0" + ] } ], "mocha": [ { "name": "mocha", - "versions": [">=5.2.0"] + "versions": [ + ">=5.2.0" + ] }, { "name": "mocha-each", - "versions": [">=2.0.1"] + "versions": [ + ">=2.0.1" + ] } ], "moleculer": [ { "name": "bluebird", - "versions": ["3.7.2"] + "versions": [ + "3.7.2" + ] } ], "mongodb-core": [ { "name": "bson", - "versions": ["4.0.0"] + "versions": [ + "4.0.0" + ] } ], "mongoose": [ { "name": "mongodb-core", - "versions": ["3.2.7"] + "versions": [ + "3.2.7" + ] + } + ], + "neo4j": [ + { + "name": "neo4j-driver", + "versions": [ + ">=4.3.0" + ] } ], "next": [ @@ -181,48 +260,63 @@ "dep": true } ], - "passport-http": [ - { - "name": "passport", - "versions": [">=0.4.1"] - }, - { - "name": "express", - "versions": [">=4.16.2"] - } - ], - "passport-local": [ + "passport-http": [ { "name": "passport", - "versions": [">=0.4.1"] + "versions": [ + ">=0.4.1" + ] }, - { - "name": "express", - "versions": [">=4.16.2"] - } - + { + "name": "express", + "versions": [ + ">=4.16.2" + ] + } + ], + "passport-local": [ + { + "name": "passport", + "versions": [ + ">=0.4.1" + ] + }, + { + "name": "express", + "versions": [ + ">=4.16.2" + ] + } ], "pg": [ { "name": "pg-native", - "versions": ["3.0.0"] + "versions": [ + "3.0.0" + ] } ], "pino": [ { "name": "pino-pretty", "dep": true, - "versions": ["8.0.0"] + "versions": [ + "8.0.0" + ] } ], "q": [ { "name": "collections", - "versions": ["5"] + "versions": [ + "5" + ] }, { "name": "q", - "versions": ["2"] + "versions": [ + "2" + ] } ] } diff --git a/packages/dd-trace/test/setup/services/neo4j.js b/packages/dd-trace/test/setup/services/neo4j.js index e54014de4f6..042bdd1bb26 100644 --- a/packages/dd-trace/test/setup/services/neo4j.js +++ b/packages/dd-trace/test/setup/services/neo4j.js @@ -8,7 +8,7 @@ function waitForNeo4j () { const operation = new RetryOperation('neo4j') operation.attempt(currentAttempt => { - const driver = neo4j.driver('bolt://localhost:11011', neo4j.auth.basic('neo4j', 'test')) + const driver = neo4j.driver('bolt://localhost:7687', neo4j.auth.basic('neo4j', 'test-password')) driver.verifyConnectivity().then(() => { driver.close() From eb119ba481a5f2f9f4a4e216a14a9e018984786d Mon Sep 17 00:00:00 2001 From: Erik van Brakel <111406+erikvanbrakel@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:59:48 +0200 Subject: [PATCH 8/8] codeowners --- CODEOWNERS | 1 - 1 file changed, 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 570f1903d13..e69de29bb2d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +0,0 @@ -* @DataDog/dd-trace-js