flow-debugger 1.0.2 → 1.2.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.
Files changed (51) hide show
  1. package/README.md +14 -2
  2. package/assets/DASHBOARD.png +1 -0
  3. package/dashboard/app.js +12 -0
  4. package/dashboard/style.css +46 -0
  5. package/dist/cjs/core/TraceEngine.js +5 -0
  6. package/dist/cjs/core/TraceEngine.js.map +1 -1
  7. package/dist/cjs/core/types.js.map +1 -1
  8. package/dist/cjs/integrations/axios.js +6 -4
  9. package/dist/cjs/integrations/axios.js.map +1 -1
  10. package/dist/cjs/integrations/fetch.js +6 -4
  11. package/dist/cjs/integrations/fetch.js.map +1 -1
  12. package/dist/cjs/integrations/mongo.js +6 -4
  13. package/dist/cjs/integrations/mongo.js.map +1 -1
  14. package/dist/cjs/integrations/mysql.js +18 -12
  15. package/dist/cjs/integrations/mysql.js.map +1 -1
  16. package/dist/cjs/integrations/postgres.js +3 -2
  17. package/dist/cjs/integrations/postgres.js.map +1 -1
  18. package/dist/cjs/integrations/redis.js +6 -4
  19. package/dist/cjs/integrations/redis.js.map +1 -1
  20. package/dist/cjs/middleware/express.js +15 -2
  21. package/dist/cjs/middleware/express.js.map +1 -1
  22. package/dist/esm/core/TraceEngine.js +5 -0
  23. package/dist/esm/core/TraceEngine.js.map +1 -1
  24. package/dist/esm/core/types.js.map +1 -1
  25. package/dist/esm/integrations/axios.js +6 -4
  26. package/dist/esm/integrations/axios.js.map +1 -1
  27. package/dist/esm/integrations/fetch.js +6 -4
  28. package/dist/esm/integrations/fetch.js.map +1 -1
  29. package/dist/esm/integrations/mongo.js +6 -4
  30. package/dist/esm/integrations/mongo.js.map +1 -1
  31. package/dist/esm/integrations/mysql.js +18 -12
  32. package/dist/esm/integrations/mysql.js.map +1 -1
  33. package/dist/esm/integrations/postgres.js +3 -2
  34. package/dist/esm/integrations/postgres.js.map +1 -1
  35. package/dist/esm/integrations/redis.js +6 -4
  36. package/dist/esm/integrations/redis.js.map +1 -1
  37. package/dist/esm/middleware/express.js +15 -2
  38. package/dist/esm/middleware/express.js.map +1 -1
  39. package/dist/types/core/TraceEngine.d.ts +1 -0
  40. package/dist/types/core/TraceEngine.d.ts.map +1 -1
  41. package/dist/types/core/types.d.ts +1 -0
  42. package/dist/types/core/types.d.ts.map +1 -1
  43. package/dist/types/integrations/axios.d.ts.map +1 -1
  44. package/dist/types/integrations/fetch.d.ts.map +1 -1
  45. package/dist/types/integrations/mongo.d.ts.map +1 -1
  46. package/dist/types/integrations/mysql.d.ts.map +1 -1
  47. package/dist/types/integrations/redis.d.ts.map +1 -1
  48. package/flowdebuger.png +0 -0
  49. package/package.json +5 -5
  50. package/python-sdk/flow_debugger_core.py +83 -0
  51. package/python-sdk/middleware.py +32 -0
@@ -0,0 +1,83 @@
1
+ import time
2
+ import uuid
3
+ from typing import List, Dict, Any, Optional, Union
4
+ from datetime import datetime
5
+
6
+ class TraceStep:
7
+ def __init__(self, name: str, service: str = 'internal', status: str = 'success'):
8
+ self.name = name
9
+ self.service = service
10
+ self.status = status
11
+ self.classification = 'INFO'
12
+ self.start_time = time.time() * 1000 # ms
13
+ self.end_time = 0
14
+ self.duration = 0
15
+ self.offset = 0
16
+ self.error = None
17
+ self.metadata = {}
18
+
19
+ def end(self):
20
+ self.end_time = time.time() * 1000
21
+ self.duration = self.end_time - self.start_time
22
+
23
+ def to_dict(self) -> Dict[str, Any]:
24
+ return {
25
+ 'name': self.name,
26
+ 'service': self.service,
27
+ 'status': self.status,
28
+ 'classification': self.classification,
29
+ 'startTime': self.start_time,
30
+ 'endTime': self.end_time,
31
+ 'duration': self.duration,
32
+ 'offset': self.offset,
33
+ 'error': self.error,
34
+ 'metadata': self.metadata
35
+ }
36
+
37
+ class RequestTracer:
38
+ def __init__(self, endpoint: str, method: str, trace_id: str = None):
39
+ self.trace_id = trace_id or f"py_{uuid.uuid4().hex[:12]}"
40
+ self.endpoint = endpoint
41
+ self.method = method
42
+ self.start_time = time.time() * 1000
43
+ self.steps: List[TraceStep] = []
44
+ self.ended = False
45
+ self.total_duration = 0
46
+ self.status_code = None
47
+
48
+ def step(self, name: str, service: str = 'internal'):
49
+ new_step = TraceStep(name, service)
50
+ new_step.offset = new_step.start_time - self.start_time
51
+ self.steps.append(new_step)
52
+ return new_step
53
+
54
+ def end(self, status_code: int = 200):
55
+ if self.ended:
56
+ return
57
+ self.ended = True
58
+ self.status_code = status_code
59
+ end_time = time.time() * 1000
60
+ self.total_duration = end_time - self.start_time
61
+
62
+ # Build final trace object
63
+ return self.to_dict()
64
+
65
+ def to_dict(self) -> Dict[str, Any]:
66
+ return {
67
+ 'traceId': self.trace_id,
68
+ 'endpoint': self.endpoint,
69
+ 'method': self.method,
70
+ 'statusCode': self.status_code,
71
+ 'steps': [s.to_dict() for s in self.steps],
72
+ 'totalDuration': self.total_duration,
73
+ 'classification': self._classify_trace(),
74
+ 'timestamp': datetime.now().isoformat(),
75
+ 'language': 'python'
76
+ }
77
+
78
+ def _classify_trace(self) -> str:
79
+ if any(s.status != 'success' for s in self.steps):
80
+ return 'ERROR'
81
+ if self.total_duration > 500:
82
+ return 'WARN'
83
+ return 'INFO'
@@ -0,0 +1,32 @@
1
+ import requests
2
+ import time
3
+ from .flow_debugger_core import RequestTracer
4
+
5
+ class FlowDebuggerFlask:
6
+ def __init__(self, app=None, debugger_url="http://localhost:3500/__debugger"):
7
+ self.debugger_url = debugger_url
8
+ if app is not None:
9
+ self.init_app(app)
10
+
11
+ def init_app(self, app):
12
+ @app.before_request
13
+ def before_request():
14
+ import flask
15
+ # Start trace
16
+ tracer = RequestTracer(endpoint=flask.request.path, method=flask.request.method)
17
+ flask.g.tracer = tracer
18
+
19
+ @app.after_request
20
+ def after_request(response):
21
+ import flask
22
+ tracer = getattr(flask.g, 'tracer', None)
23
+ if tracer:
24
+ trace_data = tracer.end(status_code=response.status_code)
25
+ # Send to Node.js dashboard API in background (sync for simple version)
26
+ try:
27
+ # In a real version, this would be buffered or async
28
+ # For this demo/SDK, we send it directly to the local debugger
29
+ requests.post(self.debugger_url, json=trace_data, timeout=0.1)
30
+ except:
31
+ pass
32
+ return response