diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 545d9c2a6..8e621552a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -224,6 +224,9 @@ importers: openapi-backend: specifier: ^5.15.0 version: 5.15.0 + prom-client: + specifier: ^15.1.3 + version: 15.1.3 proxy-addr: specifier: ^2.0.7 version: 2.0.7 @@ -832,6 +835,10 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + '@paralleldrive/cuid2@2.2.2': resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} @@ -2073,6 +2080,9 @@ packages: binary-search@1.3.6: resolution: {integrity: sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==} + bintrees@1.0.2: + resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==} + birpc@2.5.0: resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} @@ -3825,6 +3835,10 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prom-client@15.1.3: + resolution: {integrity: sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==} + engines: {node: ^16 || ^18 || >=20} + promise@1.3.0: resolution: {integrity: sha512-R9WrbTF3EPkVtWjp7B7umQGVndpsi+rsDAfrR4xAALQpFLa/+2OriecLhawxzvii2gd9+DZFwROWDuUUaqS5yA==} @@ -4376,6 +4390,9 @@ packages: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + tdigest@0.1.2: + resolution: {integrity: sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -5252,6 +5269,8 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@opentelemetry/api@1.9.0': {} + '@paralleldrive/cuid2@2.2.2': dependencies: '@noble/hashes': 1.8.0 @@ -6491,6 +6510,8 @@ snapshots: binary-search@1.3.6: {} + bintrees@1.0.2: {} + birpc@2.5.0: {} body-parser@2.2.0: @@ -8499,6 +8520,11 @@ snapshots: prelude-ls@1.2.1: {} + prom-client@15.1.3: + dependencies: + '@opentelemetry/api': 1.9.0 + tdigest: 0.1.2 + promise@1.3.0: dependencies: is-promise: 1.0.1 @@ -9141,6 +9167,10 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 + tdigest@0.1.2: + dependencies: + bintrees: 1.0.2 + tinybench@2.9.0: {} tinycon@0.6.8: {} diff --git a/src/node/hooks/express/specialpages.ts b/src/node/hooks/express/specialpages.ts index 8d42a43bb..1f4ce3302 100644 --- a/src/node/hooks/express/specialpages.ts +++ b/src/node/hooks/express/specialpages.ts @@ -13,8 +13,11 @@ const plugins = require('../../../static/js/pluginfw/plugin_defs'); import {build, buildSync} from 'esbuild' import {ArgsExpressType} from "../../types/ArgsExpressType"; +import prometheus from "../../prometheus"; + let ioI: { sockets: { sockets: any[]; }; } | null = null + exports.socketio = (hookName: string, {io}: any) => { ioI = io } @@ -35,6 +38,12 @@ exports.expressPreSession = async (hookName:string, {app}:ArgsExpressType) => { app.get('/stats', (req:any, res:any) => { res.json(require('../../stats').toJSON()); }); + + app.get('/stats/prometheus', async (req, res) => { + const metrics = await prometheus() + res.setHeader('Content-Type', metrics.contentType) + res.send(await metrics.metrics()) + }) } diff --git a/src/node/metrics.ts b/src/node/metrics.ts new file mode 100644 index 000000000..5afc72654 --- /dev/null +++ b/src/node/metrics.ts @@ -0,0 +1,11 @@ +import Prometheus from 'prom-client'; + +export const metrics = { + 'cpu': new Prometheus.Gauge({ name: 'nodejs_cpu_gauge', help: 'gauge for nodejs cpu' ,labelNames: ['type'] }), + 'memory_process': new Prometheus.Gauge({ name: 'nodejs_memory_process_gauge', help: 'gauge for nodejs memory_process' ,labelNames: ['type'] }), + 'memory_physical': new Prometheus.Gauge({ name: 'nodejs_memory_physical_gauge', help: 'gauge for nodejs_memory_physical' ,labelNames: ['type'] }), + 'eventloop_latency': new Prometheus.Gauge({ name: 'nodejs_eventloop_latency_gauge' , help: 'gauge for nodejs_eventloop_latency' ,labelNames: ['type'] }), + 'gc': new Prometheus.Gauge({ name: 'nodejs_gc_gauge' , help: 'gause for nodejs_gc' ,labelNames: ['type']}), + 'gc_duration': new Prometheus.Summary({ name: 'nodejs_gc_duration' , help: 'gause for nodejs_gc_duration', percentiles: [ 0.5, 0.75, 0.95 ] }), + 'http_duration': new Prometheus.Summary({ name: 'http_duration', help: 'summary for http_duration', percentiles: [ 0.5, 0.75, 0.95 ] ,labelNames: ['url'] }) +}; diff --git a/src/node/prometheus.ts b/src/node/prometheus.ts new file mode 100644 index 000000000..2fad567f4 --- /dev/null +++ b/src/node/prometheus.ts @@ -0,0 +1,25 @@ +import client from 'prom-client' +const db = require('./db/DB').db + +const monitor = function () { + const collectDefaultMetrics = client.collectDefaultMetrics; + const Registry = client.Registry; + const register = new Registry(); + collectDefaultMetrics({register}); + const gaugeDB = new client.Gauge({ + name: "ueberdb_stats", + help: "ueberdb stats", + labelNames: ['type'], + }) + + for (const [metric, value] of Object.entries(db.metrics)) { + if (typeof value !== 'number') continue; + gaugeDB.set({type: metric}, value); + } + + + register.registerMetric(gaugeDB); + return register +}; + +export default monitor; diff --git a/src/package.json b/src/package.json index 916839eae..9a3e949c8 100644 --- a/src/package.json +++ b/src/package.json @@ -58,6 +58,7 @@ "mime-types": "^3.0.1", "oidc-provider": "^9.4.2", "openapi-backend": "^5.15.0", + "prom-client": "^15.1.3", "proxy-addr": "^2.0.7", "rate-limiter-flexible": "^7.2.0", "rehype": "^13.0.2",