Skip to content

Commit

Permalink
feat(createTimedSpan): Pass along tags from afterCompletion
Browse files Browse the repository at this point in the history
  • Loading branch information
AkiraJ48 committed Jul 24, 2023
1 parent 81f4e7a commit f9bc59c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
27 changes: 26 additions & 1 deletion src/createTimedSpan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('timedSpan', () => {
expect(duration).toBeGreaterThan(0);
});

it('should pass along tags', async () => {
it('should pass along tags from `timedSpan`', async () => {
const mockIncrement = jest.spyOn(metricsClient, 'increment');
const mockTiming = jest.spyOn(metricsClient, 'timing');

Expand All @@ -90,6 +90,31 @@ describe('timedSpan', () => {
);
});

it('should pass along tags from `afterCompletion`', async () => {
const mockIncrement = jest.spyOn(metricsClient, 'increment');
const mockTiming = jest.spyOn(metricsClient, 'timing');

await timedSpan(
'test',
// This is false but we still successfully resolved
() => Promise.resolve(false),
() => ({ tags: ['tags-from-after-completion'] }),
['new-tags'],
);

expect(mockIncrement).toHaveBeenCalledWith('test.count', [
'success',
'new-tags',
'tags-from-after-completion',
]);

expect(mockTiming).toHaveBeenCalledWith(
'test.latency',
expect.any(Number),
['new-tags', 'tags-from-after-completion'],
);
});

it('should handle failure', async () => {
const mockIncrement = jest.spyOn(metricsClient, 'increment');
const mockTiming = jest.spyOn(metricsClient, 'timing');
Expand Down
24 changes: 18 additions & 6 deletions src/createTimedSpan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import type { MetricsClient } from './MetricsClient';

type TimingMetricsClient = Pick<MetricsClient, 'increment' | 'timing'>;

interface AfterCompletion {
tags: string[];
}

/**
* Sends timing related metrics for an asynchronous operation
*
Expand All @@ -18,28 +22,36 @@ export const createTimedSpan =
async <T>(
name: string,
block: () => PromiseLike<T>,
afterCompletion?: (duration: number, success: boolean) => void,
afterCompletion?: (
duration: number,
success: boolean,
result: T | undefined,
) => AfterCompletion | void,
tags?: string[],
): Promise<T> => {
const startTime = process.hrtime.bigint();

const handleCompletion = (success: boolean) => {
const handleCompletion = (success: boolean, result: T | undefined) => {
const durationNanos = process.hrtime.bigint() - startTime;
const successTag = success ? 'success' : 'failure';
const durationMilliseconds = Number(durationNanos) / 1e6;

const complete = afterCompletion?.(durationMilliseconds, success, result);

if (complete?.tags) {
(tags ?? []).push(...complete.tags);
}

metricsClient.timing(`${name}.latency`, durationMilliseconds, tags);
metricsClient.increment(`${name}.count`, [successTag, ...(tags ?? [])]);

afterCompletion?.(durationMilliseconds, success);
};

try {
const result = await block();
handleCompletion(true);
handleCompletion(true, result);
return result;
} catch (e) {
handleCompletion(false);
handleCompletion(false, undefined);
throw e;
}
};

0 comments on commit f9bc59c

Please sign in to comment.