flow-debugger 1.9.3 → 1.9.4
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/EXAMPLES.md +38 -0
- package/README.md +391 -266
- package/dist/cjs/index.js +10 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react_native.js +308 -0
- package/dist/cjs/react_native.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react_native.js +298 -0
- package/dist/esm/react_native.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/react_native.d.ts +54 -0
- package/dist/types/react_native.d.ts.map +1 -0
- package/package.json +126 -121
- package/python-sdk/fastapi_middleware.py +217 -0
package/dist/types/index.d.ts
CHANGED
|
@@ -15,4 +15,6 @@ export { fetchTracer, removeFetchTracer } from './integrations/fetch';
|
|
|
15
15
|
export { axiosTracer } from './integrations/axios';
|
|
16
16
|
export { flowDebugger } from './middleware/express';
|
|
17
17
|
export type { FlowDebuggerMiddleware } from './middleware/express';
|
|
18
|
+
export { DebuggerProvider, useDebugger, initializeReactNativeDebugger, getReactNativeDebugger, createFetchInterceptor, traceAsyncOperation, withDebugger } from './react_native';
|
|
19
|
+
export type { TraceStep as RNTraceStep, Trace as RNTrace, StepOptions as RNStepOptions, DebuggerContextType as RNDebuggerContextType } from './react_native';
|
|
18
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhE,YAAY,EACR,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,WAAW,EACX,KAAK,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhE,YAAY,EACR,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,UAAU,EACV,SAAS,EACT,WAAW,EACX,KAAK,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAGnE,OAAO,EACH,gBAAgB,EAChB,WAAW,EACX,6BAA6B,EAC7B,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,EACf,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACR,SAAS,IAAI,WAAW,EACxB,KAAK,IAAI,OAAO,EAChB,WAAW,IAAI,aAAa,EAC5B,mBAAmB,IAAI,qBAAqB,EAC/C,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export interface TraceStep {
|
|
2
|
+
name: string;
|
|
3
|
+
service: string;
|
|
4
|
+
status: 'success' | 'error' | 'timeout';
|
|
5
|
+
startTime: number;
|
|
6
|
+
endTime: number;
|
|
7
|
+
duration: number;
|
|
8
|
+
offset: number;
|
|
9
|
+
error?: string;
|
|
10
|
+
metadata?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface Trace {
|
|
13
|
+
traceId: string;
|
|
14
|
+
endpoint: string;
|
|
15
|
+
method: string;
|
|
16
|
+
steps: TraceStep[];
|
|
17
|
+
totalDuration: number;
|
|
18
|
+
timestamp: Date;
|
|
19
|
+
platform: 'react-native';
|
|
20
|
+
}
|
|
21
|
+
export interface StepOptions {
|
|
22
|
+
service?: string;
|
|
23
|
+
metadata?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
export interface DebuggerContextType {
|
|
26
|
+
startTrace: (endpoint: string, method?: string) => string;
|
|
27
|
+
step: <T>(traceId: string, name: string, fn: () => Promise<T>, options?: StepOptions) => Promise<T>;
|
|
28
|
+
addManualStep: (traceId: string, name: string, duration: number, options?: StepOptions) => void;
|
|
29
|
+
sendTrace: (traceId: string) => Promise<void>;
|
|
30
|
+
getTraces: () => Promise<Trace[]>;
|
|
31
|
+
}
|
|
32
|
+
declare class ReactNativeDebugger {
|
|
33
|
+
private traces;
|
|
34
|
+
private debuggerUrl;
|
|
35
|
+
private enabled;
|
|
36
|
+
constructor(debuggerUrl?: string, enabled?: boolean);
|
|
37
|
+
private loadTracesFromStorage;
|
|
38
|
+
private saveTracesToStorage;
|
|
39
|
+
startTrace(endpoint: string, method?: string): string;
|
|
40
|
+
step<T>(traceId: string, name: string, fn: () => Promise<T>, options?: StepOptions): Promise<T>;
|
|
41
|
+
addManualStep(traceId: string, name: string, duration: number, options?: StepOptions): void;
|
|
42
|
+
sendTrace(traceId: string): Promise<void>;
|
|
43
|
+
getTraces(): Promise<Trace[]>;
|
|
44
|
+
clearTraces(): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
export declare function initializeReactNativeDebugger(debuggerUrl?: string, enabled?: boolean): ReactNativeDebugger;
|
|
47
|
+
export declare function getReactNativeDebugger(): ReactNativeDebugger | null;
|
|
48
|
+
export declare const DebuggerProvider: any;
|
|
49
|
+
export declare const useDebugger: () => DebuggerContextType;
|
|
50
|
+
export declare function withDebugger<P extends object>(Component: any): any;
|
|
51
|
+
export declare function createFetchInterceptor(debuggerUrl?: string): (url: string | URL | Request, options?: RequestInit) => Promise<Response>;
|
|
52
|
+
export declare function traceAsyncOperation<T>(endpoint: string, operationName: string, operation: () => Promise<T>, service?: string): Promise<T>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=react_native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react_native.d.ts","sourceRoot":"","sources":["../../src/react_native.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,122 +1,127 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "flow-debugger",
|
|
3
|
-
"version": "1.9.
|
|
4
|
-
"description": "Production-safe flow-level debugging SDK. Traces requests, measures timing, classifies errors, detects root causes, and provides endpoint analytics with a live dashboard.",
|
|
5
|
-
"main": "dist/cjs/index.js",
|
|
6
|
-
"module": "dist/esm/index.js",
|
|
7
|
-
"types": "dist/types/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"require": "./dist/cjs/index.js",
|
|
11
|
-
"import": "./dist/esm/index.js",
|
|
12
|
-
"types": "./dist/types/index.d.ts"
|
|
13
|
-
},
|
|
14
|
-
"./express": {
|
|
15
|
-
"require": "./dist/cjs/middleware/express.js",
|
|
16
|
-
"import": "./dist/esm/middleware/express.js",
|
|
17
|
-
"types": "./dist/types/middleware/express.d.ts"
|
|
18
|
-
},
|
|
19
|
-
"./mongo": {
|
|
20
|
-
"require": "./dist/cjs/integrations/mongo.js",
|
|
21
|
-
"import": "./dist/esm/integrations/mongo.js",
|
|
22
|
-
"types": "./dist/types/integrations/mongo.d.ts"
|
|
23
|
-
},
|
|
24
|
-
"./mysql": {
|
|
25
|
-
"require": "./dist/cjs/integrations/mysql.js",
|
|
26
|
-
"import": "./dist/esm/integrations/mysql.js",
|
|
27
|
-
"types": "./dist/types/integrations/mysql.d.ts"
|
|
28
|
-
},
|
|
29
|
-
"./postgres": {
|
|
30
|
-
"require": "./dist/cjs/integrations/postgres.js",
|
|
31
|
-
"import": "./dist/esm/integrations/postgres.js",
|
|
32
|
-
"types": "./dist/types/integrations/postgres.d.ts"
|
|
33
|
-
},
|
|
34
|
-
"./redis": {
|
|
35
|
-
"require": "./dist/cjs/integrations/redis.js",
|
|
36
|
-
"import": "./dist/esm/integrations/redis.js",
|
|
37
|
-
"types": "./dist/types/integrations/redis.d.ts"
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
"
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"pg": "^8.
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "flow-debugger",
|
|
3
|
+
"version": "1.9.4",
|
|
4
|
+
"description": "Production-safe flow-level debugging SDK. Traces requests, measures timing, classifies errors, detects root causes, and provides endpoint analytics with a live dashboard.",
|
|
5
|
+
"main": "dist/cjs/index.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"require": "./dist/cjs/index.js",
|
|
11
|
+
"import": "./dist/esm/index.js",
|
|
12
|
+
"types": "./dist/types/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./express": {
|
|
15
|
+
"require": "./dist/cjs/middleware/express.js",
|
|
16
|
+
"import": "./dist/esm/middleware/express.js",
|
|
17
|
+
"types": "./dist/types/middleware/express.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./mongo": {
|
|
20
|
+
"require": "./dist/cjs/integrations/mongo.js",
|
|
21
|
+
"import": "./dist/esm/integrations/mongo.js",
|
|
22
|
+
"types": "./dist/types/integrations/mongo.d.ts"
|
|
23
|
+
},
|
|
24
|
+
"./mysql": {
|
|
25
|
+
"require": "./dist/cjs/integrations/mysql.js",
|
|
26
|
+
"import": "./dist/esm/integrations/mysql.js",
|
|
27
|
+
"types": "./dist/types/integrations/mysql.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./postgres": {
|
|
30
|
+
"require": "./dist/cjs/integrations/postgres.js",
|
|
31
|
+
"import": "./dist/esm/integrations/postgres.js",
|
|
32
|
+
"types": "./dist/types/integrations/postgres.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"./redis": {
|
|
35
|
+
"require": "./dist/cjs/integrations/redis.js",
|
|
36
|
+
"import": "./dist/esm/integrations/redis.js",
|
|
37
|
+
"types": "./dist/types/integrations/redis.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./react_native": {
|
|
40
|
+
"require": "./dist/cjs/react_native.js",
|
|
41
|
+
"import": "./dist/esm/react_native.js",
|
|
42
|
+
"types": "./dist/types/react_native.d.ts"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "npm run build:cjs && npm run build:esm && npm run build:types",
|
|
47
|
+
"build:cjs": "tsc --project tsconfig.cjs.json",
|
|
48
|
+
"build:esm": "tsc --project tsconfig.esm.json",
|
|
49
|
+
"build:types": "tsc --project tsconfig.types.json",
|
|
50
|
+
"dev": "ts-node example/server.ts",
|
|
51
|
+
"test": "jest --config jest.config.js",
|
|
52
|
+
"prepublishOnly": "npm run build"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"debugger",
|
|
56
|
+
"trace",
|
|
57
|
+
"flow",
|
|
58
|
+
"monitoring",
|
|
59
|
+
"performance",
|
|
60
|
+
"analytics",
|
|
61
|
+
"root-cause",
|
|
62
|
+
"express",
|
|
63
|
+
"mongodb",
|
|
64
|
+
"mysql",
|
|
65
|
+
"postgresql",
|
|
66
|
+
"redis",
|
|
67
|
+
"apm",
|
|
68
|
+
"observability",
|
|
69
|
+
"api-response-monitor"
|
|
70
|
+
],
|
|
71
|
+
"repository": {
|
|
72
|
+
"type": "git",
|
|
73
|
+
"url": "https://github.com/sannuk79/PROJECTS-AND-NPM-PACKAGES-"
|
|
74
|
+
},
|
|
75
|
+
"homepage": "https://github.com/sannuk79/PROJECTS-AND-NPM-PACKAGES-",
|
|
76
|
+
"bugs": {
|
|
77
|
+
"url": "https://github.com/sannuk79/debugerpackages/issues"
|
|
78
|
+
},
|
|
79
|
+
"bin": {
|
|
80
|
+
"flow-debugger": "bin/cli.js"
|
|
81
|
+
},
|
|
82
|
+
"author": "",
|
|
83
|
+
"license": "MIT",
|
|
84
|
+
"peerDependencies": {
|
|
85
|
+
"express": "^4.0.0 || ^5.0.0",
|
|
86
|
+
"mongoose": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
|
|
87
|
+
"mysql2": "^2.0.0 || ^3.0.0",
|
|
88
|
+
"pg": "^8.0.0",
|
|
89
|
+
"redis": "^4.0.0",
|
|
90
|
+
"axios": "^0.27.0 || ^1.0.0"
|
|
91
|
+
},
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"express": {
|
|
94
|
+
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"mongoose": {
|
|
97
|
+
"optional": true
|
|
98
|
+
},
|
|
99
|
+
"mysql2": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"pg": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"redis": {
|
|
106
|
+
"optional": true
|
|
107
|
+
},
|
|
108
|
+
"axios": {
|
|
109
|
+
"optional": true
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"devDependencies": {
|
|
113
|
+
"@types/express": "^4.17.21",
|
|
114
|
+
"@types/jest": "^29.5.12",
|
|
115
|
+
"@types/node": "^20.11.19",
|
|
116
|
+
"@types/pg": "^8.10.9",
|
|
117
|
+
"express": "^4.18.2",
|
|
118
|
+
"jest": "^29.7.0",
|
|
119
|
+
"mongoose": "^9.2.1",
|
|
120
|
+
"mysql2": "^3.7.0",
|
|
121
|
+
"pg": "^8.11.3",
|
|
122
|
+
"ts-jest": "^29.1.2",
|
|
123
|
+
"ts-node": "^10.9.2",
|
|
124
|
+
"typescript": "^5.3.3",
|
|
125
|
+
"autocannon": "^7.15.0"
|
|
126
|
+
}
|
|
122
127
|
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import uuid
|
|
3
|
+
from typing import Callable, Any
|
|
4
|
+
from contextlib import contextmanager
|
|
5
|
+
import asyncio
|
|
6
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
7
|
+
from starlette.requests import Request
|
|
8
|
+
from starlette.responses import Response
|
|
9
|
+
from starlette.background import BackgroundTask
|
|
10
|
+
import httpx
|
|
11
|
+
from .flow_debugger_core import RequestTracer
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FlowDebuggerFastAPI:
|
|
15
|
+
"""
|
|
16
|
+
FastAPI middleware for flow-debugger integration.
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
from flow_debugger.fastapi_middleware import FlowDebuggerFastAPI
|
|
20
|
+
|
|
21
|
+
app = FastAPI()
|
|
22
|
+
debugger = FlowDebuggerFastAPI(
|
|
23
|
+
app=app,
|
|
24
|
+
debugger_url="http://localhost:3500/__debugger"
|
|
25
|
+
)
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
app=None,
|
|
31
|
+
debugger_url: str = "http://localhost:3500/__debugger",
|
|
32
|
+
enabled: bool = True,
|
|
33
|
+
slow_threshold: int = 300,
|
|
34
|
+
capture_request_data: bool = False
|
|
35
|
+
):
|
|
36
|
+
self.debugger_url = debugger_url
|
|
37
|
+
self.enabled = enabled
|
|
38
|
+
self.slow_threshold = slow_threshold
|
|
39
|
+
self.capture_request_data = capture_request_data
|
|
40
|
+
self.app = app
|
|
41
|
+
|
|
42
|
+
if app is not None:
|
|
43
|
+
self.init_app(app)
|
|
44
|
+
|
|
45
|
+
def init_app(self, app):
|
|
46
|
+
"""Initialize the middleware with a FastAPI app."""
|
|
47
|
+
app.add_middleware(
|
|
48
|
+
FlowDebuggerMiddleware,
|
|
49
|
+
debugger=self
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class FlowDebuggerMiddleware(BaseHTTPMiddleware):
|
|
54
|
+
"""Internal middleware class that handles the actual request processing."""
|
|
55
|
+
|
|
56
|
+
def __init__(self, app, debugger: FlowDebuggerFastAPI):
|
|
57
|
+
super().__init__(app)
|
|
58
|
+
self.debugger = debugger
|
|
59
|
+
|
|
60
|
+
async def dispatch(self, request: Request, call_next) -> Response:
|
|
61
|
+
if not self.debugger.enabled:
|
|
62
|
+
return await call_next(request)
|
|
63
|
+
|
|
64
|
+
# Skip debugger endpoints to prevent recursion
|
|
65
|
+
if request.url.path.startswith('/__debugger'):
|
|
66
|
+
return await call_next(request)
|
|
67
|
+
|
|
68
|
+
# Create tracer for this request
|
|
69
|
+
tracer = RequestTracer(
|
|
70
|
+
endpoint=request.url.path,
|
|
71
|
+
method=request.method,
|
|
72
|
+
trace_id=f"fastapi_{uuid.uuid4().hex[:12]}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Store tracer in request state
|
|
76
|
+
request.state.tracer = tracer
|
|
77
|
+
|
|
78
|
+
start_time = time.time()
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
# Process the request
|
|
82
|
+
response = await call_next(request)
|
|
83
|
+
finally:
|
|
84
|
+
# Calculate duration
|
|
85
|
+
duration = (time.time() - start_time) * 1000 # Convert to milliseconds
|
|
86
|
+
|
|
87
|
+
# End the trace
|
|
88
|
+
trace_data = tracer.end(status_code=response.status_code)
|
|
89
|
+
trace_data['totalDuration'] = duration
|
|
90
|
+
trace_data['timestamp'] = tracer.timestamp.isoformat()
|
|
91
|
+
|
|
92
|
+
# Add request/response info
|
|
93
|
+
trace_data['endpoint'] = request.url.path
|
|
94
|
+
trace_data['method'] = request.method
|
|
95
|
+
|
|
96
|
+
# Send trace data to the main debugger service
|
|
97
|
+
if self.debugger.debugger_url:
|
|
98
|
+
# Create a background task to send trace data asynchronously
|
|
99
|
+
# This prevents slowing down the main request
|
|
100
|
+
async def send_trace():
|
|
101
|
+
try:
|
|
102
|
+
async with httpx.AsyncClient(timeout=5.0) as client:
|
|
103
|
+
await client.post(
|
|
104
|
+
self.debugger.debugger_url,
|
|
105
|
+
json=trace_data,
|
|
106
|
+
headers={'Content-Type': 'application/json'}
|
|
107
|
+
)
|
|
108
|
+
except Exception:
|
|
109
|
+
# Silently fail to avoid affecting the main request
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
# Add background task to response if possible
|
|
113
|
+
if hasattr(response, 'background') and response.background:
|
|
114
|
+
# Chain with existing background tasks
|
|
115
|
+
existing_task = response.background
|
|
116
|
+
response.background = BackgroundTask(
|
|
117
|
+
lambda: asyncio.gather(
|
|
118
|
+
send_trace(),
|
|
119
|
+
existing_task()
|
|
120
|
+
) if callable(existing_task) else send_trace()
|
|
121
|
+
)
|
|
122
|
+
else:
|
|
123
|
+
response.background = BackgroundTask(send_trace)
|
|
124
|
+
|
|
125
|
+
# Add trace ID to response headers
|
|
126
|
+
response.headers['X-Trace-ID'] = tracer.trace_id
|
|
127
|
+
|
|
128
|
+
return response
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Context manager and decorator utilities for manual tracing
|
|
132
|
+
@contextmanager
|
|
133
|
+
def traced_step(tracer: RequestTracer, name: str, service: str = 'internal'):
|
|
134
|
+
"""
|
|
135
|
+
Context manager for tracing code blocks manually.
|
|
136
|
+
|
|
137
|
+
Usage:
|
|
138
|
+
with traced_step(request.state.tracer, "Database query", "postgres"):
|
|
139
|
+
result = await database.fetch_all(query)
|
|
140
|
+
"""
|
|
141
|
+
if not tracer:
|
|
142
|
+
yield
|
|
143
|
+
return
|
|
144
|
+
|
|
145
|
+
step = tracer.step(name, service)
|
|
146
|
+
try:
|
|
147
|
+
yield step
|
|
148
|
+
except Exception as e:
|
|
149
|
+
step.status = 'error'
|
|
150
|
+
step.error = str(e)
|
|
151
|
+
raise
|
|
152
|
+
finally:
|
|
153
|
+
step.end()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def trace_step_async(name: str, service: str = 'internal'):
|
|
157
|
+
"""
|
|
158
|
+
Decorator for tracing async functions.
|
|
159
|
+
|
|
160
|
+
Usage:
|
|
161
|
+
@trace_step_async("User validation", "auth")
|
|
162
|
+
async def validate_user(user_id):
|
|
163
|
+
# function implementation
|
|
164
|
+
"""
|
|
165
|
+
def decorator(func):
|
|
166
|
+
async def wrapper(*args, **kwargs):
|
|
167
|
+
# Try to get tracer from request context (requires FastAPI dependency injection)
|
|
168
|
+
tracer = getattr(args[0].request.state, 'tracer', None) if hasattr(args[0], 'request') else None
|
|
169
|
+
|
|
170
|
+
if tracer:
|
|
171
|
+
with traced_step(tracer, name, service):
|
|
172
|
+
return await func(*args, **kwargs)
|
|
173
|
+
else:
|
|
174
|
+
return await func(*args, **kwargs)
|
|
175
|
+
return wrapper
|
|
176
|
+
return decorator
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# Utility function to get tracer from request
|
|
180
|
+
def get_tracer(request: Request) -> RequestTracer:
|
|
181
|
+
"""Get the current request tracer from the request state."""
|
|
182
|
+
return getattr(request.state, 'tracer', None)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
# Manual tracing function for custom steps
|
|
186
|
+
async def trace_async_step(
|
|
187
|
+
request: Request,
|
|
188
|
+
name: str,
|
|
189
|
+
func: Callable,
|
|
190
|
+
service: str = 'internal',
|
|
191
|
+
timeout: float = 30.0
|
|
192
|
+
):
|
|
193
|
+
"""
|
|
194
|
+
Manually trace an async function call.
|
|
195
|
+
|
|
196
|
+
Usage:
|
|
197
|
+
result = await trace_async_step(
|
|
198
|
+
request,
|
|
199
|
+
"External API call",
|
|
200
|
+
lambda: external_api.call(),
|
|
201
|
+
service="external"
|
|
202
|
+
)
|
|
203
|
+
"""
|
|
204
|
+
tracer = get_tracer(request)
|
|
205
|
+
if not tracer:
|
|
206
|
+
return await func()
|
|
207
|
+
|
|
208
|
+
step = tracer.step(name, service)
|
|
209
|
+
try:
|
|
210
|
+
result = await func()
|
|
211
|
+
return result
|
|
212
|
+
except Exception as e:
|
|
213
|
+
step.status = 'error'
|
|
214
|
+
step.error = str(e)
|
|
215
|
+
raise
|
|
216
|
+
finally:
|
|
217
|
+
step.end()
|