From 8f33d7db53a91ddba10f1130b523c91a8a7e851c Mon Sep 17 00:00:00 2001 From: FrancescoXX Date: Tue, 28 Sep 2021 22:19:32 +0200 Subject: [PATCH] prometheus integration --- Dockerfile | 2 ++ package-lock.json | 48 +++++++++++++++++++++++++++++++++++- package.json | 3 ++- src/server.ts | 62 +++++++++++++++++++++++++++++------------------ 4 files changed, 89 insertions(+), 26 deletions(-) diff --git a/Dockerfile b/Dockerfile index ec5462c..47f45d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,6 +3,8 @@ FROM public.ecr.aws/bitnami/node:15 # Create app directory WORKDIR /usr/src/app +ENV STAGE=local + # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied # where available (npm@5+) diff --git a/package-lock.json b/package-lock.json index 36a7c44..72f12f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,9 @@ "dependencies": { "@types/pg": "^8.6.1", "aws-sdk": "^2.822.0", - "express": "^4.16.1", + "express": "^4.17.1", "pg": "^8.7.1", + "prom-client": "^14.0.0", "typescript": "^4.2.3", "uuid": "^3.3.2" }, @@ -166,6 +167,11 @@ } ] }, + "node_modules/bintrees": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", + "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + }, "node_modules/body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -631,6 +637,17 @@ "node": ">=0.10.0" } }, + "node_modules/prom-client": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.0.0.tgz", + "integrity": "sha512-etPa4SMO4j6qTn2uaSZy7+uahGK0kXUZwO7WhoDpTf3yZ837I3jqUDYmG6N0caxuU6cyqrg0xmOxh+yneczvyA==", + "dependencies": { + "tdigest": "^0.1.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -804,6 +821,14 @@ } ] }, + "node_modules/tdigest": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", + "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "dependencies": { + "bintrees": "1.0.1" + } + }, "node_modules/toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -1035,6 +1060,11 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "bintrees": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", + "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -1388,6 +1418,14 @@ "xtend": "^4.0.0" } }, + "prom-client": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.0.0.tgz", + "integrity": "sha512-etPa4SMO4j6qTn2uaSZy7+uahGK0kXUZwO7WhoDpTf3yZ837I3jqUDYmG6N0caxuU6cyqrg0xmOxh+yneczvyA==", + "requires": { + "tdigest": "^0.1.1" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -1524,6 +1562,14 @@ } } }, + "tdigest": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", + "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "requires": { + "bintrees": "1.0.1" + } + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", diff --git a/package.json b/package.json index d7a53b3..a016bf9 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,9 @@ "dependencies": { "@types/pg": "^8.6.1", "aws-sdk": "^2.822.0", - "express": "^4.16.1", + "express": "^4.17.1", "pg": "^8.7.1", + "prom-client": "^14.0.0", "typescript": "^4.2.3", "uuid": "^3.3.2" }, diff --git a/src/server.ts b/src/server.ts index b0c9a39..3ea4c13 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,43 +1,57 @@ import * as express from "express"; -import { json } from "body-parser"; - import { deleteDynamoDbItem, getDynamoDbItem, putDynamoDbItem, updateDynamoDbItem } from "./dynamodb-item"; import { deletePostgresItem, getPostgresDbItem, createPostgresDbItem, updatePostgresItem } from "./postgresdb-item"; import { deleteAuthenticatedItem, getAuthenticatedItem, putAuthenticatedItem, updateAuthenticatedItem } from "./authenticated-item"; import { deleteItem, getItem, putItem, updateItem } from "./local-item"; +const client = require('prom-client'); +const register = new client.Registry(); +register.setDefaultLabels({ + app: 'example-nodejs-app', +}); +client.collectDefaultMetrics({ register }); // Constants -const PORT = process.env.STAGE === "local" ? 8000 : 80; +const PORT = process.env.STAGE === "local" ? 8080 : 80; const HOST = '0.0.0.0'; // App handlers const app = express(); -const parser = json(); +app.use(express.json()); app.get("/ping", (req, res) => { res.status(200).send(); }); -app.put('/local-item', parser, putItem); -app.get('/local-item', parser, getItem); -app.post('/local-item', parser, updateItem); -app.delete('/local-item', parser, deleteItem); - -app.put('/dynamodb-item', parser, putDynamoDbItem); -app.post('/dynamodb-item', parser, updateDynamoDbItem); -app.get('/dynamodb-item', parser, getDynamoDbItem); -app.delete('/dynamodb-item', parser, deleteDynamoDbItem); - -app.get('/postgresql-item/:id', parser, getPostgresDbItem); -app.get('/postgresql-item', parser, getPostgresDbItem); -app.put('/postgresql-item', parser, createPostgresDbItem); -app.post('/postgresql-item/:id', parser, updatePostgresItem); -app.delete('/postgresql-item/:id', parser, deletePostgresItem); - -app.put('/authenticated-dynamodb-item', parser, putAuthenticatedItem); -app.get('/authenticated-dynamodb-item', parser, getAuthenticatedItem); -app.post('/authenticated-dynamodb-item', parser, updateAuthenticatedItem); -app.delete('/authenticated-dynamodb-item', parser, deleteAuthenticatedItem); +app.get('/metrics', async (req: any, res: any) => { + try { + res.setHeader('Content-Type', register.contentType); + res.end(await register.metrics()); + } catch (error) { + res.send(error); + } +}); + +app.put('/local-item', putItem); +app.get('/local-item', getItem); +app.post('/local-item', updateItem); +app.delete('/local-item', deleteItem); + +app.put('/dynamodb-item', putDynamoDbItem); +app.post('/dynamodb-item', updateDynamoDbItem); +app.get('/dynamodb-item', getDynamoDbItem); +app.delete('/dynamodb-item', deleteDynamoDbItem); + +app.get('/postgresql-item/:id', getPostgresDbItem); +app.get('/postgresql-item', getPostgresDbItem); +app.put('/postgresql-item', createPostgresDbItem); +app.post('/postgresql-item/:id', updatePostgresItem); +app.delete('/postgresql-item/:id', deletePostgresItem); + +app.put('/authenticated-dynamodb-item', putAuthenticatedItem); +app.get('/authenticated-dynamodb-item', getAuthenticatedItem); +app.post('/authenticated-dynamodb-item', updateAuthenticatedItem); +app.delete('/authenticated-dynamodb-item', deleteAuthenticatedItem); + app.listen(PORT, HOST); console.log(`Running on http://${HOST}:${PORT}`);