observe-sdk 0.1.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,2 @@
1
+ include src/tracker.py
2
+ include README.md
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.4
2
+ Name: observe-sdk
3
+ Version: 0.1.0
4
+ Summary: Lightweight observability SDK for Python
5
+ Author-email: Kelechukwu Amadi-Keke <favourkaycee23@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://observe.dev
8
+ Project-URL: Repository, https://github.com/im-kaycee/observability-python-sdk
9
+ Keywords: analytics,observability,monitoring
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: httpx>=0.27.0
13
+
14
+ # observe. — Python SDK
15
+
16
+ The Python SDK for observe. Track server-side events, capture exceptions, and monitor API performance from any Python application.
17
+
18
+ ## Features
19
+
20
+ - Custom event tracking
21
+ - Exception capture with full stack traces
22
+ - User identification
23
+ - Fire and forget — sends in background threads, never blocks your app
24
+ - Works with FastAPI, Django, Flask, or plain Python
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install observe-sdk
30
+ ```
31
+
32
+ > Until published to PyPI, copy `src/tracker.py` into your project directly.
33
+
34
+ ## Quick start
35
+
36
+ ```python
37
+ from tracker import Tracker
38
+
39
+ tracker = Tracker(
40
+ api_key="obs_your_secret_key",
41
+ server_url="https://api.observe.dev",
42
+ )
43
+
44
+ # track an event
45
+ tracker.track(
46
+ event_name="order_placed",
47
+ anonymous_id="anon_abc123",
48
+ properties={"plan": "pro"},
49
+ )
50
+
51
+ # capture an exception
52
+ try:
53
+ process_payment()
54
+ except Exception as e:
55
+ tracker.capture_exception(e, extra={"user_id": "user_123"})
56
+ ```
57
+
58
+ ## Framework guides
59
+
60
+ ### FastAPI
61
+
62
+ Add the middleware to automatically track all requests:
63
+
64
+ ```python
65
+ # main.py
66
+ from fastapi import FastAPI, Request
67
+ from tracker import Tracker
68
+ import time
69
+
70
+ app = FastAPI()
71
+
72
+ tracker = Tracker(
73
+ api_key="obs_your_secret_key",
74
+ server_url="https://api.observe.dev",
75
+ )
76
+
77
+ @app.middleware("http")
78
+ async def track_requests(request: Request, call_next):
79
+ start = time.time()
80
+ try:
81
+ response = await call_next(request)
82
+ duration_ms = round((time.time() - start) * 1000)
83
+ tracker.track(
84
+ event_name="api_request",
85
+ anonymous_id="server",
86
+ properties={
87
+ "method": request.method,
88
+ "path": request.url.path,
89
+ "status_code": response.status_code,
90
+ "duration_ms": duration_ms,
91
+ },
92
+ )
93
+ return response
94
+ except Exception as e:
95
+ tracker.capture_exception(e, extra={"path": request.url.path})
96
+ raise
97
+ ```
98
+
99
+ ### Django
100
+
101
+ Create a middleware file and add it to `settings.py`:
102
+
103
+ ```python
104
+ # observe_middleware.py
105
+ import time
106
+ from tracker import Tracker
107
+
108
+ tracker = Tracker(
109
+ api_key="obs_your_secret_key",
110
+ server_url="https://api.observe.dev",
111
+ )
112
+
113
+ class ObserveMiddleware:
114
+ def __init__(self, get_response):
115
+ self.get_response = get_response
116
+
117
+ def __call__(self, request):
118
+ start = time.time()
119
+ response = self.get_response(request)
120
+ duration_ms = round((time.time() - start) * 1000)
121
+
122
+ tracker.track(
123
+ event_name="api_request",
124
+ anonymous_id=str(request.user.id) if request.user.is_authenticated else "anon",
125
+ properties={
126
+ "method": request.method,
127
+ "path": request.path,
128
+ "status_code": response.status_code,
129
+ "duration_ms": duration_ms,
130
+ },
131
+ )
132
+ return response
133
+
134
+ def process_exception(self, request, exception):
135
+ tracker.capture_exception(exception, extra={
136
+ "path": request.path,
137
+ "method": request.method,
138
+ })
139
+ ```
140
+
141
+ ```python
142
+ # settings.py
143
+ MIDDLEWARE = [
144
+ # ... existing middleware
145
+ "yourapp.observe_middleware.ObserveMiddleware",
146
+ ]
147
+ ```
148
+
149
+ ## API reference
150
+
151
+ ### `Tracker(api_key, server_url)`
152
+
153
+ | Parameter | Type | Required | Description |
154
+ |-----------|------|----------|-------------|
155
+ | `api_key` | str | Yes | Your project secret key |
156
+ | `server_url` | str | Yes | Your observe. server URL |
157
+
158
+ ### `tracker.track(event_name, anonymous_id, properties?)`
159
+
160
+ | Parameter | Type | Required | Description |
161
+ |-----------|------|----------|-------------|
162
+ | `event_name` | str | Yes | Name of the event |
163
+ | `anonymous_id` | str | Yes | Session or visitor ID |
164
+ | `properties` | dict | No | Any additional data |
165
+
166
+ ### `tracker.identify(anonymous_id, user_id)`
167
+
168
+ | Parameter | Type | Required | Description |
169
+ |-----------|------|----------|-------------|
170
+ | `anonymous_id` | str | Yes | Current session ID |
171
+ | `user_id` | str | Yes | Your user's ID |
172
+
173
+ ### `tracker.capture_exception(exception, anonymous_id?, extra?)`
174
+
175
+ | Parameter | Type | Required | Description |
176
+ |-----------|------|----------|-------------|
177
+ | `exception` | Exception | Yes | The caught exception |
178
+ | `anonymous_id` | str | No | Defaults to `"server"` |
179
+ | `extra` | dict | No | Any additional context |
180
+
181
+ ## Development
182
+
183
+ ```bash
184
+ git clone https://github.com/yourname/observability-python-sdk.git
185
+ cd observability-python-sdk
186
+ pip install httpx
187
+
188
+ # run the example
189
+ python examples/basic.py
190
+ ```
191
+
192
+ ## License
193
+
194
+ MIT
@@ -0,0 +1,181 @@
1
+ # observe. — Python SDK
2
+
3
+ The Python SDK for observe. Track server-side events, capture exceptions, and monitor API performance from any Python application.
4
+
5
+ ## Features
6
+
7
+ - Custom event tracking
8
+ - Exception capture with full stack traces
9
+ - User identification
10
+ - Fire and forget — sends in background threads, never blocks your app
11
+ - Works with FastAPI, Django, Flask, or plain Python
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pip install observe-sdk
17
+ ```
18
+
19
+ > Until published to PyPI, copy `src/tracker.py` into your project directly.
20
+
21
+ ## Quick start
22
+
23
+ ```python
24
+ from tracker import Tracker
25
+
26
+ tracker = Tracker(
27
+ api_key="obs_your_secret_key",
28
+ server_url="https://api.observe.dev",
29
+ )
30
+
31
+ # track an event
32
+ tracker.track(
33
+ event_name="order_placed",
34
+ anonymous_id="anon_abc123",
35
+ properties={"plan": "pro"},
36
+ )
37
+
38
+ # capture an exception
39
+ try:
40
+ process_payment()
41
+ except Exception as e:
42
+ tracker.capture_exception(e, extra={"user_id": "user_123"})
43
+ ```
44
+
45
+ ## Framework guides
46
+
47
+ ### FastAPI
48
+
49
+ Add the middleware to automatically track all requests:
50
+
51
+ ```python
52
+ # main.py
53
+ from fastapi import FastAPI, Request
54
+ from tracker import Tracker
55
+ import time
56
+
57
+ app = FastAPI()
58
+
59
+ tracker = Tracker(
60
+ api_key="obs_your_secret_key",
61
+ server_url="https://api.observe.dev",
62
+ )
63
+
64
+ @app.middleware("http")
65
+ async def track_requests(request: Request, call_next):
66
+ start = time.time()
67
+ try:
68
+ response = await call_next(request)
69
+ duration_ms = round((time.time() - start) * 1000)
70
+ tracker.track(
71
+ event_name="api_request",
72
+ anonymous_id="server",
73
+ properties={
74
+ "method": request.method,
75
+ "path": request.url.path,
76
+ "status_code": response.status_code,
77
+ "duration_ms": duration_ms,
78
+ },
79
+ )
80
+ return response
81
+ except Exception as e:
82
+ tracker.capture_exception(e, extra={"path": request.url.path})
83
+ raise
84
+ ```
85
+
86
+ ### Django
87
+
88
+ Create a middleware file and add it to `settings.py`:
89
+
90
+ ```python
91
+ # observe_middleware.py
92
+ import time
93
+ from tracker import Tracker
94
+
95
+ tracker = Tracker(
96
+ api_key="obs_your_secret_key",
97
+ server_url="https://api.observe.dev",
98
+ )
99
+
100
+ class ObserveMiddleware:
101
+ def __init__(self, get_response):
102
+ self.get_response = get_response
103
+
104
+ def __call__(self, request):
105
+ start = time.time()
106
+ response = self.get_response(request)
107
+ duration_ms = round((time.time() - start) * 1000)
108
+
109
+ tracker.track(
110
+ event_name="api_request",
111
+ anonymous_id=str(request.user.id) if request.user.is_authenticated else "anon",
112
+ properties={
113
+ "method": request.method,
114
+ "path": request.path,
115
+ "status_code": response.status_code,
116
+ "duration_ms": duration_ms,
117
+ },
118
+ )
119
+ return response
120
+
121
+ def process_exception(self, request, exception):
122
+ tracker.capture_exception(exception, extra={
123
+ "path": request.path,
124
+ "method": request.method,
125
+ })
126
+ ```
127
+
128
+ ```python
129
+ # settings.py
130
+ MIDDLEWARE = [
131
+ # ... existing middleware
132
+ "yourapp.observe_middleware.ObserveMiddleware",
133
+ ]
134
+ ```
135
+
136
+ ## API reference
137
+
138
+ ### `Tracker(api_key, server_url)`
139
+
140
+ | Parameter | Type | Required | Description |
141
+ |-----------|------|----------|-------------|
142
+ | `api_key` | str | Yes | Your project secret key |
143
+ | `server_url` | str | Yes | Your observe. server URL |
144
+
145
+ ### `tracker.track(event_name, anonymous_id, properties?)`
146
+
147
+ | Parameter | Type | Required | Description |
148
+ |-----------|------|----------|-------------|
149
+ | `event_name` | str | Yes | Name of the event |
150
+ | `anonymous_id` | str | Yes | Session or visitor ID |
151
+ | `properties` | dict | No | Any additional data |
152
+
153
+ ### `tracker.identify(anonymous_id, user_id)`
154
+
155
+ | Parameter | Type | Required | Description |
156
+ |-----------|------|----------|-------------|
157
+ | `anonymous_id` | str | Yes | Current session ID |
158
+ | `user_id` | str | Yes | Your user's ID |
159
+
160
+ ### `tracker.capture_exception(exception, anonymous_id?, extra?)`
161
+
162
+ | Parameter | Type | Required | Description |
163
+ |-----------|------|----------|-------------|
164
+ | `exception` | Exception | Yes | The caught exception |
165
+ | `anonymous_id` | str | No | Defaults to `"server"` |
166
+ | `extra` | dict | No | Any additional context |
167
+
168
+ ## Development
169
+
170
+ ```bash
171
+ git clone https://github.com/yourname/observability-python-sdk.git
172
+ cd observability-python-sdk
173
+ pip install httpx
174
+
175
+ # run the example
176
+ python examples/basic.py
177
+ ```
178
+
179
+ ## License
180
+
181
+ MIT
@@ -0,0 +1,17 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+ [project]
5
+ name = "observe-sdk"
6
+ version = "0.1.0"
7
+ description = "Lightweight observability SDK for Python"
8
+ readme = "README.md"
9
+ license = { text = "MIT" }
10
+ authors = [{ name = "Kelechukwu Amadi-Keke", email = "favourkaycee23@gmail.com" }]
11
+ keywords = ["analytics", "observability", "monitoring"]
12
+ requires-python = ">=3.9"
13
+ dependencies = ["httpx>=0.27.0"]
14
+
15
+ [project.urls]
16
+ Homepage = "https://observe.dev"
17
+ Repository = "https://github.com/im-kaycee/observability-python-sdk"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,194 @@
1
+ Metadata-Version: 2.4
2
+ Name: observe-sdk
3
+ Version: 0.1.0
4
+ Summary: Lightweight observability SDK for Python
5
+ Author-email: Kelechukwu Amadi-Keke <favourkaycee23@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://observe.dev
8
+ Project-URL: Repository, https://github.com/im-kaycee/observability-python-sdk
9
+ Keywords: analytics,observability,monitoring
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: httpx>=0.27.0
13
+
14
+ # observe. — Python SDK
15
+
16
+ The Python SDK for observe. Track server-side events, capture exceptions, and monitor API performance from any Python application.
17
+
18
+ ## Features
19
+
20
+ - Custom event tracking
21
+ - Exception capture with full stack traces
22
+ - User identification
23
+ - Fire and forget — sends in background threads, never blocks your app
24
+ - Works with FastAPI, Django, Flask, or plain Python
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install observe-sdk
30
+ ```
31
+
32
+ > Until published to PyPI, copy `src/tracker.py` into your project directly.
33
+
34
+ ## Quick start
35
+
36
+ ```python
37
+ from tracker import Tracker
38
+
39
+ tracker = Tracker(
40
+ api_key="obs_your_secret_key",
41
+ server_url="https://api.observe.dev",
42
+ )
43
+
44
+ # track an event
45
+ tracker.track(
46
+ event_name="order_placed",
47
+ anonymous_id="anon_abc123",
48
+ properties={"plan": "pro"},
49
+ )
50
+
51
+ # capture an exception
52
+ try:
53
+ process_payment()
54
+ except Exception as e:
55
+ tracker.capture_exception(e, extra={"user_id": "user_123"})
56
+ ```
57
+
58
+ ## Framework guides
59
+
60
+ ### FastAPI
61
+
62
+ Add the middleware to automatically track all requests:
63
+
64
+ ```python
65
+ # main.py
66
+ from fastapi import FastAPI, Request
67
+ from tracker import Tracker
68
+ import time
69
+
70
+ app = FastAPI()
71
+
72
+ tracker = Tracker(
73
+ api_key="obs_your_secret_key",
74
+ server_url="https://api.observe.dev",
75
+ )
76
+
77
+ @app.middleware("http")
78
+ async def track_requests(request: Request, call_next):
79
+ start = time.time()
80
+ try:
81
+ response = await call_next(request)
82
+ duration_ms = round((time.time() - start) * 1000)
83
+ tracker.track(
84
+ event_name="api_request",
85
+ anonymous_id="server",
86
+ properties={
87
+ "method": request.method,
88
+ "path": request.url.path,
89
+ "status_code": response.status_code,
90
+ "duration_ms": duration_ms,
91
+ },
92
+ )
93
+ return response
94
+ except Exception as e:
95
+ tracker.capture_exception(e, extra={"path": request.url.path})
96
+ raise
97
+ ```
98
+
99
+ ### Django
100
+
101
+ Create a middleware file and add it to `settings.py`:
102
+
103
+ ```python
104
+ # observe_middleware.py
105
+ import time
106
+ from tracker import Tracker
107
+
108
+ tracker = Tracker(
109
+ api_key="obs_your_secret_key",
110
+ server_url="https://api.observe.dev",
111
+ )
112
+
113
+ class ObserveMiddleware:
114
+ def __init__(self, get_response):
115
+ self.get_response = get_response
116
+
117
+ def __call__(self, request):
118
+ start = time.time()
119
+ response = self.get_response(request)
120
+ duration_ms = round((time.time() - start) * 1000)
121
+
122
+ tracker.track(
123
+ event_name="api_request",
124
+ anonymous_id=str(request.user.id) if request.user.is_authenticated else "anon",
125
+ properties={
126
+ "method": request.method,
127
+ "path": request.path,
128
+ "status_code": response.status_code,
129
+ "duration_ms": duration_ms,
130
+ },
131
+ )
132
+ return response
133
+
134
+ def process_exception(self, request, exception):
135
+ tracker.capture_exception(exception, extra={
136
+ "path": request.path,
137
+ "method": request.method,
138
+ })
139
+ ```
140
+
141
+ ```python
142
+ # settings.py
143
+ MIDDLEWARE = [
144
+ # ... existing middleware
145
+ "yourapp.observe_middleware.ObserveMiddleware",
146
+ ]
147
+ ```
148
+
149
+ ## API reference
150
+
151
+ ### `Tracker(api_key, server_url)`
152
+
153
+ | Parameter | Type | Required | Description |
154
+ |-----------|------|----------|-------------|
155
+ | `api_key` | str | Yes | Your project secret key |
156
+ | `server_url` | str | Yes | Your observe. server URL |
157
+
158
+ ### `tracker.track(event_name, anonymous_id, properties?)`
159
+
160
+ | Parameter | Type | Required | Description |
161
+ |-----------|------|----------|-------------|
162
+ | `event_name` | str | Yes | Name of the event |
163
+ | `anonymous_id` | str | Yes | Session or visitor ID |
164
+ | `properties` | dict | No | Any additional data |
165
+
166
+ ### `tracker.identify(anonymous_id, user_id)`
167
+
168
+ | Parameter | Type | Required | Description |
169
+ |-----------|------|----------|-------------|
170
+ | `anonymous_id` | str | Yes | Current session ID |
171
+ | `user_id` | str | Yes | Your user's ID |
172
+
173
+ ### `tracker.capture_exception(exception, anonymous_id?, extra?)`
174
+
175
+ | Parameter | Type | Required | Description |
176
+ |-----------|------|----------|-------------|
177
+ | `exception` | Exception | Yes | The caught exception |
178
+ | `anonymous_id` | str | No | Defaults to `"server"` |
179
+ | `extra` | dict | No | Any additional context |
180
+
181
+ ## Development
182
+
183
+ ```bash
184
+ git clone https://github.com/yourname/observability-python-sdk.git
185
+ cd observability-python-sdk
186
+ pip install httpx
187
+
188
+ # run the example
189
+ python examples/basic.py
190
+ ```
191
+
192
+ ## License
193
+
194
+ MIT
@@ -0,0 +1,9 @@
1
+ MANIFEST.in
2
+ README.md
3
+ pyproject.toml
4
+ src/tracker.py
5
+ src/observe_sdk.egg-info/PKG-INFO
6
+ src/observe_sdk.egg-info/SOURCES.txt
7
+ src/observe_sdk.egg-info/dependency_links.txt
8
+ src/observe_sdk.egg-info/requires.txt
9
+ src/observe_sdk.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ httpx>=0.27.0
@@ -0,0 +1,75 @@
1
+ import traceback
2
+ import threading
3
+ import httpx
4
+ from typing import Any
5
+
6
+
7
+ class Tracker:
8
+ def __init__(self, api_key: str, server_url: str):
9
+ if not api_key:
10
+ raise ValueError("Tracker: api_key is required")
11
+ if not server_url:
12
+ raise ValueError("Tracker: server_url is required")
13
+
14
+ self._api_key = api_key
15
+ self._server_url = server_url.rstrip("/")
16
+ self._headers = {
17
+ "Authorization": f"Bearer {self._api_key}",
18
+ "Content-Type": "application/json",
19
+ }
20
+
21
+ # ---- Tracking ----
22
+
23
+ def track(self, event_name: str, anonymous_id: str, properties: dict[str, Any] = {}):
24
+ """Track a custom server-side event."""
25
+ if not event_name:
26
+ return
27
+ self._send("/ingest/events", {
28
+ "name": event_name,
29
+ "anonymous_id": anonymous_id,
30
+ "properties": properties,
31
+ })
32
+
33
+ def identify(self, anonymous_id: str, user_id: str):
34
+ """Link an anonymous_id to a known user_id."""
35
+ self._send("/ingest/identify", {
36
+ "anonymous_id": anonymous_id,
37
+ "user_id": str(user_id),
38
+ })
39
+
40
+ def capture_exception(self, e: Exception, anonymous_id: str = "server", extra: dict = {}):
41
+ """Capture an exception and send it as an event with the stack trace."""
42
+ self.track(
43
+ event_name="exception",
44
+ anonymous_id=anonymous_id,
45
+ properties={
46
+ "exception_type": type(e).__name__,
47
+ "message": str(e),
48
+ "stack_trace": traceback.format_exc(),
49
+ **extra,
50
+ },
51
+ )
52
+
53
+ # ---- Transport ----
54
+
55
+ def _send(self, endpoint: str, payload: dict):
56
+ """Fire and forget — runs in a background thread so it never blocks."""
57
+ thread = threading.Thread(
58
+ target=self._post,
59
+ args=(endpoint, payload),
60
+ daemon=True,
61
+ )
62
+ thread.start()
63
+
64
+ def _post(self, endpoint: str, payload: dict):
65
+ try:
66
+ with httpx.Client() as client:
67
+ client.post(
68
+ f"{self._server_url}{endpoint}",
69
+ json=payload,
70
+ headers=self._headers,
71
+ timeout=5.0,
72
+ )
73
+ except Exception as e:
74
+ # fail silently — tracking should never crash the host app
75
+ print(f"Tracker: failed to send event — {e}")