usetraceforge 1.0.0__tar.gz

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.
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: usetraceforge
3
+ Version: 1.0.0
4
+ Summary: TraceForge Python SDK for unhandled panic logging
5
+ Home-page: https://github.com/khushalp2004/TraceForge
6
+ Author: Khushal Patil
7
+ Requires-Dist: requests>=2.31.0
8
+ Dynamic: author
9
+ Dynamic: home-page
10
+ Dynamic: requires-dist
11
+ Dynamic: summary
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,13 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="usetraceforge",
5
+ version="1.0.0",
6
+ packages=find_packages(),
7
+ install_requires=[
8
+ "requests>=2.31.0"
9
+ ],
10
+ author="Khushal Patil",
11
+ description="TraceForge Python SDK for unhandled panic logging",
12
+ url="https://github.com/khushalp2004/TraceForge"
13
+ )
@@ -0,0 +1,3 @@
1
+ from .client import init, capture_exception, capture_message
2
+
3
+ __all__ = ["init", "capture_exception", "capture_message"]
@@ -0,0 +1,101 @@
1
+ import os
2
+ import traceback
3
+ import requests
4
+ import threading
5
+ import sys
6
+
7
+ _config = {}
8
+ _setup_handshake_sent = False
9
+
10
+ def init(api_key: str, endpoint: str = "http://localhost:3001/ingest", auto_capture: bool = True):
11
+ if not api_key:
12
+ raise ValueError("TraceForge.init() failed: Missing API Key.")
13
+
14
+ _config["api_key"] = api_key
15
+ _config["endpoint"] = endpoint
16
+
17
+ # Send setup handshake
18
+ threading.Thread(target=_send_setup_handshake, daemon=True).start()
19
+
20
+ if auto_capture:
21
+ _setup_auto_capture()
22
+
23
+ def _get_setup_endpoint() -> str:
24
+ base = _config.get("endpoint", "").rstrip("/")
25
+ if base.endswith("/setup"):
26
+ return base
27
+ return f"{base}/setup"
28
+
29
+ def _send_setup_handshake():
30
+ global _setup_handshake_sent
31
+ if _setup_handshake_sent or not _config.get("api_key"):
32
+ return
33
+
34
+ try:
35
+ res = requests.post(
36
+ _get_setup_endpoint(),
37
+ json={"environment": "python"},
38
+ headers={
39
+ "Content-Type": "application/json",
40
+ "X-Traceforge-Key": _config["api_key"]
41
+ },
42
+ timeout=5
43
+ )
44
+ if res.status_code < 400:
45
+ _setup_handshake_sent = True
46
+ except Exception:
47
+ pass
48
+
49
+ def _send_payload(payload):
50
+ api_key = _config.get("api_key")
51
+ endpoint = _config.get("endpoint")
52
+ if not api_key or not endpoint:
53
+ return
54
+
55
+ headers = {
56
+ "X-Traceforge-Key": api_key,
57
+ "Content-Type": "application/json"
58
+ }
59
+
60
+ try:
61
+ requests.post(endpoint, json=payload, headers=headers, timeout=5)
62
+ except Exception as e:
63
+ pass
64
+
65
+ def capture_exception(exc: Exception, tags: dict = None, payload: dict = None):
66
+ if not _config.get("api_key"):
67
+ return
68
+
69
+ message = str(exc) or exc.__class__.__name__
70
+
71
+ try:
72
+ stack_trace = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
73
+ except Exception:
74
+ stack_trace = traceback.format_exc()
75
+
76
+ event = {
77
+ "message": message,
78
+ "stackTrace": stack_trace,
79
+ "environment": "python",
80
+ "tags": tags or {},
81
+ "payload": payload or {}
82
+ }
83
+
84
+ # We use threading to send this synchronously in the background
85
+ threading.Thread(target=_send_payload, args=(event,), daemon=True).start()
86
+
87
+ def capture_message(message: str, level: str = "info", context: dict = None):
88
+ # Backward compatibility
89
+ pass
90
+
91
+ def _setup_auto_capture():
92
+ # Hook into sys.excepthook to catch all unhandled exceptions
93
+ original_excepthook = sys.excepthook
94
+
95
+ def traceforge_excepthook(exc_type, exc_value, exc_traceback):
96
+ if exc_value:
97
+ capture_exception(exc_value, tags={"uncaught": "true"})
98
+ # Call the original excepthook to not break default behavior
99
+ original_excepthook(exc_type, exc_value, exc_traceback)
100
+
101
+ sys.excepthook = traceforge_excepthook
@@ -0,0 +1 @@
1
+ # Integrations for TraceForge
@@ -0,0 +1,21 @@
1
+ from traceforge.client import capture_exception
2
+
3
+ class TraceForgeMiddleware:
4
+ def __init__(self, get_response):
5
+ self.get_response = get_response
6
+
7
+ def __call__(self, request):
8
+ return self.get_response(request)
9
+
10
+ def process_exception(self, request, exception):
11
+ # Capture the exception asynchronously
12
+ payload = {
13
+ "url": request.build_absolute_uri(),
14
+ "method": request.method,
15
+ }
16
+
17
+ # We don't want to block the Django response
18
+ capture_exception(exception, tags={"framework": "django"}, payload=payload)
19
+
20
+ # Return None to let Django's default exception handling continue
21
+ return None
@@ -0,0 +1,32 @@
1
+ from traceforge.client import capture_exception
2
+
3
+ def init(app):
4
+ """
5
+ Registers a global exception handler for FastAPI/Starlette applications.
6
+ """
7
+ try:
8
+ from fastapi import Request
9
+ from starlette.responses import JSONResponse
10
+ from starlette.exceptions import HTTPException
11
+ except ImportError:
12
+ return
13
+
14
+ @app.exception_handler(Exception)
15
+ async def traceforge_exception_handler(request: Request, exc: Exception):
16
+ # Don't capture standard HTTPExceptions (like 404s) as crashes
17
+ if isinstance(exc, HTTPException) and exc.status_code < 500:
18
+ raise exc
19
+
20
+ payload = {
21
+ "url": str(request.url),
22
+ "method": request.method,
23
+ }
24
+
25
+ capture_exception(exc, tags={"framework": "fastapi"}, payload=payload)
26
+
27
+ # Re-raise the exception to let FastAPI handle it natively
28
+ # Or return a 500 JSON response if we prefer to mask it
29
+ return JSONResponse(
30
+ status_code=500,
31
+ content={"detail": "Internal Server Error"}
32
+ )
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: usetraceforge
3
+ Version: 1.0.0
4
+ Summary: TraceForge Python SDK for unhandled panic logging
5
+ Home-page: https://github.com/khushalp2004/TraceForge
6
+ Author: Khushal Patil
7
+ Requires-Dist: requests>=2.31.0
8
+ Dynamic: author
9
+ Dynamic: home-page
10
+ Dynamic: requires-dist
11
+ Dynamic: summary
@@ -0,0 +1,11 @@
1
+ setup.py
2
+ traceforge/__init__.py
3
+ traceforge/client.py
4
+ traceforge/integrations/__init__.py
5
+ traceforge/integrations/django.py
6
+ traceforge/integrations/fastapi.py
7
+ usetraceforge.egg-info/PKG-INFO
8
+ usetraceforge.egg-info/SOURCES.txt
9
+ usetraceforge.egg-info/dependency_links.txt
10
+ usetraceforge.egg-info/requires.txt
11
+ usetraceforge.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2.31.0
@@ -0,0 +1 @@
1
+ traceforge