import fs from 'fs'; import express from 'express'; import supertest from 'supertest'; import { Log } from './types'; import { Prometheus } from './index'; const revHead = 'b138dc0ef3fee4db90d6f8f905013a754276fa5f'; const tag = 'cs/v.10.0'; jest.mock('child_process', () => ({ execSync: ((inp: string) => { switch (inp) { case 'git rev-parse --abbrev-ref HEAD': return 'dev'; case 'git rev-parse HEAD': return revHead; case 'git describe --tags --abbrev=0': return tag; default: return 'unknown'; } }), })); jest.mock('fs', () => ({ writeFileSync: jest.fn(), })); jest .useFakeTimers() .setSystemTime(new Date('2024-01-01')); const isJSON = (val: string) => { try { JSON.parse(val); return true; } catch (e) { return false; } }; describe('Prometheus', () => { let prometheus: Prometheus; const config = { version: '1.0.0', namespace: 'test', name: 'test', ipAddress: '127.0.0.1', pod: 'test', distPath: '', }; const log: Log = console; beforeEach(() => { prometheus = new Prometheus(config, log); }); it('Should return metrics', async () => { const metrics = await prometheus.metrics(); expect(typeof metrics).toBe('string'); }); it('Prometheus metrics should have given structure', async () => { const metrics = await prometheus.metrics(); const lines = metrics.split('\n'); const regex = /^(.*\{.*\} \d+(\.\d+)?|.*\{.*\} \d+(\.\d+)?e-\d+|.*\{.*\} Nan|\w+ \d+(\.\d+)?|\w+ \d+(\.\d+)?e-\d+|\w+ Nan)$/; for (const line of lines) { if (line.length === 0 || line[0] === '#') continue; if (!regex.test(line)) { expect(regex.test(line)).toBe(true); } } }); it('Should return metrics in JSON', async () => { const metrics = await prometheus.metricsInJson(); expect(typeof metrics).toBe('object'); }); it('Should build info file', () => { prometheus.buildInfoFile(); expect(fs.writeFileSync).toHaveBeenCalled(); expect(fs.writeFileSync).toHaveBeenCalledWith( 'info.json', '{"version":"1.0.0","buildTime":"2024-01-01T00:00:00.000Z","commit":"b138dc0ef3fee4db90d6f8f905013a754276fa5f","branch":"dev","tags":"cs/v.10.0"}', ); }); it('Should attach prometheus endpoints to express', async () => { const app = express(); prometheus.attachToExpress(app); const request = supertest(app); const resProm = await request.get('/management/prometheus'); expect(resProm.status).toBe(200); expect(resProm.text).toContain('process_cpu_user_seconds_total'); const resJson = await request.get('/management/metrics'); expect(resJson.status).toBe(200); expect(resJson.text).toContain('process_cpu_user_seconds_total'); expect(isJSON(resJson.text)).toBe(true); }); it('Should attach express middleware and show them in stats', async () => { const app = express(); app.use(prometheus.getExpressMetricsMiddleware()); app.use('/test', (_, res) => res.send('it worked')); const request = supertest(app); await request.get('/test'); const promData = await prometheus.metrics(); expect(promData).toContain('http_request_duration_seconds_bucket{le="1",status_code="200",method="GET",path="/test"}'); }); });