allstak 0.1.2__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.
- allstak-0.1.2/.gitignore +11 -0
- allstak-0.1.2/CHANGELOG.md +132 -0
- allstak-0.1.2/LICENSE +21 -0
- allstak-0.1.2/PKG-INFO +159 -0
- allstak-0.1.2/README.md +104 -0
- allstak-0.1.2/examples/basic_usage.py +137 -0
- allstak-0.1.2/examples/curl-examples.md +348 -0
- allstak-0.1.2/pyproject.toml +105 -0
- allstak-0.1.2/src/allstak/__init__.py +410 -0
- allstak-0.1.2/src/allstak/buffer.py +151 -0
- allstak-0.1.2/src/allstak/client.py +738 -0
- allstak-0.1.2/src/allstak/config.py +378 -0
- allstak-0.1.2/src/allstak/excepthook.py +198 -0
- allstak-0.1.2/src/allstak/integrations/__init__.py +36 -0
- allstak-0.1.2/src/allstak/integrations/auto_breadcrumbs.py +116 -0
- allstak-0.1.2/src/allstak/integrations/celery.py +170 -0
- allstak-0.1.2/src/allstak/integrations/django.py +174 -0
- allstak-0.1.2/src/allstak/integrations/fastapi.py +210 -0
- allstak-0.1.2/src/allstak/integrations/flask.py +173 -0
- allstak-0.1.2/src/allstak/integrations/httpx.py +170 -0
- allstak-0.1.2/src/allstak/integrations/logging.py +174 -0
- allstak-0.1.2/src/allstak/integrations/requests.py +126 -0
- allstak-0.1.2/src/allstak/integrations/sqlalchemy.py +110 -0
- allstak-0.1.2/src/allstak/models/__init__.py +18 -0
- allstak-0.1.2/src/allstak/models/breadcrumb.py +51 -0
- allstak-0.1.2/src/allstak/models/errors.py +165 -0
- allstak-0.1.2/src/allstak/models/heartbeat.py +53 -0
- allstak-0.1.2/src/allstak/models/http_requests.py +129 -0
- allstak-0.1.2/src/allstak/models/logs.py +80 -0
- allstak-0.1.2/src/allstak/models/replay.py +91 -0
- allstak-0.1.2/src/allstak/modules/__init__.py +1 -0
- allstak-0.1.2/src/allstak/modules/cron.py +178 -0
- allstak-0.1.2/src/allstak/modules/database.py +301 -0
- allstak-0.1.2/src/allstak/modules/errors.py +295 -0
- allstak-0.1.2/src/allstak/modules/flags.py +219 -0
- allstak-0.1.2/src/allstak/modules/http_monitor.py +251 -0
- allstak-0.1.2/src/allstak/modules/logs.py +168 -0
- allstak-0.1.2/src/allstak/modules/replay.py +205 -0
- allstak-0.1.2/src/allstak/modules/tracing.py +326 -0
- allstak-0.1.2/src/allstak/propagation.py +101 -0
- allstak-0.1.2/src/allstak/sanitize.py +354 -0
- allstak-0.1.2/src/allstak/session.py +247 -0
- allstak-0.1.2/src/allstak/spool.py +368 -0
- allstak-0.1.2/src/allstak/transport.py +318 -0
- allstak-0.1.2/tests/__init__.py +0 -0
- allstak-0.1.2/tests/conftest.py +30 -0
- allstak-0.1.2/tests/test_auto_breadcrumbs.py +76 -0
- allstak-0.1.2/tests/test_before_send_sampling.py +214 -0
- allstak-0.1.2/tests/test_buffer.py +137 -0
- allstak-0.1.2/tests/test_celery_integration.py +150 -0
- allstak-0.1.2/tests/test_excepthook.py +144 -0
- allstak-0.1.2/tests/test_integration.py +349 -0
- allstak-0.1.2/tests/test_logging_integration.py +134 -0
- allstak-0.1.2/tests/test_models.py +278 -0
- allstak-0.1.2/tests/test_propagation.py +43 -0
- allstak-0.1.2/tests/test_release_autodetect.py +131 -0
- allstak-0.1.2/tests/test_requests_integration.py +68 -0
- allstak-0.1.2/tests/test_sanitize.py +304 -0
- allstak-0.1.2/tests/test_session.py +330 -0
- allstak-0.1.2/tests/test_spool.py +473 -0
- allstak-0.1.2/tests/test_tracing_context.py +45 -0
- allstak-0.1.2/tests/test_transport.py +242 -0
allstak-0.1.2/.gitignore
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the AllStak Python SDK.
|
|
4
|
+
This project follows [Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## 0.1.2 — 2026-05-18
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
- **`capture_exception` always returned `None`** (critical functional bug). The
|
|
10
|
+
client unconditionally raised `AttributeError` on every capture because it
|
|
11
|
+
referenced `self.config` instead of `self._config` when merging release tags.
|
|
12
|
+
The exception was caught and swallowed silently, so the user-visible symptom
|
|
13
|
+
was just `None` return values and no events on the wire. Fix:
|
|
14
|
+
`src/allstak/client.py:235,288`.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **`AllStak.Sanitizer`** (`src/allstak/sanitize.py`) — recursive scrubber for
|
|
18
|
+
the full event surface (user, metadata, breadcrumbs.data, contexts, request,
|
|
19
|
+
response). 25-term canonical denylist; `[REDACTED]` substitution; pure (no
|
|
20
|
+
caller mutation); cycle-safe via identity set.
|
|
21
|
+
- Sanitizer wired into the wire-bound code path
|
|
22
|
+
(`src/allstak/modules/errors.py:_send`) so every event POST is scrubbed
|
|
23
|
+
before transport. Live canary `should_not_leak_python` planted in
|
|
24
|
+
`password` / `authorization` / `cookie` / `Bearer` / `credit_card` / `ssn` /
|
|
25
|
+
nested-token fields — verified `leak_pos = 0` across `metadata`,
|
|
26
|
+
`stack_trace`, `breadcrumbs`, and `message` in production ClickHouse
|
|
27
|
+
(event `f55a4839-357c-4aaa-a353-f4df4d6ff542`).
|
|
28
|
+
- `tests/test_sanitize.py` — denylist, recursion, cycle, mutation tests.
|
|
29
|
+
|
|
30
|
+
## 0.2.0 — 2026-04-11
|
|
31
|
+
|
|
32
|
+
First production-ready release after a full real-world validation pass against a
|
|
33
|
+
FastAPI + SQLAlchemy + SQLite application driving real authentication, CRUD,
|
|
34
|
+
logs, outbound HTTP, cron jobs, and real exceptions — all verified end-to-end
|
|
35
|
+
in the AllStak dashboard.
|
|
36
|
+
|
|
37
|
+
### Highlights
|
|
38
|
+
|
|
39
|
+
- **First-class FastAPI / Starlette integration** (`allstak.integrations.fastapi`)
|
|
40
|
+
— a single line (`AllStakFastAPI(app)`) captures inbound HTTP requests,
|
|
41
|
+
per-request trace IDs, unhandled exceptions, request context (method / path /
|
|
42
|
+
host / status / user-agent), and links every captured error to the owning
|
|
43
|
+
trace.
|
|
44
|
+
- **SQLAlchemy integration** (`allstak.integrations.sqlalchemy.install`) —
|
|
45
|
+
hooks into SQLAlchemy's `before_cursor_execute` / `after_cursor_execute` /
|
|
46
|
+
`handle_error` events to record every ORM and Core query with real
|
|
47
|
+
timings, row counts, dialect detection, and error status. No monkey-patching.
|
|
48
|
+
- **`RequestContext`** is now a first-class part of the error payload so the
|
|
49
|
+
dashboard can show the exact HTTP method / path / host / status on every
|
|
50
|
+
captured exception.
|
|
51
|
+
- **`trace_id` is attached to errors automatically** (not just via metadata),
|
|
52
|
+
so the "Linked Traces" panel in the dashboard works out of the box.
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- `allstak/integrations/fastapi.py` — FastAPI / Starlette ASGI middleware and
|
|
57
|
+
convenience wrapper, plus a new `fastapi` optional-dependency group.
|
|
58
|
+
- `allstak/integrations/sqlalchemy.py` — SQLAlchemy event-based DB
|
|
59
|
+
instrumentation with a `sqlalchemy` optional-dependency group.
|
|
60
|
+
- `allstak.RequestContext` — new dataclass exported at the package root.
|
|
61
|
+
- `allstak.http.track_outbound(...)` now yields a recorder object so callers can
|
|
62
|
+
attach the real response status and body size (`call.set_response(status, size)`).
|
|
63
|
+
- Extensive production-grade PyPI classifiers, URLs (homepage, docs, repo,
|
|
64
|
+
issues, changelog), and an `all` extra that installs every optional
|
|
65
|
+
integration.
|
|
66
|
+
|
|
67
|
+
### Changed
|
|
68
|
+
|
|
69
|
+
- **SDK version bumped from `0.1.0` → `0.2.0`.** New features + new public
|
|
70
|
+
API surface (`RequestContext`, FastAPI / SQLAlchemy integrations,
|
|
71
|
+
`track_outbound` recorder) justify a minor bump under semver: no breaking
|
|
72
|
+
changes for existing code, but meaningful new functionality.
|
|
73
|
+
- `allstak.cron.job(...)` is now a **safe no-op context manager** when the SDK
|
|
74
|
+
is not initialized — previously it returned a plain function and broke
|
|
75
|
+
the documented `with allstak.cron.job("slug"):` idiom for uninitialized apps.
|
|
76
|
+
- `sqlite3` auto-instrumentation now uses a `Connection` factory subclass
|
|
77
|
+
instead of trying to reassign `sqlite3.Cursor.execute` (which raises `TypeError`
|
|
78
|
+
on a built-in type). Standalone `sqlite3` usage is now actually captured.
|
|
79
|
+
- The FastAPI middleware populates `scope["state"]` if missing so auth
|
|
80
|
+
dependencies can safely set `request.state.user` for error correlation.
|
|
81
|
+
- `examples/basic_usage.py` now reads `ALLSTAK_API_KEY` from the environment
|
|
82
|
+
and aborts cleanly if it is missing, instead of shipping a hard-coded key.
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- `HttpMonitorModule.track_outbound` no longer records every outbound call as
|
|
87
|
+
`status_code=0`. The context manager now yields a recorder that carries the
|
|
88
|
+
real status and size, and automatically tags the request with the exception
|
|
89
|
+
class name on failure.
|
|
90
|
+
- Unhandled exceptions from FastAPI route handlers are now captured
|
|
91
|
+
automatically with full request context, stack trace, trace ID, and user
|
|
92
|
+
context — previously you had to call `allstak.capture_exception` manually.
|
|
93
|
+
- Error events now include the current `trace_id` as a proper top-level field,
|
|
94
|
+
so the dashboard's Linked Traces panel resolves immediately.
|
|
95
|
+
|
|
96
|
+
### What's new for Python users
|
|
97
|
+
|
|
98
|
+
- If you use FastAPI:
|
|
99
|
+
```python
|
|
100
|
+
from fastapi import FastAPI
|
|
101
|
+
import allstak
|
|
102
|
+
from allstak.integrations.fastapi import AllStakFastAPI
|
|
103
|
+
|
|
104
|
+
allstak.init(api_key="ask_live_...")
|
|
105
|
+
app = FastAPI()
|
|
106
|
+
AllStakFastAPI(app, service="my-api")
|
|
107
|
+
```
|
|
108
|
+
That is the whole setup. Every request, every exception, and every trace are
|
|
109
|
+
captured automatically.
|
|
110
|
+
- If you use SQLAlchemy (with any dialect — Postgres, MySQL, SQLite, etc.):
|
|
111
|
+
```python
|
|
112
|
+
from sqlalchemy import create_engine
|
|
113
|
+
from allstak.integrations.sqlalchemy import install as install_sqlalchemy
|
|
114
|
+
|
|
115
|
+
engine = create_engine("postgresql://...")
|
|
116
|
+
install_sqlalchemy(engine)
|
|
117
|
+
```
|
|
118
|
+
- Cron monitoring still works exactly as before, but you can now safely use
|
|
119
|
+
`with allstak.cron.job("slug"):` even from scripts that might run without
|
|
120
|
+
the SDK initialized (tests, dry-runs, etc.).
|
|
121
|
+
|
|
122
|
+
### Breaking changes
|
|
123
|
+
|
|
124
|
+
None. `0.1.0` code keeps working as-is.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 0.1.0 — 2026-03-28
|
|
129
|
+
|
|
130
|
+
Initial beta release. Error capture, logs, HTTP monitoring, distributed
|
|
131
|
+
tracing, cron heartbeats, basic Django & Flask integrations, and transport
|
|
132
|
+
with retry/backoff + 401 disable.
|
allstak-0.1.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 AllStak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
allstak-0.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: allstak
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Official Python SDK for AllStak — error tracking, structured logs, HTTP + DB monitoring, distributed tracing, and cron monitoring with first-class FastAPI, Django and Flask support
|
|
5
|
+
Project-URL: Homepage, https://allstak.sa
|
|
6
|
+
Project-URL: Documentation, https://allstak.sa/docs/sdks/python
|
|
7
|
+
Project-URL: Repository, https://github.com/AllStak/allstak-python
|
|
8
|
+
Project-URL: Issues, https://github.com/AllStak/allstak-python/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/AllStak/allstak-python/blob/develop/CHANGELOG.md
|
|
10
|
+
Author-email: AllStak <sdk@allstak.sa>
|
|
11
|
+
Maintainer-email: AllStak <sdk@allstak.sa>
|
|
12
|
+
License: MIT
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Keywords: apm,django,error-tracking,fastapi,flask,logging,monitoring,observability,sqlalchemy,tracing
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: System Administrators
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Classifier: Programming Language :: Python
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
28
|
+
Classifier: Topic :: Software Development :: Bug Tracking
|
|
29
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
30
|
+
Classifier: Topic :: System :: Logging
|
|
31
|
+
Classifier: Topic :: System :: Monitoring
|
|
32
|
+
Classifier: Typing :: Typed
|
|
33
|
+
Requires-Python: >=3.9
|
|
34
|
+
Requires-Dist: httpx>=0.25.0
|
|
35
|
+
Provides-Extra: all
|
|
36
|
+
Requires-Dist: django>=3.2; extra == 'all'
|
|
37
|
+
Requires-Dist: flask>=2.0; extra == 'all'
|
|
38
|
+
Requires-Dist: sqlalchemy>=1.4; extra == 'all'
|
|
39
|
+
Requires-Dist: starlette>=0.27; extra == 'all'
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
42
|
+
Requires-Dist: pytest-mock>=3.12; extra == 'dev'
|
|
43
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
44
|
+
Requires-Dist: python-dotenv>=1.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: respx>=0.20; extra == 'dev'
|
|
46
|
+
Provides-Extra: django
|
|
47
|
+
Requires-Dist: django>=3.2; extra == 'django'
|
|
48
|
+
Provides-Extra: fastapi
|
|
49
|
+
Requires-Dist: starlette>=0.27; extra == 'fastapi'
|
|
50
|
+
Provides-Extra: flask
|
|
51
|
+
Requires-Dist: flask>=2.0; extra == 'flask'
|
|
52
|
+
Provides-Extra: sqlalchemy
|
|
53
|
+
Requires-Dist: sqlalchemy>=1.4; extra == 'sqlalchemy'
|
|
54
|
+
Description-Content-Type: text/markdown
|
|
55
|
+
|
|
56
|
+
# allstak
|
|
57
|
+
|
|
58
|
+
AllStak SDK for Python, Django, Flask, FastAPI, and plain services. Captures exceptions, logs, inbound and outbound HTTP requests, spans, database telemetry, and cron heartbeats.
|
|
59
|
+
|
|
60
|
+
## Install
|
|
61
|
+
|
|
62
|
+
> **Not yet on PyPI.** `pip install allstak` is reserved but does not
|
|
63
|
+
> resolve a published artifact yet. Until first publish lands (tracked
|
|
64
|
+
> in [`docs/devops/sdk-python-dotnet-first-publish.md`](https://github.com/AllStak/allstak/blob/dev/docs/devops/sdk-python-dotnet-first-publish.md)
|
|
65
|
+
> in the platform monorepo), install directly from source:
|
|
66
|
+
>
|
|
67
|
+
> ```bash
|
|
68
|
+
> pip install "git+https://github.com/AllStak/allstak-python.git@develop"
|
|
69
|
+
> ```
|
|
70
|
+
>
|
|
71
|
+
> Once `0.1.x` ships on PyPI, the canonical install becomes:
|
|
72
|
+
>
|
|
73
|
+
> ```bash
|
|
74
|
+
> pip install allstak
|
|
75
|
+
> ```
|
|
76
|
+
|
|
77
|
+
## Setup
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import os
|
|
81
|
+
import allstak
|
|
82
|
+
|
|
83
|
+
allstak.init(
|
|
84
|
+
api_key=os.getenv("ALLSTAK_API_KEY"),
|
|
85
|
+
environment=os.getenv("APP_ENV", "production"),
|
|
86
|
+
release=os.getenv("ALLSTAK_RELEASE"),
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
allstak.log.info("worker started")
|
|
90
|
+
allstak.capture_exception(RuntimeError("checkout failed"))
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## FastAPI
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
from fastapi import FastAPI
|
|
97
|
+
from allstak.integrations.fastapi import AllStakFastAPI
|
|
98
|
+
|
|
99
|
+
app = FastAPI()
|
|
100
|
+
AllStakFastAPI(app, service="checkout-api")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Flask
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from flask import Flask
|
|
107
|
+
from allstak.integrations.flask import AllStakFlask
|
|
108
|
+
|
|
109
|
+
app = Flask(__name__)
|
|
110
|
+
AllStakFlask(app)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Django
|
|
114
|
+
|
|
115
|
+
Add the middleware:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
MIDDLEWARE = [
|
|
119
|
+
"allstak.integrations.django.AllStakDjangoMiddleware",
|
|
120
|
+
*MIDDLEWARE,
|
|
121
|
+
]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Spans
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
with allstak.start_span("checkout.authorize", tags={"provider": "payments"}):
|
|
128
|
+
authorize_payment()
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Configuration
|
|
132
|
+
|
|
133
|
+
| Option | Description |
|
|
134
|
+
| --- | --- |
|
|
135
|
+
| `api_key` | Project API key. |
|
|
136
|
+
| `environment` | Deployment environment. |
|
|
137
|
+
| `release` | App version or commit SHA. |
|
|
138
|
+
| `flush_interval_ms` | Background flush interval. |
|
|
139
|
+
| `buffer_size` | Max buffered events. |
|
|
140
|
+
|
|
141
|
+
## Privacy
|
|
142
|
+
|
|
143
|
+
The SDK redacts common sensitive headers and fields. Avoid putting secrets in custom metadata.
|
|
144
|
+
|
|
145
|
+
## Troubleshooting
|
|
146
|
+
|
|
147
|
+
- No events: confirm `ALLSTAK_API_KEY` is set before `allstak.init(...)`.
|
|
148
|
+
- Missing request telemetry: register the framework integration during app startup.
|
|
149
|
+
- Short-lived script: call `allstak.get_client().flush()` before exit when a client is initialized.
|
|
150
|
+
|
|
151
|
+
## Contributing and Support
|
|
152
|
+
|
|
153
|
+
- Report bugs with the GitHub bug report template: https://github.com/AllStak/allstak-python/issues/new/choose
|
|
154
|
+
- Open pull requests using the checklist in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
155
|
+
- Report security vulnerabilities privately through [SECURITY.md](SECURITY.md).
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT
|
allstak-0.1.2/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# allstak
|
|
2
|
+
|
|
3
|
+
AllStak SDK for Python, Django, Flask, FastAPI, and plain services. Captures exceptions, logs, inbound and outbound HTTP requests, spans, database telemetry, and cron heartbeats.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
> **Not yet on PyPI.** `pip install allstak` is reserved but does not
|
|
8
|
+
> resolve a published artifact yet. Until first publish lands (tracked
|
|
9
|
+
> in [`docs/devops/sdk-python-dotnet-first-publish.md`](https://github.com/AllStak/allstak/blob/dev/docs/devops/sdk-python-dotnet-first-publish.md)
|
|
10
|
+
> in the platform monorepo), install directly from source:
|
|
11
|
+
>
|
|
12
|
+
> ```bash
|
|
13
|
+
> pip install "git+https://github.com/AllStak/allstak-python.git@develop"
|
|
14
|
+
> ```
|
|
15
|
+
>
|
|
16
|
+
> Once `0.1.x` ships on PyPI, the canonical install becomes:
|
|
17
|
+
>
|
|
18
|
+
> ```bash
|
|
19
|
+
> pip install allstak
|
|
20
|
+
> ```
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
import os
|
|
26
|
+
import allstak
|
|
27
|
+
|
|
28
|
+
allstak.init(
|
|
29
|
+
api_key=os.getenv("ALLSTAK_API_KEY"),
|
|
30
|
+
environment=os.getenv("APP_ENV", "production"),
|
|
31
|
+
release=os.getenv("ALLSTAK_RELEASE"),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
allstak.log.info("worker started")
|
|
35
|
+
allstak.capture_exception(RuntimeError("checkout failed"))
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## FastAPI
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from fastapi import FastAPI
|
|
42
|
+
from allstak.integrations.fastapi import AllStakFastAPI
|
|
43
|
+
|
|
44
|
+
app = FastAPI()
|
|
45
|
+
AllStakFastAPI(app, service="checkout-api")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Flask
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from flask import Flask
|
|
52
|
+
from allstak.integrations.flask import AllStakFlask
|
|
53
|
+
|
|
54
|
+
app = Flask(__name__)
|
|
55
|
+
AllStakFlask(app)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Django
|
|
59
|
+
|
|
60
|
+
Add the middleware:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
MIDDLEWARE = [
|
|
64
|
+
"allstak.integrations.django.AllStakDjangoMiddleware",
|
|
65
|
+
*MIDDLEWARE,
|
|
66
|
+
]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Spans
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
with allstak.start_span("checkout.authorize", tags={"provider": "payments"}):
|
|
73
|
+
authorize_payment()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Configuration
|
|
77
|
+
|
|
78
|
+
| Option | Description |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `api_key` | Project API key. |
|
|
81
|
+
| `environment` | Deployment environment. |
|
|
82
|
+
| `release` | App version or commit SHA. |
|
|
83
|
+
| `flush_interval_ms` | Background flush interval. |
|
|
84
|
+
| `buffer_size` | Max buffered events. |
|
|
85
|
+
|
|
86
|
+
## Privacy
|
|
87
|
+
|
|
88
|
+
The SDK redacts common sensitive headers and fields. Avoid putting secrets in custom metadata.
|
|
89
|
+
|
|
90
|
+
## Troubleshooting
|
|
91
|
+
|
|
92
|
+
- No events: confirm `ALLSTAK_API_KEY` is set before `allstak.init(...)`.
|
|
93
|
+
- Missing request telemetry: register the framework integration during app startup.
|
|
94
|
+
- Short-lived script: call `allstak.get_client().flush()` before exit when a client is initialized.
|
|
95
|
+
|
|
96
|
+
## Contributing and Support
|
|
97
|
+
|
|
98
|
+
- Report bugs with the GitHub bug report template: https://github.com/AllStak/allstak-python/issues/new/choose
|
|
99
|
+
- Open pull requests using the checklist in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
100
|
+
- Report security vulnerabilities privately through [SECURITY.md](SECURITY.md).
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Basic usage example — demonstrates core AllStak SDK features.
|
|
3
|
+
|
|
4
|
+
Run with:
|
|
5
|
+
cd allstak-python
|
|
6
|
+
pip install -e ".[dev]"
|
|
7
|
+
python examples/basic_usage.py
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
import time
|
|
13
|
+
|
|
14
|
+
import allstak
|
|
15
|
+
|
|
16
|
+
# ---------------------------------------------------------------------------
|
|
17
|
+
# 1. Initialize the SDK
|
|
18
|
+
#
|
|
19
|
+
# Set ALLSTAK_API_KEY (and optionally ALLSTAK_HOST) in your environment
|
|
20
|
+
# before running this example. Never commit real API keys to source control.
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
api_key = os.environ.get("ALLSTAK_API_KEY")
|
|
24
|
+
if not api_key:
|
|
25
|
+
sys.stderr.write("ALLSTAK_API_KEY is not set — aborting example.\n")
|
|
26
|
+
sys.exit(1)
|
|
27
|
+
|
|
28
|
+
allstak.init(
|
|
29
|
+
api_key=api_key,
|
|
30
|
+
host=os.environ.get("ALLSTAK_HOST", "https://api.allstak.sa"),
|
|
31
|
+
environment=os.environ.get("ALLSTAK_ENVIRONMENT", "development"),
|
|
32
|
+
release=os.environ.get("ALLSTAK_RELEASE", "0.2.0"),
|
|
33
|
+
debug=bool(os.environ.get("ALLSTAK_DEBUG")),
|
|
34
|
+
)
|
|
35
|
+
print("✓ AllStak SDK initialized")
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------
|
|
38
|
+
# 2. Set user context
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
allstak.set_user(user_id="usr-demo-001", email="demo@allstak.dev")
|
|
42
|
+
print("✓ User context set")
|
|
43
|
+
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
# 3. Capture an exception
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
result = 1 / 0
|
|
50
|
+
except ZeroDivisionError as e:
|
|
51
|
+
event_id = allstak.capture_exception(
|
|
52
|
+
e,
|
|
53
|
+
metadata={
|
|
54
|
+
"source": "basic_usage_example",
|
|
55
|
+
"operation": "demo_division",
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
print(f"✓ Exception captured → event ID: {event_id}")
|
|
59
|
+
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
61
|
+
# 4. Capture an error by name (without exception object)
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
event_id = allstak.capture_error(
|
|
65
|
+
exception_class="ExternalServiceError",
|
|
66
|
+
message="Payment gateway timed out after 30s",
|
|
67
|
+
level="error",
|
|
68
|
+
metadata={
|
|
69
|
+
"gateway": "stripe",
|
|
70
|
+
"timeout_ms": 30000,
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
print(f"✓ Error captured → event ID: {event_id}")
|
|
74
|
+
|
|
75
|
+
# ---------------------------------------------------------------------------
|
|
76
|
+
# 5. Log messages
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
allstak.log.info("Application started", service="demo-app")
|
|
80
|
+
allstak.log.warn(
|
|
81
|
+
"Slow query detected",
|
|
82
|
+
service="db-service",
|
|
83
|
+
metadata={"query_ms": 4200, "table": "orders"},
|
|
84
|
+
)
|
|
85
|
+
allstak.log.error(
|
|
86
|
+
"Failed to send email",
|
|
87
|
+
service="notifications",
|
|
88
|
+
metadata={"recipient": "user@example.com", "attempt": 3},
|
|
89
|
+
)
|
|
90
|
+
print("✓ Log messages queued")
|
|
91
|
+
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
# 6. Record HTTP requests
|
|
94
|
+
# ---------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
allstak.http.record(
|
|
97
|
+
direction="outbound",
|
|
98
|
+
method="POST",
|
|
99
|
+
host="payments.stripe.com",
|
|
100
|
+
path="/v1/charges",
|
|
101
|
+
status_code=200,
|
|
102
|
+
duration_ms=320,
|
|
103
|
+
request_size=256,
|
|
104
|
+
response_size=1024,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
allstak.http.record(
|
|
108
|
+
direction="inbound",
|
|
109
|
+
method="GET",
|
|
110
|
+
host="api.myapp.com",
|
|
111
|
+
path="/api/users/me",
|
|
112
|
+
status_code=200,
|
|
113
|
+
duration_ms=18,
|
|
114
|
+
)
|
|
115
|
+
print("✓ HTTP requests recorded")
|
|
116
|
+
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
# 7. Session replay (server-side events)
|
|
119
|
+
# ---------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
import uuid
|
|
122
|
+
session_id = str(uuid.uuid4())
|
|
123
|
+
|
|
124
|
+
with allstak.replay.start_session(session_id=session_id) as session:
|
|
125
|
+
session.record("navigation", {"from": "/home", "to": "/dashboard"})
|
|
126
|
+
session.record("api_call", {"endpoint": "/api/users", "method": "GET"})
|
|
127
|
+
print(f"✓ Replay session {session.session_id[:8]}... recorded")
|
|
128
|
+
|
|
129
|
+
# ---------------------------------------------------------------------------
|
|
130
|
+
# 8. Flush everything
|
|
131
|
+
# ---------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
print("Flushing all buffers...")
|
|
134
|
+
allstak.flush()
|
|
135
|
+
time.sleep(0.5) # give background workers time to complete
|
|
136
|
+
print("✓ All events flushed")
|
|
137
|
+
print("\nDone! Check http://localhost:3000/overview for results.")
|