this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add husky, prom-client, tweak pino

Also update packages

alice 62ac1c51 f05f0165

+96 -32
+1
.env.example
··· 1 1 # env variables 2 + METRICS_PORT=3001
+2
.husky/pre-commit
··· 1 + # shellcheck disable=SC2148 2 + bunx lint-staged
+1 -1
.prettierignore
··· 1 - pnpm-lock.yaml 1 + # ...
+15 -7
package.json
··· 9 9 "dev": "bunx --watch src/index.ts", 10 10 "format": "bunx prettier --write .", 11 11 "lint": "bunx eslint .", 12 - "lint:fix": "bunx eslint --fix ." 12 + "lint:fix": "bunx eslint --fix .", 13 + "prepare": "husky" 13 14 }, 14 15 "dependencies": { 15 16 "dotenv": "^16.4.5", 16 - "pino": "^9.4.0", 17 - "pino-pretty": "^11.2.2" 17 + "fastify": "^5.0.0", 18 + "husky": "^9.1.6", 19 + "lint-staged": "^15.2.10", 20 + "pino": "^9.5.0", 21 + "pino-pretty": "^11.3.0", 22 + "prom-client": "^15.1.3" 18 23 }, 19 24 "devDependencies": { 20 - "@eslint/js": "^9.12.0", 25 + "@eslint/js": "^9.13.0", 21 26 "@trivago/prettier-plugin-sort-imports": "^4.3.0", 22 27 "@types/eslint__js": "^8.42.3", 23 - "@types/node": "^22.7.5", 24 - "eslint": "^9.12.0", 28 + "@types/node": "^22.7.7", 29 + "eslint": "^9.13.0", 25 30 "prettier": "^3.3.3", 26 31 "tsx": "^4.19.1", 27 32 "typescript": "^5.6.3", 28 - "typescript-eslint": "^8.8.1" 33 + "typescript-eslint": "^8.10.0" 34 + }, 35 + "lint-staged": { 36 + "*": "prettier --ignore-unknown --write --ignore-path .prettierignore" 29 37 }, 30 38 "author": "alice", 31 39 "license": "MIT"
+30 -8
src/index.ts
··· 1 - import dotenv from 'dotenv'; 1 + import 'dotenv/config'; 2 2 3 3 import logger from './logger.js'; 4 + import { startMetricsServer, stopMetricsServer } from './metrics.js'; 4 5 5 - dotenv.config(); 6 + await startMetricsServer(Number(process.env.METRICS_PORT)); 7 + logger.info('Hello, World!'); 8 + 9 + let isShuttingDown = false; 10 + async function shutdown() { 11 + if (isShuttingDown) { 12 + logger.info('Shutdown called but one is already in progress.'); 13 + return; 14 + } 6 15 7 - logger.info('Hello, World!'); 16 + isShuttingDown = true; 8 17 9 - function shutdown() { 10 18 logger.info('Shutting down gracefully...'); 19 + try { 20 + await stopMetricsServer(); 21 + } catch (error) { 22 + logger.error(`Error closing Metrics server: ${(error as Error).message}`); 23 + } 11 24 12 - // ... 13 25 process.exit(0); 26 + } 14 27 15 - } 28 + process.on('SIGINT', () => { 29 + shutdown().catch((error: unknown) => { 30 + logger.error(`Shutdown failed: ${(error as Error).message}`); 31 + process.exit(1); 32 + }); 33 + }); 16 34 17 - process.on('SIGINT', shutdown); 18 - process.on('SIGTERM', shutdown); 35 + process.on('SIGTERM', () => { 36 + shutdown().catch((error: unknown) => { 37 + logger.error(`Shutdown failed: ${(error as Error).message}`); 38 + process.exit(1); 39 + }); 40 + });
+12 -16
src/logger.ts
··· 1 1 import { pino } from 'pino'; 2 - 3 - const logger = pino({ 4 - level: process.env.LOG_LEVEL ?? 'info', 5 - transport: 6 - process.env.NODE_ENV !== 'production' ? 7 - { 8 - target: 'pino-pretty', 9 - options: { 10 - colorize: true, 11 - translateTime: 'SYS:standard', 12 - ignore: 'pid,hostname', 13 - }, 14 - } 15 - : undefined, 16 - timestamp: pino.stdTimeFunctions.isoTime, 17 - }); 2 + import pretty from 'pino-pretty'; 18 3 4 + const logger = pino( 5 + { 6 + level: process.env.LOG_LEVEL ?? 'info', 7 + timestamp: pino.stdTimeFunctions.isoTime, 8 + }, 9 + pretty({ 10 + sync: process.env.NODE_ENV !== 'production' ? true : false, 11 + colorize: true, 12 + translateTime: 'SYS:standard', 13 + }), 14 + ); 19 15 export default logger;
+35
src/metrics.ts
··· 1 + import Fastify from 'fastify'; 2 + import { Registry, collectDefaultMetrics } from 'prom-client'; 3 + 4 + import logger from './logger.js'; 5 + 6 + const register = new Registry(); 7 + collectDefaultMetrics({ register }); 8 + 9 + const app = Fastify({ 10 + loggerInstance: logger, 11 + disableRequestLogging: true, 12 + }); 13 + 14 + app.get('/metrics', async (request, reply) => { 15 + const metrics = await register.metrics(); 16 + reply.type(register.contentType).send(metrics); 17 + }); 18 + 19 + const startMetricsServer = async (port: number, host = '127.0.0.1') => { 20 + try { 21 + await app.listen({ 22 + port, 23 + host, 24 + listenTextResolver: (address) => `Metrics server started and available at ${address}/metrics`, 25 + }); 26 + } catch (error) { 27 + app.log.error(`Error starting Metrics server: ${(error as Error).message}`); 28 + } 29 + }; 30 + 31 + const stopMetricsServer = async () => { 32 + await app.close(); 33 + }; 34 + 35 + export { startMetricsServer, stopMetricsServer };