Skip to content

Commit

Permalink
feat(api): track request content length (#3316)
Browse files Browse the repository at this point in the history
## Changes

Fixes
https://linear.app/nango/issue/NAN-2540/track-request-content-length


- API track request content length
Inside traces as tag and as a metric to be able to graph it properly.
I'm not the best at math so hopefully the computation is correct.

![Screenshot 2025-01-16 at 11 31
05](https://github.com/user-attachments/assets/1732262f-c8a0-4891-b42d-458920ce214b)
![Screenshot 2025-01-16 at 11 24
19](https://github.com/user-attachments/assets/cedd961c-56e8-490c-9004-6d61438dfe1f)
  • Loading branch information
bodinsamuel authored Jan 16, 2025
1 parent 32bfc10 commit 5439cee
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
11 changes: 10 additions & 1 deletion packages/server/lib/utils/asyncWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Endpoint } from '@nangohq/types';
import type { RequestHandler, Request, Response, NextFunction } from 'express';
import { isAsyncFunction } from 'util/types';
import type { RequestLocals } from './express.js';
import { metrics } from '@nangohq/utils';

export function asyncWrapper<TEndpoint extends Endpoint<any>, Locals extends Record<string, any> = Required<RequestLocals>>(
fn: (
Expand All @@ -13,7 +14,15 @@ export function asyncWrapper<TEndpoint extends Endpoint<any>, Locals extends Rec
): RequestHandler<any, TEndpoint['Reply'], any, any, any> {
return (req, res, next) => {
const active = tracer.scope().active();
active?.setTag('http.route', req.route?.path || req.originalUrl);
if (active) {
active.setTag('http.route', req.route?.path || req.originalUrl);
const contentLength = req.header('content-length');
if (contentLength) {
const int = parseInt(contentLength, 10);
active.setTag('http.request.body.size', int);
metrics.histogram(metrics.Types.API_REQUEST_CONTENT_LENGTH, int);
}
}
if (isAsyncFunction(fn)) {
return (fn(req, res, next) as unknown as Promise<any>).catch((err: unknown) => {
next(err);
Expand Down
12 changes: 11 additions & 1 deletion packages/utils/lib/express/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import tracer from 'dd-trace';
import type { Request, Response, NextFunction, Express } from 'express';
import type { Endpoint } from '@nangohq/types';
import * as metrics from '../telemetry/metrics.js';

export type EndpointRequest<E extends Endpoint<any>> = Request<E['Params'], E['Reply'], E['Body'], E['Querystring']>;
export type EndpointResponse<E extends Endpoint<any>> = Response<E['Reply']>;
Expand All @@ -18,7 +19,16 @@ export interface RouteHandler<E extends Endpoint<any>> extends Route<E> {
export const createRoute = <E extends Endpoint<any>>(server: Express, rh: RouteHandler<E>): void => {
const safeHandler = (req: EndpointRequest<E>, res: EndpointResponse<E>, next: NextFunction): void => {
const active = tracer.scope().active();
active?.setTag('http.route', req.route?.path || req.originalUrl);
if (active) {
active?.setTag('http.route', req.route?.path || req.originalUrl);
const contentLength = req.header('content-length');
if (contentLength) {
const int = parseInt(contentLength, 10);
active.setTag('http.request.body.size', int);
metrics.histogram(metrics.Types.API_REQUEST_CONTENT_LENGTH, int);
}
}

Promise.resolve(rh.handler(req, res, next)).catch((err: unknown) => next(err));
};

Expand Down
8 changes: 7 additions & 1 deletion packages/utils/lib/telemetry/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export enum Types {
ORCH_TASKS_SUCCEEDED = 'nango.orch.tasks.succeeded',
ORCH_TASKS_FAILED = 'nango.orch.tasks.failed',
ORCH_TASKS_EXPIRED = 'nango.orch.tasks.expired',
ORCH_TASKS_CANCELLED = 'nango.orch.tasks.cancelled'
ORCH_TASKS_CANCELLED = 'nango.orch.tasks.cancelled',

API_REQUEST_CONTENT_LENGTH = 'nango.api.request.content_length'
}

export function increment(metricName: Types, value = 1, dimensions?: Record<string, string | number>): void {
Expand All @@ -69,6 +71,10 @@ export function gauge(metricName: Types, value?: number): void {
tracer.dogstatsd.gauge(metricName, value ?? 1);
}

export function histogram(metricName: Types, value: number): void {
tracer.dogstatsd.histogram(metricName, value);
}

export function duration(metricName: Types, value: number): void {
tracer.dogstatsd.distribution(metricName, value);
}
Expand Down

0 comments on commit 5439cee

Please sign in to comment.