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.
@@ -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.3",
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
- "scripts": {
41
- "build": "npm run build:cjs && npm run build:esm && npm run build:types",
42
- "build:cjs": "tsc --project tsconfig.cjs.json",
43
- "build:esm": "tsc --project tsconfig.esm.json",
44
- "build:types": "tsc --project tsconfig.types.json",
45
- "dev": "ts-node example/server.ts",
46
- "test": "jest --config jest.config.js",
47
- "prepublishOnly": "npm run build"
48
- },
49
- "keywords": [
50
- "debugger",
51
- "trace",
52
- "flow",
53
- "monitoring",
54
- "performance",
55
- "analytics",
56
- "root-cause",
57
- "express",
58
- "mongodb",
59
- "mysql",
60
- "postgresql",
61
- "redis",
62
- "apm",
63
- "observability",
64
- "api-response-monitor"
65
- ],
66
- "repository": {
67
- "type": "git",
68
- "url": "https://github.com/sannuk79/PROJECTS-AND-NPM-PACKAGES-"
69
- },
70
- "homepage": "https://github.com/sannuk79/PROJECTS-AND-NPM-PACKAGES-",
71
- "bugs": {
72
- "url": "https://github.com/sannuk79/debugerpackages/issues"
73
- },
74
- "bin": {
75
- "flow-debugger": "bin/cli.js"
76
- },
77
- "author": "",
78
- "license": "MIT",
79
- "peerDependencies": {
80
- "express": "^4.0.0 || ^5.0.0",
81
- "mongoose": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
82
- "mysql2": "^2.0.0 || ^3.0.0",
83
- "pg": "^8.0.0",
84
- "redis": "^4.0.0",
85
- "axios": "^0.27.0 || ^1.0.0"
86
- },
87
- "peerDependenciesMeta": {
88
- "express": {
89
- "optional": true
90
- },
91
- "mongoose": {
92
- "optional": true
93
- },
94
- "mysql2": {
95
- "optional": true
96
- },
97
- "pg": {
98
- "optional": true
99
- },
100
- "redis": {
101
- "optional": true
102
- },
103
- "axios": {
104
- "optional": true
105
- }
106
- },
107
- "devDependencies": {
108
- "@types/express": "^4.17.21",
109
- "@types/jest": "^29.5.12",
110
- "@types/node": "^20.11.19",
111
- "@types/pg": "^8.10.9",
112
- "express": "^4.18.2",
113
- "jest": "^29.7.0",
114
- "mongoose": "^9.2.1",
115
- "mysql2": "^3.7.0",
116
- "pg": "^8.11.3",
117
- "ts-jest": "^29.1.2",
118
- "ts-node": "^10.9.2",
119
- "typescript": "^5.3.3",
120
- "autocannon": "^7.15.0"
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()