function-trace 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ import type { TraceOptions, TraceStats } from "./types/index.js";
2
+ export declare function trace<F extends (...args: any[]) => any>(fn: F, options?: TraceOptions): F & {
3
+ stats: TraceStats;
4
+ };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEjE,wBAAgB,KAAK,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACnD,EAAE,EAAE,CAAC,EACL,OAAO,GAAE,YAAiB,GAC3B,CAAC,GAAG;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,CAsD3B"}
package/dist/index.js ADDED
@@ -0,0 +1,47 @@
1
+ export function trace(fn, options = {}) {
2
+ const { log = false, maxHistory = 50 } = options;
3
+ const stats = { calls: 0, errors: 0, lastTime: 0, history: [] };
4
+ const wrapped = ((...args) => {
5
+ const start = performance.now ? performance.now() : Date.now();
6
+ stats.calls += 1;
7
+ try {
8
+ const result = fn(...args);
9
+ if (result instanceof Promise) {
10
+ return result
11
+ .then((res) => {
12
+ const end = performance.now
13
+ ? performance.now()
14
+ : Date.now();
15
+ stats.lastTime = end - start;
16
+ stats.history.push(stats.lastTime);
17
+ if (stats.history.length > maxHistory)
18
+ stats.history.shift();
19
+ if (log)
20
+ console.log(`[func-trace] ${fn.name || 'anonymous'} executed in ${stats.lastTime.toFixed(2)}ms`);
21
+ return res;
22
+ })
23
+ .catch((err) => {
24
+ stats.errors += 1;
25
+ throw err;
26
+ });
27
+ }
28
+ else {
29
+ const end = performance.now ? performance.now() : Date.now();
30
+ stats.lastTime = end - start;
31
+ stats.history.push(stats.lastTime);
32
+ if (stats.history.length > maxHistory)
33
+ stats.history.shift();
34
+ if (log)
35
+ console.log(`[func-trace] ${fn.name || 'anonymous'} executed in ${stats.lastTime.toFixed(2)}ms`);
36
+ return result;
37
+ }
38
+ }
39
+ catch (err) {
40
+ stats.errors += 1;
41
+ throw err;
42
+ }
43
+ });
44
+ wrapped.stats = stats;
45
+ return wrapped;
46
+ }
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,KAAK,CACjB,EAAK,EACL,UAAwB,EAAE;IAE1B,MAAM,EAAE,GAAG,GAAG,KAAK,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,KAAK,GAAe,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAE5E,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,IAAmB,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/D,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAEjB,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YAE3B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC5B,OAAO,MAAM;qBACR,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;oBACV,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG;wBACvB,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE;wBACnB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;oBACjB,KAAK,CAAC,QAAQ,GAAG,GAAG,GAAG,KAAK,CAAC;oBAC7B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBACnC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU;wBACjC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;oBAC1B,IAAI,GAAG;wBACH,OAAO,CAAC,GAAG,CACP,gBACI,EAAE,CAAC,IAAI,IAAI,WACf,gBAAgB,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAChD,CAAC;oBACN,OAAO,GAAG,CAAC;gBACf,CAAC,CAAC;qBACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;oBACX,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;oBAClB,MAAM,GAAG,CAAC;gBACd,CAAC,CAAC,CAAC;YACX,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7D,KAAK,CAAC,QAAQ,GAAG,GAAG,GAAG,KAAK,CAAC;gBAC7B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACnC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU;oBAAE,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC7D,IAAI,GAAG;oBACH,OAAO,CAAC,GAAG,CACP,gBACI,EAAE,CAAC,IAAI,IAAI,WACf,gBAAgB,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAChD,CAAC;gBACN,OAAO,MAAM,CAAC;YAClB,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;YAClB,MAAM,GAAG,CAAC;QACd,CAAC;IACL,CAAC,CAA8B,CAAC;IAEhC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,OAAO,OAAO,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface TraceOptions {
2
+ log?: boolean;
3
+ maxHistory?: number;
4
+ color?: boolean;
5
+ }
6
+ export interface TraceStats {
7
+ calls: number;
8
+ errors: number;
9
+ lastTime: number;
10
+ history: number[];
11
+ }
12
+ export declare function trace<F extends (...args: any[]) => any>(fn: F, options?: TraceOptions): F & {
13
+ stats: TraceStats;
14
+ };
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IACzB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAGD,wBAAgB,KAAK,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,EACnD,EAAE,EAAE,CAAC,EACL,OAAO,GAAE,YAAiB,GAC3B,CAAC,GAAG;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,CAgE3B"}
@@ -0,0 +1,57 @@
1
+ export function trace(fn, options = {}) {
2
+ const { log = false, maxHistory = 50, color = true } = options;
3
+ const stats = { calls: 0, errors: 0, lastTime: 0, history: [] };
4
+ const wrapped = ((...args) => {
5
+ const start = performance.now ? performance.now() : Date.now();
6
+ stats.calls += 1;
7
+ try {
8
+ const result = fn(...args);
9
+ if (result instanceof Promise) {
10
+ return result
11
+ .then((res) => {
12
+ const end = performance.now
13
+ ? performance.now()
14
+ : Date.now();
15
+ stats.lastTime = end - start;
16
+ stats.history.push(stats.lastTime);
17
+ if (stats.history.length > maxHistory)
18
+ stats.history.shift();
19
+ if (log) {
20
+ const bold = '\x1b[1m';
21
+ const cyan = '\x1b[36m';
22
+ const reset = '\x1b[0m';
23
+ const prefix = color ? `${bold}${cyan}[function-trace]${reset}` : '[function-trace]';
24
+ console.log(`${prefix} ${fn.name || 'anonymous'} executed in ${stats.lastTime.toFixed(2)}ms`);
25
+ }
26
+ return res;
27
+ })
28
+ .catch((err) => {
29
+ stats.errors += 1;
30
+ throw err;
31
+ });
32
+ }
33
+ else {
34
+ const end = performance.now ? performance.now() : Date.now();
35
+ stats.lastTime = end - start;
36
+ stats.history.push(stats.lastTime);
37
+ if (stats.history.length > maxHistory)
38
+ stats.history.shift();
39
+ if (log) {
40
+ const bold = '\x1b[1m';
41
+ const cyan = '\x1b[36m';
42
+ const reset = '\x1b[0m';
43
+ const prefix = color ? `${bold}${cyan}[function-trace]${reset}` : '[function-trace]';
44
+ console.log(`${prefix} ${fn.name || 'anonymous'} executed in ${stats.lastTime.toFixed(2)}ms`);
45
+ }
46
+ return result;
47
+ }
48
+ }
49
+ catch (err) {
50
+ stats.errors += 1;
51
+ throw err;
52
+ }
53
+ });
54
+ wrapped.stats = stats;
55
+ return wrapped;
56
+ }
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface TraceOptions {
2
+ log?: boolean;
3
+ maxHistory?: number;
4
+ }
5
+ export interface TraceStats {
6
+ calls: number;
7
+ errors: number;
8
+ lastTime: number;
9
+ history: number[];
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IACzB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../tests/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import { trace } from "../src/index.js";
2
+ console.log("Running func-trace tests...");
3
+ const sum = () => {
4
+ return 1 + 2 + 3 + 4 + 5;
5
+ };
6
+ const tracedSum = trace(sum, { log: true });
7
+ tracedSum();
8
+ tracedSum();
9
+ tracedSum();
10
+ console.log("Sum stats:", tracedSum.stats);
11
+ console.log("----");
12
+ // Sync function
13
+ const multiply = trace((a, b) => a * b, { log: true });
14
+ multiply(3, 4);
15
+ // Async function
16
+ const fetchTodo = trace(async (id) => {
17
+ const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
18
+ return res.json();
19
+ }, { log: true });
20
+ await fetchTodo(1);
21
+ // Inspect stats
22
+ console.log(fetchTodo.stats);
23
+ console.log("----");
24
+ console.log("Multiply result:", multiply(5, 6));
25
+ console.log("Multiply stats:");
26
+ console.log(multiply.stats);
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../tests/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAC3C,MAAM,GAAG,GAAG,GAAG,EAAE;IACb,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,SAAS,EAAE,CAAC;AACZ,SAAS,EAAE,CAAC;AACZ,SAAS,EAAE,CAAC;AAEZ,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;AAC3C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACpB,gBAAgB;AAChB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;AACvD,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEf,iBAAiB;AACjB,MAAM,SAAS,GAAG,KAAK,CACnB,KAAK,EAAE,EAAU,EAAE,EAAE;IACjB,MAAM,GAAG,GAAG,MAAM,KAAK,CACnB,8CAA8C,EAAE,EAAE,CACrD,CAAC;IACF,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC,EACD,EAAE,GAAG,EAAE,IAAI,EAAE,CAChB,CAAC;AAEF,MAAM,SAAS,CAAC,CAAC,CAAC,CAAC;AAEnB,gBAAgB;AAChB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC7B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAGpB,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAChD,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AAC/B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface TraceOptions {
2
+ log?: boolean;
3
+ maxHistory?: number;
4
+ }
5
+ export interface TraceStats {
6
+ calls: number;
7
+ errors: number;
8
+ lastTime: number;
9
+ history: number[];
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IACzB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "function-trace",
3
+ "version": "0.1.0",
4
+ "description": "Tiny universal function profiler/logger for full-stack developers",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "prepublishOnly": "npm run build",
14
+ "test": "npm run build && node dist/tests/index.js"
15
+ },
16
+ "keywords": [
17
+ "trace",
18
+ "profiler",
19
+ "logger",
20
+ "performance",
21
+ "async",
22
+ "typescript"
23
+ ],
24
+ "license": "MIT",
25
+ "author": {
26
+ "name": "Masum Billah",
27
+ "email": "dev.billah@gmail.com",
28
+ "url": "https://masum-billah.vercel.app"
29
+ },
30
+ "devDependencies": {
31
+ "ts-node": "^10.9.2",
32
+ "tsup": "^7.0.0",
33
+ "typescript": "^5.0.0"
34
+ }
35
+ }
package/readme.md ADDED
@@ -0,0 +1,237 @@
1
+ # function-trace
2
+
3
+ > A tiny universal function profiler and logger for full-stack developers. Trace execution time, monitor function calls, and track errors with zero configuration.
4
+
5
+ ![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)
6
+ ![Version](https://img.shields.io/badge/Version-0.1.0-success.svg)
7
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5-blue.svg)
8
+
9
+ ## Features
10
+
11
+ ✨ **Lightweight** - Minimal overhead, perfect for production
12
+ ⚡ **Universal** - Works with sync and async functions
13
+ 📊 **Performance Tracking** - Automatic execution time measurement
14
+ 📈 **Statistics** - Built-in call counts, error tracking, and history
15
+ 🎨 **Beautiful Output** - Color-coded console logging
16
+ 📦 **Zero Dependencies** - Pure TypeScript, no external packages
17
+ 🔧 **Type-Safe** - Full TypeScript support with proper type inference
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install function-trace
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ### Basic Usage
28
+
29
+ ```typescript
30
+ import { trace } from 'function-trace';
31
+
32
+ // Wrap any function with trace
33
+ const add = trace((a: number, b: number) => a + b, { log: true });
34
+
35
+ const result = add(5, 3);
36
+ // Output: [function-trace] anonymous executed in 0.05ms
37
+
38
+ console.log(add.stats); // { calls: 1, errors: 0, lastTime: 0.05, history: [0.05] }
39
+ ```
40
+
41
+ ### Synchronous Functions
42
+
43
+ ```typescript
44
+ import { trace } from 'function-trace';
45
+
46
+ const sum = () => {
47
+ return 1 + 2 + 3 + 4 + 5;
48
+ };
49
+
50
+ const tracedSum = trace(sum, { log: true });
51
+
52
+ tracedSum(); // [function-trace] sum executed in 0.02ms
53
+ tracedSum(); // [function-trace] sum executed in 0.01ms
54
+ tracedSum(); // [function-trace] sum executed in 0.02ms
55
+
56
+ console.log(tracedSum.stats);
57
+ // {
58
+ // calls: 3,
59
+ // errors: 0,
60
+ // lastTime: 0.02,
61
+ // history: [0.02, 0.01, 0.02]
62
+ // }
63
+ ```
64
+
65
+ ### Asynchronous Functions
66
+
67
+ ```typescript
68
+ import { trace } from 'function-trace';
69
+
70
+ const fetchTodo = trace(
71
+ async (id: number) => {
72
+ const res = await fetch(
73
+ `https://jsonplaceholder.typicode.com/todos/${id}`
74
+ );
75
+ return res.json();
76
+ },
77
+ { log: true }
78
+ );
79
+
80
+ await fetchTodo(1);
81
+ // [function-trace] fetchTodo executed in 145.32ms
82
+
83
+ console.log(fetchTodo.stats);
84
+ // {
85
+ // calls: 1,
86
+ // errors: 0,
87
+ // lastTime: 145.32,
88
+ // history: [145.32]
89
+ // }
90
+ ```
91
+
92
+ ### Named Functions
93
+
94
+ ```typescript
95
+ import { trace } from 'function-trace';
96
+
97
+ const multiply = (a: number, b: number) => a * b;
98
+ const tracedMultiply = trace(multiply, { log: true });
99
+
100
+ tracedMultiply(3, 4);
101
+ // [function-trace] multiply executed in 0.03ms
102
+ ```
103
+
104
+ ## API Reference
105
+
106
+ ### `trace<F>(fn: F, options?: TraceOptions): F & { stats: TraceStats }`
107
+
108
+ Wraps a function with performance tracking and returns the wrapped function with stats.
109
+
110
+ #### Parameters
111
+
112
+ - **fn** - The function to trace (sync or async)
113
+ - **options** - Configuration object (optional)
114
+
115
+ #### Options
116
+
117
+ ```typescript
118
+ interface TraceOptions {
119
+ log?: boolean; // Enable console logging (default: false)
120
+ maxHistory?: number; // Number of execution times to keep (default: 50)
121
+ color?: boolean; // Enable colored output (default: true)
122
+ }
123
+ ```
124
+
125
+ #### Return Value
126
+
127
+ The wrapped function with attached `stats` property:
128
+
129
+ ```typescript
130
+ interface TraceStats {
131
+ calls: number; // Total number of calls
132
+ errors: number; // Total number of errors
133
+ lastTime: number; // Last execution time in ms
134
+ history: number[]; // Array of last N execution times
135
+ }
136
+ ```
137
+
138
+ ## Production Examples
139
+
140
+ ### Database Query Monitoring
141
+
142
+ ```typescript
143
+ import { trace } from 'function-trace';
144
+
145
+ const getUserById = trace(
146
+ async (userId: string) => {
147
+ // Your database query
148
+ const user = await db.users.findById(userId);
149
+ return user;
150
+ },
151
+ { log: true, maxHistory: 100 }
152
+ );
153
+
154
+ // Monitor performance over time
155
+ async function handleRequest(userId: string) {
156
+ const user = await getUserById(userId);
157
+
158
+ // Check if query is getting slower
159
+ const avgTime =
160
+ getUserById.stats.history.reduce((a, b) => a + b, 0) /
161
+ getUserById.stats.history.length;
162
+
163
+ if (avgTime > 100) {
164
+ console.warn('Database query is getting slow');
165
+ }
166
+
167
+ return user;
168
+ }
169
+ ```
170
+
171
+ ### API Endpoint Monitoring
172
+
173
+ ```typescript
174
+ import { trace } from 'function-trace';
175
+
176
+ const apiCall = trace(
177
+ async (url: string) => {
178
+ const response = await fetch(url);
179
+ return response.json();
180
+ },
181
+ { log: true, maxHistory: 200 }
182
+ );
183
+
184
+ // Track API performance
185
+ console.log(`Total API calls: ${apiCall.stats.calls}`);
186
+ console.log(`Failed calls: ${apiCall.stats.errors}`);
187
+ console.log(`Last response time: ${apiCall.stats.lastTime}ms`);
188
+ ```
189
+
190
+ ### Function Performance Alerts
191
+
192
+ ```typescript
193
+ import { trace } from 'function-trace';
194
+
195
+ const criticalOperation = trace(
196
+ async () => {
197
+ // Some critical operation
198
+ },
199
+ { log: true, maxHistory: 50 }
200
+ );
201
+
202
+ async function executeWithAlert() {
203
+ await criticalOperation();
204
+
205
+ const avgTime =
206
+ criticalOperation.stats.history.reduce((a, b) => a + b, 0) /
207
+ criticalOperation.stats.history.length;
208
+
209
+ if (avgTime > 1000) {
210
+ // Send alert to monitoring service
211
+ console.error('⚠️ Operation exceeded SLA threshold');
212
+ }
213
+ }
214
+ ```
215
+
216
+ ## Best Practices
217
+
218
+ 1. **Enable logging in development** - Use `log: true` during development for instant feedback
219
+ 2. **Disable logging in production** - Set `log: false` for performance-critical paths
220
+ 3. **Adjust history size** - Use `maxHistory` based on your monitoring needs
221
+ 4. **Track errors** - Use `stats.errors` to identify failing operations
222
+ 5. **Analyze history** - Review `history` array for performance trends
223
+
224
+ ## Performance Considerations
225
+
226
+ - Minimal overhead (~0.05ms per call)
227
+ - Memory efficient with configurable history size
228
+ - No garbage collection pressure with bounded history array
229
+ - Suitable for high-frequency function calls
230
+
231
+ ## License
232
+
233
+ MIT © [Masum Billah](https://masum-billah.vercel.app)
234
+
235
+ ## Contributing
236
+
237
+ Contributions are welcome! Feel free to submit a Pull Request.