flow-debugger 1.0.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/PORTFOLIO_README_SECTION.md +177 -0
- package/README.md +251 -0
- package/dashboard/app.js +339 -0
- package/dashboard/index.html +168 -0
- package/dashboard/style.css +846 -0
- package/dist/cjs/core/Analytics.js +174 -0
- package/dist/cjs/core/Analytics.js.map +1 -0
- package/dist/cjs/core/Classifier.js +66 -0
- package/dist/cjs/core/Classifier.js.map +1 -0
- package/dist/cjs/core/HealthMonitor.js +79 -0
- package/dist/cjs/core/HealthMonitor.js.map +1 -0
- package/dist/cjs/core/RootCause.js +89 -0
- package/dist/cjs/core/RootCause.js.map +1 -0
- package/dist/cjs/core/Sampler.js +34 -0
- package/dist/cjs/core/Sampler.js.map +1 -0
- package/dist/cjs/core/Timeline.js +90 -0
- package/dist/cjs/core/Timeline.js.map +1 -0
- package/dist/cjs/core/TraceEngine.js +222 -0
- package/dist/cjs/core/TraceEngine.js.map +1 -0
- package/dist/cjs/core/types.js +21 -0
- package/dist/cjs/core/types.js.map +1 -0
- package/dist/cjs/index.js +46 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/integrations/axios.js +136 -0
- package/dist/cjs/integrations/axios.js.map +1 -0
- package/dist/cjs/integrations/fetch.js +153 -0
- package/dist/cjs/integrations/fetch.js.map +1 -0
- package/dist/cjs/integrations/mongo.js +111 -0
- package/dist/cjs/integrations/mongo.js.map +1 -0
- package/dist/cjs/integrations/mysql.js +212 -0
- package/dist/cjs/integrations/mysql.js.map +1 -0
- package/dist/cjs/integrations/postgres.js +182 -0
- package/dist/cjs/integrations/postgres.js.map +1 -0
- package/dist/cjs/integrations/redis.js +105 -0
- package/dist/cjs/integrations/redis.js.map +1 -0
- package/dist/cjs/middleware/express.js +255 -0
- package/dist/cjs/middleware/express.js.map +1 -0
- package/dist/esm/core/Analytics.js +170 -0
- package/dist/esm/core/Analytics.js.map +1 -0
- package/dist/esm/core/Classifier.js +61 -0
- package/dist/esm/core/Classifier.js.map +1 -0
- package/dist/esm/core/HealthMonitor.js +75 -0
- package/dist/esm/core/HealthMonitor.js.map +1 -0
- package/dist/esm/core/RootCause.js +86 -0
- package/dist/esm/core/RootCause.js.map +1 -0
- package/dist/esm/core/Sampler.js +30 -0
- package/dist/esm/core/Sampler.js.map +1 -0
- package/dist/esm/core/Timeline.js +86 -0
- package/dist/esm/core/Timeline.js.map +1 -0
- package/dist/esm/core/TraceEngine.js +217 -0
- package/dist/esm/core/TraceEngine.js.map +1 -0
- package/dist/esm/core/types.js +18 -0
- package/dist/esm/core/types.js.map +1 -0
- package/dist/esm/index.js +22 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/integrations/axios.js +133 -0
- package/dist/esm/integrations/axios.js.map +1 -0
- package/dist/esm/integrations/fetch.js +149 -0
- package/dist/esm/integrations/fetch.js.map +1 -0
- package/dist/esm/integrations/mongo.js +107 -0
- package/dist/esm/integrations/mongo.js.map +1 -0
- package/dist/esm/integrations/mysql.js +209 -0
- package/dist/esm/integrations/mysql.js.map +1 -0
- package/dist/esm/integrations/postgres.js +179 -0
- package/dist/esm/integrations/postgres.js.map +1 -0
- package/dist/esm/integrations/redis.js +102 -0
- package/dist/esm/integrations/redis.js.map +1 -0
- package/dist/esm/middleware/express.js +219 -0
- package/dist/esm/middleware/express.js.map +1 -0
- package/dist/types/core/Analytics.d.ts +35 -0
- package/dist/types/core/Analytics.d.ts.map +1 -0
- package/dist/types/core/Classifier.d.ts +21 -0
- package/dist/types/core/Classifier.d.ts.map +1 -0
- package/dist/types/core/HealthMonitor.d.ts +14 -0
- package/dist/types/core/HealthMonitor.d.ts.map +1 -0
- package/dist/types/core/RootCause.d.ts +12 -0
- package/dist/types/core/RootCause.d.ts.map +1 -0
- package/dist/types/core/Sampler.d.ts +13 -0
- package/dist/types/core/Sampler.d.ts.map +1 -0
- package/dist/types/core/Timeline.d.ts +22 -0
- package/dist/types/core/Timeline.d.ts.map +1 -0
- package/dist/types/core/TraceEngine.d.ts +47 -0
- package/dist/types/core/TraceEngine.d.ts.map +1 -0
- package/dist/types/core/types.d.ts +118 -0
- package/dist/types/core/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/integrations/axios.d.ts +22 -0
- package/dist/types/integrations/axios.d.ts.map +1 -0
- package/dist/types/integrations/fetch.d.ts +25 -0
- package/dist/types/integrations/fetch.d.ts.map +1 -0
- package/dist/types/integrations/mongo.d.ts +26 -0
- package/dist/types/integrations/mongo.d.ts.map +1 -0
- package/dist/types/integrations/mysql.d.ts +20 -0
- package/dist/types/integrations/mysql.d.ts.map +1 -0
- package/dist/types/integrations/postgres.d.ts +20 -0
- package/dist/types/integrations/postgres.d.ts.map +1 -0
- package/dist/types/integrations/redis.d.ts +20 -0
- package/dist/types/integrations/redis.d.ts.map +1 -0
- package/dist/types/middleware/express.d.ts +39 -0
- package/dist/types/middleware/express.d.ts.map +1 -0
- package/example/server.ts +234 -0
- package/jest.config.js +8 -0
- package/package.json +110 -0
- package/portfolio-repo/APIRESPONSE DASH.png +0 -0
- package/portfolio-repo/PAYLOAD.png +0 -0
- package/portfolio-repo/README.md +182 -0
- package/src/core/Analytics.ts +209 -0
- package/src/core/Classifier.ts +82 -0
- package/src/core/HealthMonitor.ts +92 -0
- package/src/core/RootCause.ts +105 -0
- package/src/core/Sampler.ts +35 -0
- package/src/core/Timeline.ts +108 -0
- package/src/core/TraceEngine.ts +266 -0
- package/src/core/types.ts +170 -0
- package/src/index.ts +42 -0
- package/src/integrations/axios.ts +164 -0
- package/src/integrations/fetch.ts +172 -0
- package/src/integrations/mongo.ts +130 -0
- package/src/integrations/mysql.ts +239 -0
- package/src/integrations/postgres.ts +217 -0
- package/src/integrations/redis.ts +122 -0
- package/src/middleware/express.ts +264 -0
- package/tests/Analytics.test.ts +136 -0
- package/tests/Classifier.test.ts +57 -0
- package/tests/RootCause.test.ts +69 -0
- package/tests/TraceEngine.test.ts +110 -0
- package/tsconfig.cjs.json +9 -0
- package/tsconfig.esm.json +9 -0
- package/tsconfig.json +31 -0
- package/tsconfig.types.json +8 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// flow-debugger — PostgreSQL Auto-Instrument (pg)
|
|
3
|
+
// Patches pg Pool/Client to trace all queries
|
|
4
|
+
// ─────────────────────────────────────────────────────────────
|
|
5
|
+
import { DEFAULT_CONFIG } from '../core/types';
|
|
6
|
+
import { classifyQuery } from '../core/Classifier';
|
|
7
|
+
/**
|
|
8
|
+
* Auto-instrument pg Pool/Client to trace all queries.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* pgTracer(pool, { getTracer: () => currentTracer })
|
|
12
|
+
*
|
|
13
|
+
* Output:
|
|
14
|
+
* Postgres SELECT orders → 18ms ✔
|
|
15
|
+
* Postgres UPDATE invoice → timeout ❌
|
|
16
|
+
*/
|
|
17
|
+
export function pgTracer(pool, options) {
|
|
18
|
+
try {
|
|
19
|
+
if (pool.__flowDebuggerPatched)
|
|
20
|
+
return;
|
|
21
|
+
pool.__flowDebuggerPatched = true;
|
|
22
|
+
const config = { ...DEFAULT_CONFIG, ...options?.config };
|
|
23
|
+
const originalQuery = pool.query.bind(pool);
|
|
24
|
+
pool.query = function tracedQuery(...args) {
|
|
25
|
+
const tracer = options?.getTracer?.();
|
|
26
|
+
if (!tracer) {
|
|
27
|
+
return originalQuery(...args);
|
|
28
|
+
}
|
|
29
|
+
const sql = extractSql(args);
|
|
30
|
+
const operation = extractPgOperation(sql);
|
|
31
|
+
const stepName = `Postgres ${operation}`;
|
|
32
|
+
const startTime = performance.now();
|
|
33
|
+
// Detect if callback is provided
|
|
34
|
+
const lastArg = args[args.length - 1];
|
|
35
|
+
if (typeof lastArg === 'function') {
|
|
36
|
+
// Callback style
|
|
37
|
+
const callback = lastArg;
|
|
38
|
+
args[args.length - 1] = function (err, result) {
|
|
39
|
+
recordStep(tracer, stepName, startTime, err, sql, operation, config);
|
|
40
|
+
callback(err, result);
|
|
41
|
+
};
|
|
42
|
+
return originalQuery(...args);
|
|
43
|
+
}
|
|
44
|
+
// Promise style
|
|
45
|
+
const promise = originalQuery(...args);
|
|
46
|
+
if (promise && typeof promise.then === 'function') {
|
|
47
|
+
return promise.then((result) => {
|
|
48
|
+
recordStep(tracer, stepName, startTime, null, sql, operation, config);
|
|
49
|
+
return result;
|
|
50
|
+
}, (err) => {
|
|
51
|
+
recordStep(tracer, stepName, startTime, err, sql, operation, config);
|
|
52
|
+
throw err;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return promise;
|
|
56
|
+
};
|
|
57
|
+
// Also patch connect() to instrument clients from the pool
|
|
58
|
+
if (pool.connect && !pool.__connectPatched) {
|
|
59
|
+
pool.__connectPatched = true;
|
|
60
|
+
const originalConnect = pool.connect.bind(pool);
|
|
61
|
+
pool.connect = function tracedConnect(...connectArgs) {
|
|
62
|
+
const lastArg = connectArgs[connectArgs.length - 1];
|
|
63
|
+
if (typeof lastArg === 'function') {
|
|
64
|
+
// Callback style: connect((err, client, done) => { ... })
|
|
65
|
+
const callback = lastArg;
|
|
66
|
+
connectArgs[connectArgs.length - 1] = function (err, client, done) {
|
|
67
|
+
if (client && !client.__flowDebuggerPatched) {
|
|
68
|
+
patchClient(client, options, config);
|
|
69
|
+
}
|
|
70
|
+
callback(err, client, done);
|
|
71
|
+
};
|
|
72
|
+
return originalConnect(...connectArgs);
|
|
73
|
+
}
|
|
74
|
+
// Promise style
|
|
75
|
+
const promise = originalConnect(...connectArgs);
|
|
76
|
+
if (promise && typeof promise.then === 'function') {
|
|
77
|
+
return promise.then((client) => {
|
|
78
|
+
if (client && !client.__flowDebuggerPatched) {
|
|
79
|
+
patchClient(client, options, config);
|
|
80
|
+
}
|
|
81
|
+
return client;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return promise;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (_) {
|
|
89
|
+
// Production-safe: never crash
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Patch an individual pg Client's query method */
|
|
93
|
+
function patchClient(client, options, config) {
|
|
94
|
+
try {
|
|
95
|
+
client.__flowDebuggerPatched = true;
|
|
96
|
+
const originalClientQuery = client.query.bind(client);
|
|
97
|
+
client.query = function tracedClientQuery(...args) {
|
|
98
|
+
const tracer = options?.getTracer?.();
|
|
99
|
+
if (!tracer) {
|
|
100
|
+
return originalClientQuery(...args);
|
|
101
|
+
}
|
|
102
|
+
const sql = extractSql(args);
|
|
103
|
+
const operation = extractPgOperation(sql);
|
|
104
|
+
const stepName = `Postgres ${operation}`;
|
|
105
|
+
const startTime = performance.now();
|
|
106
|
+
const lastArg = args[args.length - 1];
|
|
107
|
+
if (typeof lastArg === 'function') {
|
|
108
|
+
const callback = lastArg;
|
|
109
|
+
args[args.length - 1] = function (err, result) {
|
|
110
|
+
recordStep(tracer, stepName, startTime, err, sql, operation, config);
|
|
111
|
+
callback(err, result);
|
|
112
|
+
};
|
|
113
|
+
return originalClientQuery(...args);
|
|
114
|
+
}
|
|
115
|
+
const promise = originalClientQuery(...args);
|
|
116
|
+
if (promise && typeof promise.then === 'function') {
|
|
117
|
+
return promise.then((result) => {
|
|
118
|
+
recordStep(tracer, stepName, startTime, null, sql, operation, config);
|
|
119
|
+
return result;
|
|
120
|
+
}, (err) => {
|
|
121
|
+
recordStep(tracer, stepName, startTime, err, sql, operation, config);
|
|
122
|
+
throw err;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return promise;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (_) { }
|
|
129
|
+
}
|
|
130
|
+
/** Record a step from query execution */
|
|
131
|
+
function recordStep(tracer, stepName, startTime, err, sql, operation, config) {
|
|
132
|
+
try {
|
|
133
|
+
const endTime = performance.now();
|
|
134
|
+
const duration = endTime - startTime;
|
|
135
|
+
const status = err ? 'error' : 'success';
|
|
136
|
+
const classification = classifyQuery(duration, status, config);
|
|
137
|
+
const step = {
|
|
138
|
+
name: stepName,
|
|
139
|
+
service: 'postgres',
|
|
140
|
+
status,
|
|
141
|
+
classification,
|
|
142
|
+
startTime,
|
|
143
|
+
endTime,
|
|
144
|
+
duration,
|
|
145
|
+
error: err?.message,
|
|
146
|
+
stackTrace: err?.stack,
|
|
147
|
+
metadata: { sql: sql.substring(0, 200), operation },
|
|
148
|
+
};
|
|
149
|
+
tracer.addStep(step);
|
|
150
|
+
if (duration > (config.slowQueryThreshold ?? 300)) {
|
|
151
|
+
try {
|
|
152
|
+
(config.logger || console.log)(`\x1b[33m⚠ Slow PostgreSQL query: ${stepName} (${Math.round(duration)}ms)\n ${sql.substring(0, 100)}\x1b[0m`);
|
|
153
|
+
}
|
|
154
|
+
catch (_) { }
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (_) { }
|
|
158
|
+
}
|
|
159
|
+
/** Extract SQL string from query arguments */
|
|
160
|
+
function extractSql(args) {
|
|
161
|
+
if (typeof args[0] === 'string')
|
|
162
|
+
return args[0];
|
|
163
|
+
if (args[0] && typeof args[0] === 'object' && args[0].text)
|
|
164
|
+
return args[0].text;
|
|
165
|
+
return 'unknown';
|
|
166
|
+
}
|
|
167
|
+
/** Extract the SQL operation type from a query string */
|
|
168
|
+
function extractPgOperation(sql) {
|
|
169
|
+
const trimmed = sql.trim().toUpperCase();
|
|
170
|
+
const match = trimmed.match(/^(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|WITH)\b/);
|
|
171
|
+
if (match) {
|
|
172
|
+
const op = match[1];
|
|
173
|
+
const tableMatch = sql.match(/(?:FROM|INTO|UPDATE|TABLE|JOIN)\s+"?(\w+)"?/i);
|
|
174
|
+
const table = tableMatch ? tableMatch[1] : '';
|
|
175
|
+
return table ? `${op} ${table}` : op;
|
|
176
|
+
}
|
|
177
|
+
return sql.substring(0, 30);
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=postgres.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../../src/integrations/postgres.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// flow-debugger — Redis Auto-Instrument
|
|
3
|
+
// Wraps Redis client commands to trace all operations
|
|
4
|
+
// ─────────────────────────────────────────────────────────────
|
|
5
|
+
import { DEFAULT_CONFIG } from '../core/types';
|
|
6
|
+
import { classifyQuery } from '../core/Classifier';
|
|
7
|
+
/** Commands to trace */
|
|
8
|
+
const TRACED_COMMANDS = [
|
|
9
|
+
'get', 'set', 'del', 'exists', 'expire', 'ttl',
|
|
10
|
+
'hget', 'hset', 'hdel', 'hgetall', 'hmset', 'hmget',
|
|
11
|
+
'lpush', 'rpush', 'lpop', 'rpop', 'lrange', 'llen',
|
|
12
|
+
'sadd', 'srem', 'smembers', 'sismember',
|
|
13
|
+
'zadd', 'zrem', 'zrange', 'zrank', 'zscore',
|
|
14
|
+
'incr', 'decr', 'incrby', 'decrby',
|
|
15
|
+
'setex', 'setnx', 'mget', 'mset',
|
|
16
|
+
'publish', 'subscribe',
|
|
17
|
+
'eval', 'evalsha',
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Auto-instrument a Redis client (ioredis or node-redis v4).
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* redisTracer(redisClient, { getTracer: () => currentTracer })
|
|
24
|
+
*
|
|
25
|
+
* Output:
|
|
26
|
+
* Redis SET session → 3ms ✔
|
|
27
|
+
* Redis GET cache → timeout ❌
|
|
28
|
+
*/
|
|
29
|
+
export function redisTracer(client, options) {
|
|
30
|
+
try {
|
|
31
|
+
if (client.__flowDebuggerPatched)
|
|
32
|
+
return;
|
|
33
|
+
client.__flowDebuggerPatched = true;
|
|
34
|
+
const config = { ...DEFAULT_CONFIG, ...options?.config };
|
|
35
|
+
for (const command of TRACED_COMMANDS) {
|
|
36
|
+
if (typeof client[command] !== 'function')
|
|
37
|
+
continue;
|
|
38
|
+
const original = client[command].bind(client);
|
|
39
|
+
client[command] = async function tracedCommand(...args) {
|
|
40
|
+
const tracer = options?.getTracer?.();
|
|
41
|
+
if (!tracer) {
|
|
42
|
+
return original(...args);
|
|
43
|
+
}
|
|
44
|
+
const key = args[0] !== undefined ? String(args[0]).substring(0, 50) : '';
|
|
45
|
+
const stepName = `Redis ${command.toUpperCase()} ${key}`;
|
|
46
|
+
const startTime = performance.now();
|
|
47
|
+
let status = 'success';
|
|
48
|
+
let error;
|
|
49
|
+
let stackTrace;
|
|
50
|
+
try {
|
|
51
|
+
const result = await original(...args);
|
|
52
|
+
const endTime = performance.now();
|
|
53
|
+
const duration = endTime - startTime;
|
|
54
|
+
const classification = classifyQuery(duration, status, config);
|
|
55
|
+
tracer.addStep({
|
|
56
|
+
name: stepName,
|
|
57
|
+
service: 'redis',
|
|
58
|
+
status,
|
|
59
|
+
classification,
|
|
60
|
+
startTime,
|
|
61
|
+
endTime,
|
|
62
|
+
duration,
|
|
63
|
+
metadata: { command: command.toUpperCase(), key },
|
|
64
|
+
});
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
69
|
+
error = e.message;
|
|
70
|
+
stackTrace = e.stack;
|
|
71
|
+
// Detect connection errors as CRITICAL
|
|
72
|
+
const isConnectionError = error.includes('ECONNREFUSED') ||
|
|
73
|
+
error.includes('ECONNRESET') ||
|
|
74
|
+
error.includes('ETIMEDOUT') ||
|
|
75
|
+
error.includes('connection') ||
|
|
76
|
+
error.includes('Connection');
|
|
77
|
+
status = isConnectionError ? 'timeout' : 'error';
|
|
78
|
+
const endTime = performance.now();
|
|
79
|
+
const duration = endTime - startTime;
|
|
80
|
+
const classification = classifyQuery(duration, status, config);
|
|
81
|
+
tracer.addStep({
|
|
82
|
+
name: stepName,
|
|
83
|
+
service: 'redis',
|
|
84
|
+
status,
|
|
85
|
+
classification,
|
|
86
|
+
startTime,
|
|
87
|
+
endTime,
|
|
88
|
+
duration,
|
|
89
|
+
error,
|
|
90
|
+
stackTrace,
|
|
91
|
+
metadata: { command: command.toUpperCase(), key },
|
|
92
|
+
});
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (_) {
|
|
99
|
+
// Production-safe: never crash
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../../../src/integrations/redis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────
|
|
2
|
+
// flow-debugger — Express Middleware
|
|
3
|
+
// Auto-traces every request, provides /__debugger API + dashboard
|
|
4
|
+
// ─────────────────────────────────────────────────────────────
|
|
5
|
+
import { TraceEngine } from '../core/TraceEngine';
|
|
6
|
+
import { Analytics } from '../core/Analytics';
|
|
7
|
+
import { Sampler } from '../core/Sampler';
|
|
8
|
+
import { DEFAULT_CONFIG } from '../core/types';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
// AsyncLocalStorage for automatic tracer context propagation
|
|
12
|
+
let asyncLocalStorage;
|
|
13
|
+
try {
|
|
14
|
+
const { AsyncLocalStorage } = require('async_hooks');
|
|
15
|
+
asyncLocalStorage = new AsyncLocalStorage();
|
|
16
|
+
}
|
|
17
|
+
catch (_) {
|
|
18
|
+
// Fallback for environments without async_hooks
|
|
19
|
+
asyncLocalStorage = null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create the flow-debugger Express middleware.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* const debugger = flowDebugger({ slowThreshold: 500 });
|
|
26
|
+
* app.use(debugger.middleware);
|
|
27
|
+
*
|
|
28
|
+
* // Auto-instrument databases
|
|
29
|
+
* mongoTracer(mongoose, { getTracer: debugger.getTracer });
|
|
30
|
+
* mysqlTracer(pool, { getTracer: debugger.getTracer });
|
|
31
|
+
*
|
|
32
|
+
* // Dashboard at: GET /__debugger/dashboard
|
|
33
|
+
* // API at: GET /__debugger
|
|
34
|
+
*/
|
|
35
|
+
export function flowDebugger(config) {
|
|
36
|
+
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
37
|
+
const engine = new TraceEngine(mergedConfig);
|
|
38
|
+
const analytics = new Analytics(mergedConfig.maxTraces);
|
|
39
|
+
const sampler = new Sampler(mergedConfig.samplingRate, mergedConfig.alwaysSampleErrors);
|
|
40
|
+
// Current tracer per async context
|
|
41
|
+
let fallbackTracer = null;
|
|
42
|
+
const getTracer = () => {
|
|
43
|
+
if (asyncLocalStorage) {
|
|
44
|
+
try {
|
|
45
|
+
const store = asyncLocalStorage.getStore();
|
|
46
|
+
return store?.tracer || null;
|
|
47
|
+
}
|
|
48
|
+
catch (_) { }
|
|
49
|
+
}
|
|
50
|
+
return fallbackTracer;
|
|
51
|
+
};
|
|
52
|
+
const middleware = (req, res, next) => {
|
|
53
|
+
try {
|
|
54
|
+
// Skip debugger endpoints
|
|
55
|
+
if (req.path?.startsWith('/__debugger')) {
|
|
56
|
+
return handleDebuggerRoute(req, res, next, analytics, mergedConfig);
|
|
57
|
+
}
|
|
58
|
+
if (!mergedConfig.enabled)
|
|
59
|
+
return next();
|
|
60
|
+
// Sampling
|
|
61
|
+
if (!sampler.shouldSample())
|
|
62
|
+
return next();
|
|
63
|
+
const tracer = engine.startTrace(req.path || req.url, req.method);
|
|
64
|
+
req.tracer = tracer;
|
|
65
|
+
req.traceId = tracer.getTraceId();
|
|
66
|
+
// Set header for client correlation
|
|
67
|
+
res.setHeader('X-Trace-Id', tracer.getTraceId());
|
|
68
|
+
const run = () => {
|
|
69
|
+
fallbackTracer = tracer;
|
|
70
|
+
// Calculate payload size if body exists
|
|
71
|
+
let payloadSize;
|
|
72
|
+
try {
|
|
73
|
+
if (req.body) {
|
|
74
|
+
const bodyStr = JSON.stringify(req.body);
|
|
75
|
+
payloadSize = Buffer.byteLength(bodyStr, 'utf8');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (_) {
|
|
79
|
+
// ignore
|
|
80
|
+
}
|
|
81
|
+
// Hook into response finish
|
|
82
|
+
const originalEnd = res.end;
|
|
83
|
+
res.end = function (...args) {
|
|
84
|
+
try {
|
|
85
|
+
const trace = tracer.end(res.statusCode);
|
|
86
|
+
// Add environment and payload size to trace
|
|
87
|
+
trace.environment = mergedConfig.environment;
|
|
88
|
+
trace.payloadSize = payloadSize;
|
|
89
|
+
analytics.record(trace);
|
|
90
|
+
// If error and we had skipped sampling, re-sample
|
|
91
|
+
}
|
|
92
|
+
catch (_) {
|
|
93
|
+
// never crash
|
|
94
|
+
}
|
|
95
|
+
fallbackTracer = null;
|
|
96
|
+
return originalEnd.apply(res, args);
|
|
97
|
+
};
|
|
98
|
+
next();
|
|
99
|
+
};
|
|
100
|
+
// Use AsyncLocalStorage if available
|
|
101
|
+
if (asyncLocalStorage) {
|
|
102
|
+
asyncLocalStorage.run({ tracer }, run);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
run();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (_) {
|
|
109
|
+
// Production-safe: if debugger fails, pass through
|
|
110
|
+
next();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return { middleware, engine, analytics, getTracer };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Handle /__debugger routes
|
|
117
|
+
*/
|
|
118
|
+
function handleDebuggerRoute(req, res, next, analytics, config) {
|
|
119
|
+
if (!config.enableDashboard)
|
|
120
|
+
return next();
|
|
121
|
+
try {
|
|
122
|
+
const subPath = req.path.replace('/__debugger', '') || '/';
|
|
123
|
+
switch (subPath) {
|
|
124
|
+
case '/':
|
|
125
|
+
case '/api':
|
|
126
|
+
// JSON analytics API
|
|
127
|
+
res.json(analytics.getReport());
|
|
128
|
+
break;
|
|
129
|
+
case '/dashboard': {
|
|
130
|
+
// Serve the HTML dashboard
|
|
131
|
+
const dashboardPath = path.resolve(__dirname, '../../dashboard/index.html');
|
|
132
|
+
if (fs.existsSync(dashboardPath)) {
|
|
133
|
+
res.sendFile(dashboardPath);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// Fallback: inline minimal dashboard
|
|
137
|
+
res.send(getInlineDashboard());
|
|
138
|
+
}
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case '/dashboard/style.css': {
|
|
142
|
+
const cssPath = path.resolve(__dirname, '../../dashboard/style.css');
|
|
143
|
+
if (fs.existsSync(cssPath)) {
|
|
144
|
+
res.type('text/css').sendFile(cssPath);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
res.status(404).send('Not found');
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
case '/dashboard/app.js': {
|
|
152
|
+
const jsPath = path.resolve(__dirname, '../../dashboard/app.js');
|
|
153
|
+
if (fs.existsSync(jsPath)) {
|
|
154
|
+
res.type('application/javascript').sendFile(jsPath);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
res.status(404).send('Not found');
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case '/health':
|
|
162
|
+
res.json(analytics.getHealthMonitor().getAllHealth());
|
|
163
|
+
break;
|
|
164
|
+
case '/endpoint': {
|
|
165
|
+
const endpoint = req.query?.path || req.query?.endpoint;
|
|
166
|
+
if (endpoint) {
|
|
167
|
+
const report = analytics.getEndpointReport(String(endpoint));
|
|
168
|
+
res.json(report || { error: 'Endpoint not found' });
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
res.json({ error: 'Provide ?path=/your/endpoint' });
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case '/search': {
|
|
176
|
+
const query = req.query?.q || req.query?.query;
|
|
177
|
+
const env = req.query?.env;
|
|
178
|
+
const limit = req.query?.limit ? parseInt(String(req.query.limit), 10) : 50;
|
|
179
|
+
if (query) {
|
|
180
|
+
const results = analytics.searchTraces(String(query), { env: env ? String(env) : undefined, limit });
|
|
181
|
+
res.json({ query, results, count: results.length });
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
res.json({ error: 'Provide ?q=search_term' });
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
default:
|
|
189
|
+
next();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
res.status(500).json({ error: 'Debugger dashboard error' });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/** Inline fallback dashboard if files aren't found */
|
|
197
|
+
function getInlineDashboard() {
|
|
198
|
+
return `<!DOCTYPE html>
|
|
199
|
+
<html lang="en">
|
|
200
|
+
<head>
|
|
201
|
+
<meta charset="UTF-8">
|
|
202
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
203
|
+
<title>Flow Debugger Dashboard</title>
|
|
204
|
+
<style>body{font-family:system-ui;background:#0a0a1a;color:#e0e0e0;padding:20px}
|
|
205
|
+
h1{color:#7c3aed}.card{background:#1a1a2e;border-radius:12px;padding:20px;margin:10px 0;border:1px solid #2a2a4a}</style>
|
|
206
|
+
</head>
|
|
207
|
+
<body>
|
|
208
|
+
<h1>🔍 Flow Debugger</h1>
|
|
209
|
+
<p>Dashboard files not found. API available at <a href="/__debugger" style="color:#7c3aed">/__debugger</a></p>
|
|
210
|
+
<div class="card" id="data">Loading...</div>
|
|
211
|
+
<script>
|
|
212
|
+
fetch('/__debugger').then(r=>r.json()).then(d=>{
|
|
213
|
+
document.getElementById('data').innerHTML='<pre>'+JSON.stringify(d,null,2)+'</pre>';
|
|
214
|
+
});
|
|
215
|
+
</script>
|
|
216
|
+
</body>
|
|
217
|
+
</html>`;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=express.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../../src/middleware/express.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Trace, EndpointStats, AnalyticsReport } from './types';
|
|
2
|
+
import { HealthMonitor } from './HealthMonitor';
|
|
3
|
+
export declare class Analytics {
|
|
4
|
+
private traces;
|
|
5
|
+
private maxTraces;
|
|
6
|
+
private startTime;
|
|
7
|
+
private healthMonitor;
|
|
8
|
+
constructor(maxTraces?: number);
|
|
9
|
+
/** Record a completed trace */
|
|
10
|
+
record(trace: Trace): void;
|
|
11
|
+
/** Get full analytics report */
|
|
12
|
+
getReport(): AnalyticsReport;
|
|
13
|
+
/** Get stats for a specific endpoint */
|
|
14
|
+
getEndpointReport(path: string): EndpointStats | null;
|
|
15
|
+
/** Get aggregated stats per endpoint */
|
|
16
|
+
private getEndpointStats;
|
|
17
|
+
/** Get service failure breakdown across all traces */
|
|
18
|
+
private getTopFailures;
|
|
19
|
+
/** Calculate service failure stats from a set of traces */
|
|
20
|
+
private getServiceFailures;
|
|
21
|
+
/** Clear all stored traces */
|
|
22
|
+
clear(): void;
|
|
23
|
+
/** Get raw trace count */
|
|
24
|
+
getTraceCount(): number;
|
|
25
|
+
/**
|
|
26
|
+
* Search traces by traceId, endpoint, or error message.
|
|
27
|
+
* Returns matching traces sorted by most recent first.
|
|
28
|
+
*/
|
|
29
|
+
searchTraces(query: string, options?: {
|
|
30
|
+
env?: string;
|
|
31
|
+
limit?: number;
|
|
32
|
+
}): Trace[];
|
|
33
|
+
getHealthMonitor(): HealthMonitor;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=Analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Analytics.d.ts","sourceRoot":"","sources":["../../../src/core/Analytics.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,KAAK,EACL,aAAa,EACb,eAAe,EAIlB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,qBAAa,SAAS;IAClB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,aAAa,CAAgB;gBAEzB,SAAS,SAAO;IAM5B,+BAA+B;IAC/B,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAkB1B,gCAAgC;IAChC,SAAS,IAAI,eAAe;IAmB5B,wCAAwC;IACxC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAKrD,wCAAwC;IACxC,OAAO,CAAC,gBAAgB;IAkDxB,sDAAsD;IACtD,OAAO,CAAC,cAAc;IAItB,2DAA2D;IAC3D,OAAO,CAAC,kBAAkB;IAsB1B,8BAA8B;IAC9B,KAAK,IAAI,IAAI;IAIb,0BAA0B;IAC1B,aAAa,IAAI,MAAM;IAIvB;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,KAAK,EAAE;IAwChF,gBAAgB,IAAI,aAAa;CAGpC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ClassificationLevel, StepStatus, TraceStep, DebuggerConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Classify a single step based on its duration and status.
|
|
4
|
+
*
|
|
5
|
+
* INFO → normal, <slowThreshold ms
|
|
6
|
+
* WARN → slow (>slowThreshold ms)
|
|
7
|
+
* ERROR → step failed
|
|
8
|
+
* CRITICAL → dependency down / timeout
|
|
9
|
+
*/
|
|
10
|
+
export declare function classify(duration: number, status: StepStatus, config: Pick<DebuggerConfig, 'slowThreshold'>): ClassificationLevel;
|
|
11
|
+
/**
|
|
12
|
+
* Classify an entire trace based on its steps.
|
|
13
|
+
* The trace gets the highest severity from any of its steps.
|
|
14
|
+
*/
|
|
15
|
+
export declare function classifyTrace(steps: TraceStep[], _totalDuration: number, config: Pick<DebuggerConfig, 'slowThreshold'>): ClassificationLevel;
|
|
16
|
+
/**
|
|
17
|
+
* Classify a database query specifically — used by integrations
|
|
18
|
+
* to detect slow queries with a dedicated threshold.
|
|
19
|
+
*/
|
|
20
|
+
export declare function classifyQuery(duration: number, status: StepStatus, config: Pick<DebuggerConfig, 'slowQueryThreshold'>): ClassificationLevel;
|
|
21
|
+
//# sourceMappingURL=Classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Classifier.d.ts","sourceRoot":"","sources":["../../../src/core/Classifier.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,cAAc,EACjB,MAAM,SAAS,CAAC;AAEjB;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,GAC9C,mBAAmB,CAOrB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,SAAS,EAAE,EAClB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,GAC9C,mBAAmB,CAuBrB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CACzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,oBAAoB,CAAC,GACnD,mBAAmB,CAOrB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TraceStep, HealthStatus, ServiceTag } from './types';
|
|
2
|
+
export declare class HealthMonitor {
|
|
3
|
+
private records;
|
|
4
|
+
/** Record a step result to update health tracking */
|
|
5
|
+
recordStep(step: TraceStep): void;
|
|
6
|
+
/** Get health status for a specific service */
|
|
7
|
+
getHealth(service: ServiceTag): HealthStatus | null;
|
|
8
|
+
/** Get health status for all tracked services */
|
|
9
|
+
getAllHealth(): HealthStatus[];
|
|
10
|
+
private toHealthStatus;
|
|
11
|
+
/** Reset all health records */
|
|
12
|
+
reset(): void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=HealthMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HealthMonitor.d.ts","sourceRoot":"","sources":["../../../src/core/HealthMonitor.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,SAAS,EACT,YAAY,EAEZ,UAAU,EACb,MAAM,SAAS,CAAC;AAUjB,qBAAa,aAAa;IACtB,OAAO,CAAC,OAAO,CAAmC;IAElD,qDAAqD;IACrD,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IA4BjC,+CAA+C;IAC/C,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI;IAMnD,iDAAiD;IACjD,YAAY,IAAI,YAAY,EAAE;IAI9B,OAAO,CAAC,cAAc;IAuBtB,+BAA+B;IAC/B,KAAK,IAAI,IAAI;CAGhB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TraceStep, RootCauseResult, DebuggerConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Detect the root cause of a trace failure or slowness.
|
|
4
|
+
*
|
|
5
|
+
* Algorithm:
|
|
6
|
+
* 1. If response is 500 and a step failed → root cause = first failed step
|
|
7
|
+
* 2. If a step timed out → root cause = timeout step (CRITICAL)
|
|
8
|
+
* 3. If DB/Redis slow and total latency high → root cause = slow dependency
|
|
9
|
+
* 4. If no failures but overall slow → root cause = slowest step
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectRootCause(steps: TraceStep[], statusCode: number | undefined, config: Pick<DebuggerConfig, 'slowThreshold' | 'slowQueryThreshold'>): RootCauseResult | null;
|
|
12
|
+
//# sourceMappingURL=RootCause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RootCause.d.ts","sourceRoot":"","sources":["../../../src/core/RootCause.ts"],"names":[],"mappings":"AAKA,OAAO,EACH,SAAS,EACT,eAAe,EACf,cAAc,EAEjB,MAAM,SAAS,CAAC;AAEjB;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC3B,KAAK,EAAE,SAAS,EAAE,EAClB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,oBAAoB,CAAC,GACrE,eAAe,GAAG,IAAI,CA2DxB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class Sampler {
|
|
2
|
+
private rate;
|
|
3
|
+
private alwaysSampleErrors;
|
|
4
|
+
constructor(rate?: number, alwaysSampleErrors?: boolean);
|
|
5
|
+
/** Should this request be sampled? */
|
|
6
|
+
shouldSample(): boolean;
|
|
7
|
+
/** Force sample if it's an error (if alwaysSampleErrors is true) */
|
|
8
|
+
shouldSampleError(): boolean;
|
|
9
|
+
/** Update sampling rate at runtime */
|
|
10
|
+
setRate(rate: number): void;
|
|
11
|
+
getRate(): number;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=Sampler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Sampler.d.ts","sourceRoot":"","sources":["../../../src/core/Sampler.ts"],"names":[],"mappings":"AAKA,qBAAa,OAAO;IAChB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,kBAAkB,CAAU;gBAExB,IAAI,SAAI,EAAE,kBAAkB,UAAO;IAK/C,sCAAsC;IACtC,YAAY,IAAI,OAAO;IAMvB,oEAAoE;IACpE,iBAAiB,IAAI,OAAO;IAI5B,sCAAsC;IACtC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3B,OAAO,IAAI,MAAM;CAGpB"}
|