From 9701ba1aeff5f0f41b46be697c2218b97917d185 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 13 Dec 2023 11:16:57 +0530 Subject: [PATCH 01/16] Remove graceful shutdown for the metrics server --- src/OpenAPM.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index ad3cf4f..e87eed9 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -165,20 +165,6 @@ export class OpenAPM extends LevitateEvents { ); }; - private gracefullyShutdownMetricsServer = () => { - this.metricsServer?.close((err) => { - promClient.register.clear(); - console.log('Shutting down metrics server.'); - if (err) { - console.error('Error while shutting down the metrics server:', err); - process.exit(1); - } else { - console.log('Metrics server shut down gracefully.'); - process.exit(0); - } - }); - }; - private initiateMetricsRoute = () => { // Creating native http server this.metricsServer = http.createServer(async (req, res) => { @@ -197,8 +183,6 @@ export class OpenAPM extends LevitateEvents { this.metricsServer?.listen(this.metricsServerPort, () => { console.log(`Metrics server running at ${this.metricsServerPort}`); }); - process.on('SIGINT', this.gracefullyShutdownMetricsServer); - process.on('SIGTERM', this.gracefullyShutdownMetricsServer); }; private parseLabelsFromParams = ( From 996df729263881e8348434843fb646a9859b7061 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 13 Dec 2023 13:33:55 +0530 Subject: [PATCH 02/16] 0.5.1-alpha.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd3759c..86555ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.5.0", + "version": "0.5.1-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.5.0", + "version": "0.5.1-alpha.1", "license": "Apache-2.0", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index c849bb8..1ed4eed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.5.0", + "version": "0.5.1-alpha.1", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From bc1149b000329eb86e22b06e2ba5bbc0df06aa7e Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 20 Dec 2023 15:46:51 +0530 Subject: [PATCH 03/16] Instrument 'pg' package query function --- package-lock.json | 451 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 + playground/app.js | 47 +++-- src/OpenAPM.ts | 10 +- src/clients/pg.ts | 61 +++++++ tsup.config.ts | 2 +- 6 files changed, 555 insertions(+), 21 deletions(-) create mode 100644 src/clients/pg.ts diff --git a/package-lock.json b/package-lock.json index 86555ea..b9d5af1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@types/express": "^4.17.17", "@types/mysql2": "github:types/mysql2", "@types/node": "^20.4.4", + "@types/pg": "^8.10.9", "@types/response-time": "^2.3.5", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", @@ -39,6 +40,7 @@ "mysql2": "^3.6.0", "node-fetch": "^3.3.1", "parse-prometheus-text-format": "^1.1.1", + "pg": "^8.11.3", "prettier": "2.8.8", "supertest": "^6.3.3", "ts-node": "^10.9.1", @@ -59,6 +61,9 @@ }, "mysql2": { "optional": true + }, + "pg": { + "optional": true } } }, @@ -2820,6 +2825,74 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/pg": { + "version": "8.10.9", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.9.tgz", + "integrity": "sha512-UksbANNE/f8w0wOMxVKKIrLCbEMV+oM1uKejmwXr39olg4xqcfBDbXxObJAt6XxHbDa4XTKOlUEcEltXDX+XLQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@types/pg/node_modules/pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "dev": true, + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/pg/node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/pg/node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dev": true, + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/pg/node_modules/postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/pg/node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@types/qs": { "version": "6.9.9", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", @@ -3736,6 +3809,15 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -6638,6 +6720,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -6729,6 +6817,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6822,6 +6916,106 @@ "node": "*" } }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dev": true, + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "dev": true, + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "dev": true + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "dev": true, + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", + "dev": true + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dev": true, + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dev": true, + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -6917,6 +7111,51 @@ } } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dev": true, + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-range": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", + "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -7575,6 +7814,15 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, "node_modules/sqlstring": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", @@ -8689,6 +8937,15 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -10541,6 +10798,61 @@ "undici-types": "~5.26.4" } }, + "@types/pg": { + "version": "8.10.9", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.9.tgz", + "integrity": "sha512-UksbANNE/f8w0wOMxVKKIrLCbEMV+oM1uKejmwXr39olg4xqcfBDbXxObJAt6XxHbDa4XTKOlUEcEltXDX+XLQ==", + "dev": true, + "requires": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + }, + "dependencies": { + "pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "dev": true, + "requires": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + } + }, + "postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "dev": true + }, + "postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dev": true, + "requires": { + "obuf": "~1.1.2" + } + }, + "postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "dev": true + }, + "postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "dev": true + } + } + }, "@types/qs": { "version": "6.9.9", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", @@ -11203,6 +11515,12 @@ "update-browserslist-db": "^1.0.13" } }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "dev": true + }, "builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -13333,6 +13651,12 @@ "es-abstract": "^1.22.1" } }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -13397,6 +13721,12 @@ "p-limit": "^3.0.2" } }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13469,6 +13799,82 @@ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dev": true, + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-cloudflare": "^1.1.1", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "dev": true, + "optional": true + }, + "pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "dev": true + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "dev": true + }, + "pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "dev": true + }, + "pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "dev": true, + "requires": {} + }, + "pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", + "dev": true + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dev": true, + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dev": true, + "requires": { + "split2": "^4.1.0" + } + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -13519,6 +13925,39 @@ "yaml": "^2.1.1" } }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "dev": true + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "dev": true + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "dev": true + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "postgres-range": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", + "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -13999,6 +14438,12 @@ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", "dev": true }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true + }, "sqlstring": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", @@ -14747,6 +15192,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/package.json b/package.json index 1ed4eed..9f35816 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@types/express": "^4.17.17", "@types/mysql2": "github:types/mysql2", "@types/node": "^20.4.4", + "@types/pg": "^8.10.9", "@types/response-time": "^2.3.5", "@typescript-eslint/eslint-plugin": "^5.61.0", "@typescript-eslint/parser": "^5.61.0", @@ -49,6 +50,7 @@ "mysql2": "^3.6.0", "node-fetch": "^3.3.1", "parse-prometheus-text-format": "^1.1.1", + "pg": "^8.11.3", "prettier": "2.8.8", "supertest": "^6.3.3", "ts-node": "^10.9.1", @@ -73,6 +75,9 @@ }, "express": { "optional": true + }, + "pg": { + "optional": true } }, "directories": { diff --git a/playground/app.js b/playground/app.js index 49ee438..a7ecb94 100644 --- a/playground/app.js +++ b/playground/app.js @@ -6,7 +6,8 @@ require('dotenv').config(); var express = require('express'); var { OpenAPM } = require('../dist/index.js'); -var mysql2 = require('mysql2'); +var pg = require('pg'); +// var mysql2 = require('mysql2'); const openapm = new OpenAPM({ extractLabels: { @@ -28,27 +29,34 @@ const openapm = new OpenAPM({ }); openapm.instrument('express'); -openapm.instrument('mysql'); +openapm.instrument('postgres'); const app = express(); +let client; +// const pool = mysql2.createPool( +// `mysql://express-app:password@127.0.0.1/express` // If this throws an error, Change the db url to the one you're running on your machine locally or the testing instance you might have hosted. +// ); -const pool = mysql2.createPool( - `mysql://express-app:password@127.0.0.1/express` // If this throws an error, Change the db url to the one you're running on your machine locally or the testing instance you might have hosted. -); +app.get('/result', async (req, res) => { + // pool.getConnection((err, conn) => { + // conn.query( + // { + // sql: 'SELECT SLEEP(RAND() * 10)' + // }, + // (...args) => { + // console.log(args); + // } + // ); + // }); + // await client.query(`INSERT INTO "users" (username) VALUES ('JohnDoe');`); + let result; + try { + result = await client.query('select * from users;'); + } catch (error) {} -app.get('/result', (req, res) => { - pool.getConnection((err, conn) => { - conn.query( - { - sql: 'SELECT SLEEP(RAND() * 10)' - }, - (...args) => { - console.log(args); - } - ); + res.status(200).json({ + users: result?.rows }); - - res.status(200).json({}); }); app.get('/organizations/:org/users', (req, res) => { @@ -61,6 +69,9 @@ app.get('/cancel/:ids', (req, res) => { res.status(200).json({}); }); -const server = app.listen(3000, () => { +const server = app.listen(3000, async () => { + client = new pg.Client('postgresql://tester:password@localhost:5432/testdb'); // If this throws an error, Change the db url to the one you're running on your machine locally or the testing instance you might have hosted. + + await client.connect(); console.log('serving at 3000'); }); diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index e87eed9..5a856c0 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -23,6 +23,7 @@ import { instrumentExpress } from './clients/express'; import { instrumentMySQL } from './clients/mysql2'; import { instrumentNestFactory } from './clients/nestjs'; import { LevitateConfig, LevitateEvents } from './levitate/events'; +import { instrumentPG } from './clients/pg'; export type ExtractFromParams = { from: 'params'; @@ -66,12 +67,13 @@ export interface OpenAPMOptions { levitateConfig?: LevitateConfig; } -export type SupportedModules = 'express' | 'mysql' | 'nestjs'; +export type SupportedModules = 'express' | 'mysql' | 'nestjs' | 'postgres'; const moduleNames = { express: 'express', mysql: 'mysql2', - nestjs: '@nestjs/core' + nestjs: '@nestjs/core', + postgres: 'pg' }; const packageJson = getPackageJson(); @@ -298,6 +300,10 @@ export class OpenAPM extends LevitateEvents { const { NestFactory } = require('@nestjs/core'); instrumentNestFactory(NestFactory, this._REDMiddleware); } + if (moduleName === 'postgres') { + const pg = require('pg'); + instrumentPG(pg); + } } catch (error) { if (Object.keys(moduleNames).includes(moduleName)) { console.log(error); diff --git a/src/clients/pg.ts b/src/clients/pg.ts new file mode 100644 index 0000000..21ee1f5 --- /dev/null +++ b/src/clients/pg.ts @@ -0,0 +1,61 @@ +import type * as PG from 'pg'; +import promClient from 'prom-client'; +import type OpenAPM from '../OpenAPM'; +import { wrap } from '../shimmer'; + +export const instrumentPG = (pg: typeof PG | { default: typeof PG }) => { + const histogram = new promClient.Histogram({ + name: 'db_requests_duration_milliseconds', + help: 'Duration of DB transactions in milliseconds', + labelNames: ['database_name', 'query', 'status'], + buckets: promClient.exponentialBuckets(0.25, 1.5, 31) + }); + + const pgModule = // @ts-ignore + (pg?.[Symbol.toStringTag] === 'Module' ? pg.default : pg) as typeof PG; + + // wrap( + // pgModule.Client.prototype, + // 'connect', + // (original: PG.Client['connect']) => { + // return async function ( + // this: PG.Client['connect'], + // ...args: Parameters + // ) { + // const result = await original.apply(this, args); + // return result; + // } as PG.Client['connect']; + // } + // ); + + wrap(pgModule.Client.prototype, 'query', (original: PG.Client['query']) => { + return async function ( + this: PG.Client['query'], + ...args: Parameters + ) { + let query = ''; + if (typeof args[0] === 'string') { + query = args[0]; + } else if (typeof args[0] === 'object') { + // @ts-ignore + query = args[0]?.text; + } + const end = histogram.startTimer({ + query: query, + database_name: '[db-name]' + }); + try { + const result = await original.apply(this, args); + end({ + status: 'success' + }); + return result; + } catch (error) { + end({ + status: 'failure' + }); + throw error; + } + } as PG.Client['query']; + }); +}; diff --git a/tsup.config.ts b/tsup.config.ts index 5e6fa1f..e3b7c31 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -9,6 +9,6 @@ export default defineConfig({ minify: true, treeshake: true, shims: true, - external: ['mysql2', '@nestjs/core'], + external: ['mysql2', '@nestjs/core', 'pg'], dts: true }); From b7a0da94ac0948a773aea6dfd182de57e686dc14 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Thu, 21 Dec 2023 17:47:32 +0530 Subject: [PATCH 04/16] Get database name from the connectionParameters --- src/clients/pg.ts | 28 ++++++++++------------------ src/shimmer.ts | 4 ++-- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/clients/pg.ts b/src/clients/pg.ts index 21ee1f5..ffdbd7b 100644 --- a/src/clients/pg.ts +++ b/src/clients/pg.ts @@ -1,7 +1,7 @@ import type * as PG from 'pg'; import promClient from 'prom-client'; -import type OpenAPM from '../OpenAPM'; import { wrap } from '../shimmer'; +import { maskValuesInSQLQuery } from '../utils'; export const instrumentPG = (pg: typeof PG | { default: typeof PG }) => { const histogram = new promClient.Histogram({ @@ -14,23 +14,13 @@ export const instrumentPG = (pg: typeof PG | { default: typeof PG }) => { const pgModule = // @ts-ignore (pg?.[Symbol.toStringTag] === 'Module' ? pg.default : pg) as typeof PG; - // wrap( - // pgModule.Client.prototype, - // 'connect', - // (original: PG.Client['connect']) => { - // return async function ( - // this: PG.Client['connect'], - // ...args: Parameters - // ) { - // const result = await original.apply(this, args); - // return result; - // } as PG.Client['connect']; - // } - // ); - wrap(pgModule.Client.prototype, 'query', (original: PG.Client['query']) => { return async function ( - this: PG.Client['query'], + this: PG.Client['query'] & { + connectionParameters: { + database: string; + }; + }, ...args: Parameters ) { let query = ''; @@ -40,10 +30,12 @@ export const instrumentPG = (pg: typeof PG | { default: typeof PG }) => { // @ts-ignore query = args[0]?.text; } + const end = histogram.startTimer({ - query: query, - database_name: '[db-name]' + query: maskValuesInSQLQuery(query).substring(0, 100), + database_name: this.connectionParameters.database ?? '[db-name]' }); + try { const result = await original.apply(this, args); end({ diff --git a/src/shimmer.ts b/src/shimmer.ts index 025c5d2..4cb7d85 100644 --- a/src/shimmer.ts +++ b/src/shimmer.ts @@ -46,7 +46,7 @@ export function isWrapped< export function wrap< T extends Record, K extends keyof T ->(nodule: T, name: K, wrapper: (original: T[K]) => T[K]) { +>(nodule: T, name: K, wrapper: (original: T[K], nodule?: T) => T[K]) { // Retrieve the original property from the object using the given key. const original = nodule?.[name]; @@ -65,7 +65,7 @@ export function wrap< } // Create the wrapped function by invoking the wrapper with the original function. - const wrappedFn = wrapper(original); + const wrappedFn = wrapper(original, nodule); // Add a property to the wrapped function to store the original function for later reference. defineProperty(wrappedFn, symbols.ORIGINAL, original); From b37047de5bf0e32ce6bfa3602a24d66161822eda Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Thu, 21 Dec 2023 17:49:18 +0530 Subject: [PATCH 05/16] 0.6.0-alpha.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9d5af1..35dba7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.5.1-alpha.1", + "version": "0.6.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.5.1-alpha.1", + "version": "0.6.0-alpha.1", "license": "Apache-2.0", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 9f35816..4db0870 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.5.1-alpha.1", + "version": "0.6.0-alpha.1", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From 4de858f272c7b6a217127a60a5954fea039e0350 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Fri, 22 Dec 2023 12:29:42 +0530 Subject: [PATCH 06/16] Update documentation --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9909193..9d3d58c 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ npm install --save @last9/openapm@latest 1. [Express](#express) 2. [MySQL](#mysql) 3. [NestJS](#nestjs) +4. [Postgres](#postgres) ### Express @@ -37,7 +38,7 @@ app.listen(3000) ### MySQL -This currently supports instrumentation for all Node.js ORMs, which are [mysql2](https://www.npmjs.com/package/mysql2) compatible. +This currently supports instrumentation for all Node.js ORMs, that uses [mysql2](https://www.npmjs.com/package/mysql2). Ensure to add this line of code before you initialize db `connection/pool/poolCluster`. @@ -53,6 +54,10 @@ OpenAPM currently supports RED Metrics for NestJS v4 and above. openapm.instrument('nestjs'); ``` +### Postgres + +This currently supports instrumentation for all Node.js ORMs, that uses [pg](https://www.npmjs.com/package/pg). + ## Options ### Usage From bffd5e431c4742e21ff4f99e8dcb263e58b5684d Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Fri, 22 Dec 2023 12:35:21 +0530 Subject: [PATCH 07/16] Update documentation --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9d3d58c..81ab879 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,10 @@ openapm.instrument('nestjs'); This currently supports instrumentation for all Node.js ORMs, that uses [pg](https://www.npmjs.com/package/pg). +```js +openapm.instrument('postgres'); +``` + ## Options ### Usage From 47670be6059ea3e84a261d059e863ec0ee9936e1 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Fri, 22 Dec 2023 12:41:54 +0530 Subject: [PATCH 08/16] 0.7.0-alpha.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 35dba7d..07093fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@last9/openapm", - "version": "0.6.0-alpha.1", + "version": "0.7.0-alpha.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@last9/openapm", - "version": "0.6.0-alpha.1", + "version": "0.7.0-alpha.1", "license": "Apache-2.0", "dependencies": { "chalk": "^4.1.2", diff --git a/package.json b/package.json index 4db0870..4b5d1d0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@last9/openapm", "description": "OpenAPM for Node.js", - "version": "0.6.0-alpha.1", + "version": "0.7.0-alpha.1", "main": "dist/index.js", "module": "dist/esm/index.js", "scripts": { From 0a7a89a2833bad15af3a03d79243bb7a6229c8b3 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Fri, 24 May 2024 15:28:25 +0530 Subject: [PATCH 09/16] Update the workflow file --- .github/workflows/build.yml | 10 ++++++ playground/app.js | 6 ++-- run-tests.sh | 9 ++++- src/OpenAPM.ts | 11 ++---- tests/mysql2.test.ts | 2 +- tests/pg.test.ts | 70 +++++++++++++++++++++++++++++++++++++ 6 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 tests/pg.test.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80d7061..45c0afd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,12 +17,22 @@ jobs: with: mysql-version: '8.0' + - uses: harmon758/postgresql-action@v1 + with: + postgresql version: '14' + - name: Test MySQL Connection run: mysql -h localhost -u root -e 'SELECT version()' + - name: Test Postgres Connection + run: psql -h localhost -U root -c 'SELECT version()' + - name: Create test DB run: mysql -h localhost -u root -e 'CREATE DATABASE test_db' + - name: Create test DB + run: psql -h localhost -U root -c 'CREATE DATABASE testdb' + - name: 🛎 Checkout uses: actions/checkout@v3 diff --git a/playground/app.js b/playground/app.js index cd2e8f5..b9fcf81 100644 --- a/playground/app.js +++ b/playground/app.js @@ -5,7 +5,7 @@ * */ require('dotenv').config(); var express = require('express'); -var { OpenAPM } = require('../dist/index.js'); +var { OpenAPM } = require('../dist/src/index.js'); var pg = require('pg'); // var mysql2 = require('mysql2'); @@ -52,7 +52,9 @@ app.get('/result', async (req, res) => { // await client.query(`INSERT INTO "users" (username) VALUES ('JohnDoe');`); let result; try { - result = await client.query('select * from users;'); + result = await client.query( + "select * from users where username='JohnDoe';" + ); } catch (error) {} res.status(200).json({ diff --git a/run-tests.sh b/run-tests.sh index b069832..13999bd 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -38,6 +38,11 @@ runMysqlTests() { npm run vitest -t ./tests/mysql2.test.ts } +# Run PG tests +runPgTests() { + npm run vitest -t ./tests/pg.test.ts +} + # Check if a variable is passed if [ "$1" = "express" ]; then npm run vitest -t ./tests/express.test.ts @@ -53,7 +58,9 @@ elif [ "$1" = "nestjs" ]; then elif [ "$1" = "prisma" ]; then runPrismaTests elif [ "$1" = "mysql2" ]; then - runAllTests + runMysqlTests +elif [ "$1" = "pg" ]; then + runPgTests else runAllTests fi \ No newline at end of file diff --git a/src/OpenAPM.ts b/src/OpenAPM.ts index 7099631..b64d256 100644 --- a/src/OpenAPM.ts +++ b/src/OpenAPM.ts @@ -80,19 +80,14 @@ export interface OpenAPMOptions { levitateConfig?: LevitateConfig; } -export type SupportedModules = - | 'express' - | 'mysql' - | 'nestjs' - | 'nextjs' - | 'postgres'; +export type SupportedModules = 'express' | 'mysql' | 'nestjs' | 'nextjs' | 'pg'; const moduleNames = { express: 'express', mysql: 'mysql2', nestjs: '@nestjs/core', nextjs: 'next', - postgres: 'pg' + pg: 'pg' }; const packageJson = getPackageJson(); @@ -457,7 +452,7 @@ export class OpenAPM extends LevitateEvents { ); } - if (moduleName === 'postgres') { + if (moduleName === 'pg') { const pg = require('pg'); instrumentPG(pg); } diff --git a/tests/mysql2.test.ts b/tests/mysql2.test.ts index 7ed0731..e1a0d0f 100644 --- a/tests/mysql2.test.ts +++ b/tests/mysql2.test.ts @@ -3,7 +3,7 @@ import mysql2, { Connection, Pool, PoolCluster } from 'mysql2'; import { instrumentMySQL, symbols } from '../src/clients/mysql2'; import prom, { Histogram } from 'prom-client'; -const connectionUri = 'mysql://root@localhost:3306/test_db'; +const connectionUri = 'mysql://root:password@localhost:3306/test_db'; const sendTestRequest = async (conn: Connection | Pool, query: string) => { return new Promise((resolve) => { diff --git a/tests/pg.test.ts b/tests/pg.test.ts new file mode 100644 index 0000000..e50b8c6 --- /dev/null +++ b/tests/pg.test.ts @@ -0,0 +1,70 @@ +import type { Connection } from 'pg'; +import { describe, beforeAll, afterAll, expect, test } from 'vitest'; +import { Client } from 'pg'; +import { OpenAPM, getMetricClient } from '../src/OpenAPM'; + +let connectionUri = 'postgres://tester:password@localhost:5432/testdb'; + +describe('pg', () => { + let client; + let openapm: OpenAPM; + + const getMetrics = async () => { + const client = getMetricClient(); + const parsedData = await client.register.getMetricsAsJSON(); + return parsedData; + }; + + beforeAll(async () => { + openapm = new OpenAPM(); + openapm.instrument('pg'); + + client = new Client(connectionUri); + await client.connect(); + }); + + afterAll(async () => { + await openapm.shutdown(); + await client.end(); + }); + + test('should connect to the database', async () => { + const res = await client.query('SELECT NOW()'); + expect(res.rows[0].now).toBeDefined(); + }); + + test('should capture metrics', async () => { + const res = await client.query('SELECT NOW()'); + expect(res.rows[0].now).toBeDefined(); + const metrics = await getMetrics(); + + const length = metrics.find( + (m) => m.name === 'db_requests_duration_milliseconds' + )?.values.length; + + expect(length).toBeDefined(); + expect(length).toBeGreaterThan(0); + }); + + test('masks the values in the query', async () => { + await client.query('SELECT * FROM users WHERE id = 1'); + await client.query("SELECT * FROM users WHERE username = 'JohnDoe'"); + + const metrics = await getMetrics(); + + const histogram = metrics.find( + (m) => m.name === 'db_requests_duration_milliseconds' + ); + const values = histogram?.values; + + const numberQuery = values?.find( + (v) => v.labels.query === 'SELECT * FROM users WHERE id = $1' + ); + const stringQuery = values?.find( + (v) => v.labels.query === 'SELECT * FROM users WHERE username = $1' + ); + + expect(numberQuery).toBeDefined(); + expect(stringQuery).toBeDefined(); + }); +}); From f0a587f17f4b1048b254f742722c808e213f0855 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 14:39:01 +0530 Subject: [PATCH 10/16] Add username and password for postgres sql db in workflow --- .github/workflows/build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45c0afd..bd84efe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,18 +20,20 @@ jobs: - uses: harmon758/postgresql-action@v1 with: postgresql version: '14' + postgresql user: 'tester' + postgresql password: 'password' - name: Test MySQL Connection run: mysql -h localhost -u root -e 'SELECT version()' - name: Test Postgres Connection - run: psql -h localhost -U root -c 'SELECT version()' + run: psql - name: Create test DB run: mysql -h localhost -u root -e 'CREATE DATABASE test_db' - name: Create test DB - run: psql -h localhost -U root -c 'CREATE DATABASE testdb' + run: psql -h localhost -U tester -c 'CREATE DATABASE testdb' - name: 🛎 Checkout uses: actions/checkout@v3 From d59744080bdb386af5210bdc36fa2ee458fcd2a7 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 15:01:55 +0530 Subject: [PATCH 11/16] Update the user and password in the test file --- .github/workflows/build.yml | 6 ++---- tests/pg.test.ts | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd84efe..45c0afd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,20 +20,18 @@ jobs: - uses: harmon758/postgresql-action@v1 with: postgresql version: '14' - postgresql user: 'tester' - postgresql password: 'password' - name: Test MySQL Connection run: mysql -h localhost -u root -e 'SELECT version()' - name: Test Postgres Connection - run: psql + run: psql -h localhost -U root -c 'SELECT version()' - name: Create test DB run: mysql -h localhost -u root -e 'CREATE DATABASE test_db' - name: Create test DB - run: psql -h localhost -U tester -c 'CREATE DATABASE testdb' + run: psql -h localhost -U root -c 'CREATE DATABASE testdb' - name: 🛎 Checkout uses: actions/checkout@v3 diff --git a/tests/pg.test.ts b/tests/pg.test.ts index e50b8c6..9a49c6e 100644 --- a/tests/pg.test.ts +++ b/tests/pg.test.ts @@ -3,7 +3,7 @@ import { describe, beforeAll, afterAll, expect, test } from 'vitest'; import { Client } from 'pg'; import { OpenAPM, getMetricClient } from '../src/OpenAPM'; -let connectionUri = 'postgres://tester:password@localhost:5432/testdb'; +let connectionUri = 'postgres://root:password@localhost:5432/testdb'; describe('pg', () => { let client; From 5b92b171967d5e15de4b2c84df8e176455b2bfca Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 15:08:23 +0530 Subject: [PATCH 12/16] Remove supported version --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 45c0afd..3333476 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,8 +18,6 @@ jobs: mysql-version: '8.0' - uses: harmon758/postgresql-action@v1 - with: - postgresql version: '14' - name: Test MySQL Connection run: mysql -h localhost -u root -e 'SELECT version()' From 5c25f95f4e08de563b3ab7afe3009cd499cf53ec Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 15:45:40 +0530 Subject: [PATCH 13/16] Add postgres as a service --- .github/workflows/build.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3333476..2c1c204 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,12 @@ jobs: release: name: Build runs-on: ubuntu-latest + services: + postgres: + image: postgres:12 + env: + POSTGRES_USER: root + POSTGRES_PASSWORD: password steps: - uses: actions/setup-node@v2 with: @@ -17,8 +23,6 @@ jobs: with: mysql-version: '8.0' - - uses: harmon758/postgresql-action@v1 - - name: Test MySQL Connection run: mysql -h localhost -u root -e 'SELECT version()' From 5e36b062c6c67955249de62201a8fb6918c42d41 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 15:48:56 +0530 Subject: [PATCH 14/16] Change the port --- tests/pg.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pg.test.ts b/tests/pg.test.ts index 9a49c6e..0c988ad 100644 --- a/tests/pg.test.ts +++ b/tests/pg.test.ts @@ -3,7 +3,7 @@ import { describe, beforeAll, afterAll, expect, test } from 'vitest'; import { Client } from 'pg'; import { OpenAPM, getMetricClient } from '../src/OpenAPM'; -let connectionUri = 'postgres://root:password@localhost:5432/testdb'; +let connectionUri = 'postgres://root:password@localhost:7432/testdb'; describe('pg', () => { let client; From f63457502c0896046e175c4d39a59ffe142cef65 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 15:50:52 +0530 Subject: [PATCH 15/16] Add port in the create db step --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c1c204..79d809d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: run: mysql -h localhost -u root -e 'CREATE DATABASE test_db' - name: Create test DB - run: psql -h localhost -U root -c 'CREATE DATABASE testdb' + run: psql -h localhost -p 7432 -U root -c 'CREATE DATABASE testdb' - name: 🛎 Checkout uses: actions/checkout@v3 From 0fe37747d3455120dd22de33f7c5d52057d13f77 Mon Sep 17 00:00:00 2001 From: Tushar Choudhari Date: Wed, 29 May 2024 15:52:40 +0530 Subject: [PATCH 16/16] Add port in test pg connection step --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79d809d..d24c203 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: run: mysql -h localhost -u root -e 'SELECT version()' - name: Test Postgres Connection - run: psql -h localhost -U root -c 'SELECT version()' + run: psql -h localhost -p 7432 -U root -c 'SELECT version()' - name: Create test DB run: mysql -h localhost -u root -e 'CREATE DATABASE test_db'