Skip to content

Commit

Permalink
feat: add fastify cpu profiler server
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelcr committed Aug 16, 2024
1 parent 232f9bb commit 735726e
Show file tree
Hide file tree
Showing 8 changed files with 624 additions and 2 deletions.
25 changes: 24 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"fastify-metrics": "^10.2.0",
"node-pg-migrate": "^6.2.2",
"pino": "^8.11.0",
"postgres": "^3.3.4"
"postgres": "^3.3.4",
"stacks-encoding-native-js": "^1.0.0"
}
}
5 changes: 5 additions & 0 deletions src/helpers/iterators.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as stream from 'stream';
import * as util from 'util';
import { logger } from '../logger';
import { isDevEnv } from './values';

Expand Down Expand Up @@ -76,3 +78,6 @@ export async function* asyncIterableToGenerator<T>(iter: AsyncIterable<T>) {
yield entry;
}
}

/** Promisify a pipeline */
export const pipelineAsync = util.promisify(stream.pipeline);
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export * from './fastify';
export * from './helpers';
export * from './logger';
export * from './postgres';
export * from './profiler';
export * from './server-version';
export * from './shutdown-handler';
67 changes: 67 additions & 0 deletions src/profiler/__tests__/profiler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { FastifyInstance } from 'fastify';
import { buildProfilerServer } from '../server';
import { timeout } from '../../helpers';

describe('CPU profiler', () => {
let fastify: FastifyInstance;

beforeAll(async () => {
fastify = await buildProfilerServer();
});

test('CPU profiler snapshot bad duration', async () => {
const query1 = await fastify.inject({
method: 'GET',
url: `/profile/cpu?duration=-100`,
});
expect(query1.statusCode).toBe(400);
});

test('generate CPU profiler snapshot', async () => {
const duration = 0.25; // 250 milliseconds
const query1 = await fastify.inject({
method: 'GET',
url: `/profile/cpu?duration=${duration}`,
});
expect(query1.statusCode).toBe(200);
expect(query1.headers['content-type']).toBe('application/json; charset=utf-8');
let cpuProfileBody: any;
// Ensure entire profile result was streamed/returned
expect(() => {
cpuProfileBody = query1.json();
}).not.toThrow();
// Cursory check for the expected JSON format of a `.cpuprofile` file
expect(cpuProfileBody).toEqual(
expect.objectContaining({
nodes: expect.any(Array),
samples: expect.any(Array),
timeDeltas: expect.any(Array),
startTime: expect.any(Number),
endTime: expect.any(Number),
})
);
});

test('cancel CPU profiler snapshot', async () => {
const duration = 150; // 150 seconds
// init a cpu profile request, hold on to the promise for reading the request response
const promise = fastify.inject({
method: 'GET',
url: `/profile/cpu?duration=${duration}`,
});
await timeout(200);
// perform a request to cancel the previous profile session
const endQuery = await fastify.inject({
method: 'GET',
url: `/profile/cancel`,
});
expect(endQuery.statusCode).toBe(200);
// ensure the initial request failed
const result = await promise;
expect(result.statusCode).toBe(500);
});

afterAll(async () => {
await fastify.close();
});
});
2 changes: 2 additions & 0 deletions src/profiler/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './inspector-util';
export * from './server';
Loading

0 comments on commit 735726e

Please sign in to comment.