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.
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +57 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/types/index.d.ts +11 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/tests/index.d.ts +2 -0
- package/dist/tests/index.d.ts.map +1 -0
- package/dist/tests/index.js +27 -0
- package/dist/tests/index.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +35 -0
- package/readme.md +237 -0
package/dist/index.d.ts
ADDED
|
@@ -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":"AAcA,MAAM,UAAU,KAAK,CACjB,EAAK,EACL,UAAwB,EAAE;IAE1B,MAAM,EAAE,GAAG,GAAG,KAAK,EAAE,UAAU,GAAG,EAAE,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAC/D,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,EAAE,CAAC;wBACN,MAAM,IAAI,GAAG,SAAS,CAAC;wBACvB,MAAM,IAAI,GAAG,UAAU,CAAC;wBACxB,MAAM,KAAK,GAAG,SAAS,CAAC;wBACxB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,mBAAmB,KAAK,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;wBACrF,OAAO,CAAC,GAAG,CACP,GAAG,MAAM,IACL,EAAE,CAAC,IAAI,IAAI,WACf,gBAAgB,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAChD,CAAC;oBACN,CAAC;oBACD,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,EAAE,CAAC;oBACN,MAAM,IAAI,GAAG,SAAS,CAAC;oBACvB,MAAM,IAAI,GAAG,UAAU,CAAC;oBACxB,MAAM,KAAK,GAAG,SAAS,CAAC;oBACxB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,mBAAmB,KAAK,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;oBACrF,OAAO,CAAC,GAAG,CACP,GAAG,MAAM,IACL,EAAE,CAAC,IAAI,IAAI,WACf,gBAAgB,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAChD,CAAC;gBACN,CAAC;gBACD,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 @@
|
|
|
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 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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
|
+

|
|
6
|
+

|
|
7
|
+

|
|
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.
|