This guide is for those not using an Express.js backend but who want to track the backend duration of their requests.
To track your requests, create a middleware using the provided example for Express. Ensure that you allow the fetchlytics-id
header.
We are working on expanding our support to other frameworks and libraries.
1export interface FetchAnalyticsOptions {
2 apiKey: string;
3 appName: string;
4}
5
6export function trackRequestAnalytics(options: FetchAnalyticsOptions) {
7 return (req: Request, res: Response, next: NextFunction) => {
8 // Extract the unique fetch identifier from the request headers
9 const fetchLyticsId = req.headers?.['fetchlytics-id'];
10
11 if (!fetchLyticsId) {
12 return next(); // Skip if no fetch identifier is found
13 }
14
15 // Track the start time of the request
16 const start = Date.now();
17
18 // Function to run when the response is finished
19 const onResponseFinished = async () => {
20 const fullUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
21 const duration = Date.now() - start;
22 const analyticsData = {
23 fetchLyticsId,
24 appName: options.appName,
25 url: fullUrl,
26 method: req.method,
27 status: res.statusCode,
28 duration,
29 timestamp: start,
30 };
31
32 try {
33 // Dynamically import node-fetch only when needed
34 const fetch = (await import('node-fetch')).default;
35
36 // Send the analytics data
37 await fetch('https://fetchlytics.dev/api/datacollector/backendAnalytic', {
38 method: 'POST',
39 headers: {
40 'Content-Type': 'application/json',
41 Authorization: `Bearer ${options.apiKey}`,
42 },
43 body: JSON.stringify(analyticsData),
44 });
45 } catch (error) {
46 console.error('Failed to send backend analytics:', error);
47 }
48 };
49
50 // Attach the onResponseFinished function to the response finish
51 if (res.on) {
52 res.on('finish', onResponseFinished); // For Express or Fastify-like frameworks
53 } else if (typeof res.end === 'function') {
54 const originalEnd = res.end;
55 res.end = (...args: any[]) => {
56 onResponseFinished();
57 return originalEnd.apply(res, args); // Make sure to return the result of the original res.end function
58 };
59 }
60
61 next(); // Proceed to the next middleware
62 };
63}