ghosttrap-sdk 0.4.2__tar.gz → 0.4.4__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,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: ghosttrap-sdk
3
+ Version: 0.4.4
4
+ Summary: Drop-in error reporter for ghosttrap.io
5
+ Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-sdk
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+
9
+ # ghosttrap-sdk
10
+
11
+ Error reporting for Python apps, built for AI agents. Part of [ghosttrap](https://github.com/alex-rowley/ghosttrap-cli).
12
+
13
+ ## Install
14
+
15
+ ```
16
+ pip install ghosttrap-sdk
17
+ ```
18
+
19
+ ## Use
20
+
21
+ ```python
22
+ import ghosttrap
23
+ ghosttrap.init("t_your_token_here")
24
+ ```
25
+
26
+ Get your token by running `ghosttrap setup` from [ghosttrap-cli](https://github.com/alex-rowley/ghosttrap-cli).
27
+
28
+ ### Optional kwargs
29
+
30
+ ```python
31
+ ghosttrap.init(
32
+ "t_your_token_here",
33
+ server="https://ghosttrap.io", # override only if self-hosting
34
+ send_user=False, # see "User context" below
35
+ )
36
+ ```
37
+
38
+ ## What it hooks into
39
+
40
+ - **`sys.excepthook`** — unhandled exceptions
41
+ - **Python logging** — `logger.exception()` and `logger.error(..., exc_info=True)`
42
+ - **Celery** — task failures via `celery.signals.task_failure` (auto-detected)
43
+
44
+ ## What it sends
45
+
46
+ Every report includes the exception type, message, traceback, frames (file/line/function/code), and the server's hostname (`socket.gethostname()`).
47
+
48
+ ## Django
49
+
50
+ ```python
51
+ INSTALLED_APPS = [
52
+ ...
53
+ "ghosttrap.django.GhostTrapApp",
54
+ ]
55
+
56
+ MIDDLEWARE = [
57
+ "ghosttrap.django.GhostTrapMiddleware",
58
+ ...
59
+ ]
60
+ ```
61
+
62
+ ## Manually trap an event
63
+
64
+ For errors you catch and handle but still want logged, or for non-exception conditions worth flagging:
65
+
66
+ ```python
67
+ import ghosttrap
68
+
69
+ try:
70
+ do_thing()
71
+ except ValueError as e:
72
+ ghosttrap.trap(e) # caught exception — sent with type, message, traceback
73
+ fallback()
74
+
75
+ ghosttrap.trap("payment gateway returned 503") # synthetic event labelled "TrappedEvent"
76
+ ```
77
+
78
+ `trap()` accepts an exception instance or a string. Strings get the caller's stack attached and a `TrappedEvent` type so they're distinct from real exceptions in the CLI. Both go through the same 5-minute dedup window as the auto-hook.
79
+
80
+ ## User context
81
+
82
+ Off by default. Pass `send_user=True` to `init()` and the Django middleware will attach the authenticated user's `id` and `username` to each report. Has no effect outside Django.
83
+
84
+ ```python
85
+ ghosttrap.init("t_your_token_here", send_user=True)
86
+ ```
87
+
88
+ ## Zero dependencies
89
+
90
+ Pure Python stdlib. No transitive dependencies in your production image.
@@ -0,0 +1,82 @@
1
+ # ghosttrap-sdk
2
+
3
+ Error reporting for Python apps, built for AI agents. Part of [ghosttrap](https://github.com/alex-rowley/ghosttrap-cli).
4
+
5
+ ## Install
6
+
7
+ ```
8
+ pip install ghosttrap-sdk
9
+ ```
10
+
11
+ ## Use
12
+
13
+ ```python
14
+ import ghosttrap
15
+ ghosttrap.init("t_your_token_here")
16
+ ```
17
+
18
+ Get your token by running `ghosttrap setup` from [ghosttrap-cli](https://github.com/alex-rowley/ghosttrap-cli).
19
+
20
+ ### Optional kwargs
21
+
22
+ ```python
23
+ ghosttrap.init(
24
+ "t_your_token_here",
25
+ server="https://ghosttrap.io", # override only if self-hosting
26
+ send_user=False, # see "User context" below
27
+ )
28
+ ```
29
+
30
+ ## What it hooks into
31
+
32
+ - **`sys.excepthook`** — unhandled exceptions
33
+ - **Python logging** — `logger.exception()` and `logger.error(..., exc_info=True)`
34
+ - **Celery** — task failures via `celery.signals.task_failure` (auto-detected)
35
+
36
+ ## What it sends
37
+
38
+ Every report includes the exception type, message, traceback, frames (file/line/function/code), and the server's hostname (`socket.gethostname()`).
39
+
40
+ ## Django
41
+
42
+ ```python
43
+ INSTALLED_APPS = [
44
+ ...
45
+ "ghosttrap.django.GhostTrapApp",
46
+ ]
47
+
48
+ MIDDLEWARE = [
49
+ "ghosttrap.django.GhostTrapMiddleware",
50
+ ...
51
+ ]
52
+ ```
53
+
54
+ ## Manually trap an event
55
+
56
+ For errors you catch and handle but still want logged, or for non-exception conditions worth flagging:
57
+
58
+ ```python
59
+ import ghosttrap
60
+
61
+ try:
62
+ do_thing()
63
+ except ValueError as e:
64
+ ghosttrap.trap(e) # caught exception — sent with type, message, traceback
65
+ fallback()
66
+
67
+ ghosttrap.trap("payment gateway returned 503") # synthetic event labelled "TrappedEvent"
68
+ ```
69
+
70
+ `trap()` accepts an exception instance or a string. Strings get the caller's stack attached and a `TrappedEvent` type so they're distinct from real exceptions in the CLI. Both go through the same 5-minute dedup window as the auto-hook.
71
+
72
+ ## User context
73
+
74
+ Off by default. Pass `send_user=True` to `init()` and the Django middleware will attach the authenticated user's `id` and `username` to each report. Has no effect outside Django.
75
+
76
+ ```python
77
+ ghosttrap.init("t_your_token_here", send_user=True)
78
+ ```
79
+
80
+ ## Zero dependencies
81
+
82
+ Pure Python stdlib. No transitive dependencies in your production image.
@@ -0,0 +1,3 @@
1
+ from ghosttrap.client import init, report, trap
2
+
3
+ __all__ = ["init", "report", "trap"]
@@ -61,16 +61,30 @@ def init(dsn, server=None, send_user=False):
61
61
 
62
62
 
63
63
  def report(exc, user=None):
64
- """Report a caught exception to the ghosttrap server.
64
+ """Report a caught exception. Kept for backward compatibility; prefer `trap`."""
65
+ trap(exc, user=user)
66
+
67
+
68
+ def trap(exc_or_message, user=None):
69
+ """Manually trap an event.
70
+
71
+ Pass an exception instance to report a caught error (its type, message,
72
+ and traceback are sent). Pass a string to report a synthetic event with
73
+ the caller's current stack — labelled `TrappedEvent` so it's distinct
74
+ from real exceptions.
65
75
 
66
76
  Args:
67
- exc: the exception instance from an `except Exception as exc` block
77
+ exc_or_message: exception instance or string
68
78
  user: optional dict with user context (id, username). Only sent
69
79
  if init() was called with send_user=True.
70
80
  """
71
81
  if _endpoint is None:
72
82
  return
73
- _post(_build_payload(type(exc), exc, exc.__traceback__, user=user))
83
+ if isinstance(exc_or_message, BaseException):
84
+ exc = exc_or_message
85
+ _post(_build_payload(type(exc), exc, exc.__traceback__, user=user))
86
+ else:
87
+ _post(_build_synthetic_payload(str(exc_or_message), user=user))
74
88
 
75
89
 
76
90
  def _error_hook(exc_type, exc_value, exc_tb):
@@ -102,6 +116,27 @@ class _GhostTrapLogHandler(logging.Handler):
102
116
  report(record.exc_info[1])
103
117
 
104
118
 
119
+ def _build_synthetic_payload(message, user=None):
120
+ frames_obj = traceback.extract_stack()[:-2] # drop trap() and this builder
121
+ formatted = ["Traceback (most recent call last):\n"]
122
+ formatted += traceback.format_list(frames_obj)
123
+ formatted.append(f"TrappedEvent: {message}\n")
124
+ payload = {
125
+ "type": "TrappedEvent",
126
+ "message": message,
127
+ "traceback": formatted,
128
+ "frames": [
129
+ {"file": f.filename, "line": f.lineno, "function": f.name, "code": f.line}
130
+ for f in frames_obj
131
+ ],
132
+ }
133
+ if _server_name:
134
+ payload["server_name"] = _server_name
135
+ if user and _send_user:
136
+ payload["user"] = user
137
+ return payload
138
+
139
+
105
140
  def _build_payload(exc_type, exc_value, exc_tb, user=None):
106
141
  frames = traceback.extract_tb(exc_tb) if exc_tb else []
107
142
  payload = {
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: ghosttrap-sdk
3
+ Version: 0.4.4
4
+ Summary: Drop-in error reporter for ghosttrap.io
5
+ Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-sdk
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+
9
+ # ghosttrap-sdk
10
+
11
+ Error reporting for Python apps, built for AI agents. Part of [ghosttrap](https://github.com/alex-rowley/ghosttrap-cli).
12
+
13
+ ## Install
14
+
15
+ ```
16
+ pip install ghosttrap-sdk
17
+ ```
18
+
19
+ ## Use
20
+
21
+ ```python
22
+ import ghosttrap
23
+ ghosttrap.init("t_your_token_here")
24
+ ```
25
+
26
+ Get your token by running `ghosttrap setup` from [ghosttrap-cli](https://github.com/alex-rowley/ghosttrap-cli).
27
+
28
+ ### Optional kwargs
29
+
30
+ ```python
31
+ ghosttrap.init(
32
+ "t_your_token_here",
33
+ server="https://ghosttrap.io", # override only if self-hosting
34
+ send_user=False, # see "User context" below
35
+ )
36
+ ```
37
+
38
+ ## What it hooks into
39
+
40
+ - **`sys.excepthook`** — unhandled exceptions
41
+ - **Python logging** — `logger.exception()` and `logger.error(..., exc_info=True)`
42
+ - **Celery** — task failures via `celery.signals.task_failure` (auto-detected)
43
+
44
+ ## What it sends
45
+
46
+ Every report includes the exception type, message, traceback, frames (file/line/function/code), and the server's hostname (`socket.gethostname()`).
47
+
48
+ ## Django
49
+
50
+ ```python
51
+ INSTALLED_APPS = [
52
+ ...
53
+ "ghosttrap.django.GhostTrapApp",
54
+ ]
55
+
56
+ MIDDLEWARE = [
57
+ "ghosttrap.django.GhostTrapMiddleware",
58
+ ...
59
+ ]
60
+ ```
61
+
62
+ ## Manually trap an event
63
+
64
+ For errors you catch and handle but still want logged, or for non-exception conditions worth flagging:
65
+
66
+ ```python
67
+ import ghosttrap
68
+
69
+ try:
70
+ do_thing()
71
+ except ValueError as e:
72
+ ghosttrap.trap(e) # caught exception — sent with type, message, traceback
73
+ fallback()
74
+
75
+ ghosttrap.trap("payment gateway returned 503") # synthetic event labelled "TrappedEvent"
76
+ ```
77
+
78
+ `trap()` accepts an exception instance or a string. Strings get the caller's stack attached and a `TrappedEvent` type so they're distinct from real exceptions in the CLI. Both go through the same 5-minute dedup window as the auto-hook.
79
+
80
+ ## User context
81
+
82
+ Off by default. Pass `send_user=True` to `init()` and the Django middleware will attach the authenticated user's `id` and `username` to each report. Has no effect outside Django.
83
+
84
+ ```python
85
+ ghosttrap.init("t_your_token_here", send_user=True)
86
+ ```
87
+
88
+ ## Zero dependencies
89
+
90
+ Pure Python stdlib. No transitive dependencies in your production image.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ghosttrap-sdk"
7
- version = "0.4.2"
7
+ version = "0.4.4"
8
8
  description = "Drop-in error reporter for ghosttrap.io"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ghosttrap-sdk
3
- Version: 0.4.2
4
- Summary: Drop-in error reporter for ghosttrap.io
5
- Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-sdk
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
-
9
- # ghosttrap-sdk
10
-
11
- Error reporting for Python apps, built for AI agents. Part of [ghosttrap](https://github.com/alex-rowley/ghosttrap-cli).
12
-
13
- ## Install
14
-
15
- ```
16
- pip install ghosttrap-sdk
17
- ```
18
-
19
- ## Use
20
-
21
- ```python
22
- import ghosttrap
23
- ghosttrap.init("t_your_token_here")
24
- ```
25
-
26
- Get your token by running `ghosttrap setup` from [ghosttrap-cli](https://github.com/alex-rowley/ghosttrap-cli).
27
-
28
- ## What it hooks into
29
-
30
- - **`sys.excepthook`** — unhandled exceptions
31
- - **Python logging** — `logger.exception()` and `logger.error(..., exc_info=True)`
32
- - **Celery** — task failures via `celery.signals.task_failure` (auto-detected)
33
-
34
- ## Django
35
-
36
- ```python
37
- INSTALLED_APPS = [
38
- ...
39
- "ghosttrap.django.GhostTrapApp",
40
- ]
41
-
42
- MIDDLEWARE = [
43
- "ghosttrap.django.GhostTrapMiddleware",
44
- ...
45
- ]
46
- ```
47
-
48
- ## Zero dependencies
49
-
50
- Pure Python stdlib. No transitive dependencies in your production image.
@@ -1,42 +0,0 @@
1
- # ghosttrap-sdk
2
-
3
- Error reporting for Python apps, built for AI agents. Part of [ghosttrap](https://github.com/alex-rowley/ghosttrap-cli).
4
-
5
- ## Install
6
-
7
- ```
8
- pip install ghosttrap-sdk
9
- ```
10
-
11
- ## Use
12
-
13
- ```python
14
- import ghosttrap
15
- ghosttrap.init("t_your_token_here")
16
- ```
17
-
18
- Get your token by running `ghosttrap setup` from [ghosttrap-cli](https://github.com/alex-rowley/ghosttrap-cli).
19
-
20
- ## What it hooks into
21
-
22
- - **`sys.excepthook`** — unhandled exceptions
23
- - **Python logging** — `logger.exception()` and `logger.error(..., exc_info=True)`
24
- - **Celery** — task failures via `celery.signals.task_failure` (auto-detected)
25
-
26
- ## Django
27
-
28
- ```python
29
- INSTALLED_APPS = [
30
- ...
31
- "ghosttrap.django.GhostTrapApp",
32
- ]
33
-
34
- MIDDLEWARE = [
35
- "ghosttrap.django.GhostTrapMiddleware",
36
- ...
37
- ]
38
- ```
39
-
40
- ## Zero dependencies
41
-
42
- Pure Python stdlib. No transitive dependencies in your production image.
@@ -1,3 +0,0 @@
1
- from ghosttrap.client import init, report
2
-
3
- __all__ = ["init", "report"]
@@ -1,50 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ghosttrap-sdk
3
- Version: 0.4.2
4
- Summary: Drop-in error reporter for ghosttrap.io
5
- Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-sdk
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
-
9
- # ghosttrap-sdk
10
-
11
- Error reporting for Python apps, built for AI agents. Part of [ghosttrap](https://github.com/alex-rowley/ghosttrap-cli).
12
-
13
- ## Install
14
-
15
- ```
16
- pip install ghosttrap-sdk
17
- ```
18
-
19
- ## Use
20
-
21
- ```python
22
- import ghosttrap
23
- ghosttrap.init("t_your_token_here")
24
- ```
25
-
26
- Get your token by running `ghosttrap setup` from [ghosttrap-cli](https://github.com/alex-rowley/ghosttrap-cli).
27
-
28
- ## What it hooks into
29
-
30
- - **`sys.excepthook`** — unhandled exceptions
31
- - **Python logging** — `logger.exception()` and `logger.error(..., exc_info=True)`
32
- - **Celery** — task failures via `celery.signals.task_failure` (auto-detected)
33
-
34
- ## Django
35
-
36
- ```python
37
- INSTALLED_APPS = [
38
- ...
39
- "ghosttrap.django.GhostTrapApp",
40
- ]
41
-
42
- MIDDLEWARE = [
43
- "ghosttrap.django.GhostTrapMiddleware",
44
- ...
45
- ]
46
- ```
47
-
48
- ## Zero dependencies
49
-
50
- Pure Python stdlib. No transitive dependencies in your production image.
File without changes