feat(08-01): add Prometheus /metrics endpoint with prom-client
- Install prom-client library for Prometheus metrics - Create src/lib/server/metrics.ts with default Node.js process metrics - Add /metrics endpoint that returns Prometheus-format text - Exposes CPU, memory, heap, event loop metrics Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
38
package-lock.json
generated
38
package-lock.json
generated
@@ -12,6 +12,7 @@
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"nanoid": "^5.1.6",
|
||||
"prom-client": "^15.1.3",
|
||||
"sharp": "^0.34.5",
|
||||
"svelecte": "^5.3.0",
|
||||
"svelte-gestures": "^5.2.2",
|
||||
@@ -1626,6 +1627,15 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@opentelemetry/api": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
|
||||
"integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.58.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.1.tgz",
|
||||
@@ -2638,6 +2648,12 @@
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bintrees": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz",
|
||||
"integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
@@ -5059,6 +5075,19 @@
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prom-client": {
|
||||
"version": "15.1.3",
|
||||
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.3.tgz",
|
||||
"integrity": "sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"tdigest": "^0.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16 || ^18 || >=20"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||
@@ -5623,6 +5652,15 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/tdigest": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz",
|
||||
"integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bintrees": "1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"better-sqlite3": "^12.6.2",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"nanoid": "^5.1.6",
|
||||
"prom-client": "^15.1.3",
|
||||
"sharp": "^0.34.5",
|
||||
"svelecte": "^5.3.0",
|
||||
"svelte-gestures": "^5.2.2",
|
||||
|
||||
7
src/lib/server/metrics.ts
Normal file
7
src/lib/server/metrics.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Registry, collectDefaultMetrics } from 'prom-client';
|
||||
|
||||
// Create a custom registry for metrics
|
||||
export const registry = new Registry();
|
||||
|
||||
// Collect default Node.js process metrics (CPU, memory, event loop, etc.)
|
||||
collectDefaultMetrics({ register: registry });
|
||||
22
src/routes/metrics/+server.ts
Normal file
22
src/routes/metrics/+server.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { RequestHandler } from './$types';
|
||||
import { registry } from '$lib/server/metrics';
|
||||
|
||||
export const GET: RequestHandler = async () => {
|
||||
try {
|
||||
const metrics = await registry.metrics();
|
||||
|
||||
return new Response(metrics, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': registry.contentType
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Metrics collection failed:', error);
|
||||
|
||||
return new Response('Metrics unavailable', {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'text/plain' }
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user