vitalwatch 0.1.1__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.
- vitalwatch-0.1.1/LICENSE +21 -0
- vitalwatch-0.1.1/PKG-INFO +320 -0
- vitalwatch-0.1.1/README.md +306 -0
- vitalwatch-0.1.1/pyproject.toml +28 -0
- vitalwatch-0.1.1/setup.cfg +4 -0
- vitalwatch-0.1.1/src/vitalwatch/__init__.py +274 -0
- vitalwatch-0.1.1/src/vitalwatch/asgi.py +434 -0
- vitalwatch-0.1.1/src/vitalwatch/cli.py +212 -0
- vitalwatch-0.1.1/src/vitalwatch/client.py +156 -0
- vitalwatch-0.1.1/src/vitalwatch/django.py +221 -0
- vitalwatch-0.1.1/src/vitalwatch/env.py +122 -0
- vitalwatch-0.1.1/src/vitalwatch/flask.py +231 -0
- vitalwatch-0.1.1/src/vitalwatch/release.py +191 -0
- vitalwatch-0.1.1/src/vitalwatch/reporter.py +392 -0
- vitalwatch-0.1.1/src/vitalwatch/scrubber.py +151 -0
- vitalwatch-0.1.1/src/vitalwatch.egg-info/PKG-INFO +320 -0
- vitalwatch-0.1.1/src/vitalwatch.egg-info/SOURCES.txt +29 -0
- vitalwatch-0.1.1/src/vitalwatch.egg-info/dependency_links.txt +1 -0
- vitalwatch-0.1.1/src/vitalwatch.egg-info/entry_points.txt +2 -0
- vitalwatch-0.1.1/src/vitalwatch.egg-info/top_level.txt +1 -0
- vitalwatch-0.1.1/tests/test_asgi.py +542 -0
- vitalwatch-0.1.1/tests/test_client.py +110 -0
- vitalwatch-0.1.1/tests/test_django.py +250 -0
- vitalwatch-0.1.1/tests/test_env.py +89 -0
- vitalwatch-0.1.1/tests/test_environment.py +49 -0
- vitalwatch-0.1.1/tests/test_flask.py +237 -0
- vitalwatch-0.1.1/tests/test_hooks.py +182 -0
- vitalwatch-0.1.1/tests/test_release.py +244 -0
- vitalwatch-0.1.1/tests/test_reporter.py +178 -0
- vitalwatch-0.1.1/tests/test_scrubber.py +96 -0
- vitalwatch-0.1.1/tests/test_status.py +176 -0
vitalwatch-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CestnyTR
|
|
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.
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vitalwatch
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: VitalWatch Hub için Python raporlayıcı — sunucu hataları, yavaş istekler, canlılık
|
|
5
|
+
Author: CestnyTR
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/CestnyTR/vitalwatch-python
|
|
8
|
+
Project-URL: Hub, https://github.com/CestnyTR/vitalwatch-hub
|
|
9
|
+
Keywords: monitoring,error-tracking,flask,wsgi,vitalwatch
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# vitalwatch (Python)
|
|
16
|
+
|
|
17
|
+
[VitalWatch Hub](https://github.com/CestnyTR/vitalwatch-hub) için Python raporlayıcı: sunucu
|
|
18
|
+
hataları, yavaş istekler, canlılık.
|
|
19
|
+
|
|
20
|
+
Bağımlılık yok. Build adımı yok. Python 3.9+.
|
|
21
|
+
|
|
22
|
+
Kardeş paketler: `cestnytr/vitalwatch-laravel` (Laravel), `vitalwatch-node` (Node),
|
|
23
|
+
`t.js` (tarayıcı, hub reposunda `resources/sdk/t.js`).
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Kapsam — ve neden bu kadar dar
|
|
28
|
+
|
|
29
|
+
Bu paket **yalnızca sunucu tarafını** kapsar. Tarayıcı hataları hub'dan servis edilen
|
|
30
|
+
`t.js` ile toplanır; o dosya bilinçli olarak pakete taşınmadı — hosted olması bir
|
|
31
|
+
düzeltmenin dakikalar içinde tüm sitelere yayılmasını sağlıyor, paket olsaydı her
|
|
32
|
+
düzeltme için bütün projelerin yeniden dağıtılması gerekirdi.
|
|
33
|
+
|
|
34
|
+
Toplanmayanlar — yapılandırmayla dahi açılamaz:
|
|
35
|
+
|
|
36
|
+
IP adresi · User-Agent · istek gövdesi · query string **değerleri** (yalnızca yol) ·
|
|
37
|
+
oturum verisi · çerez · ham SQL literalleri
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Kurulum
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install git+https://github.com/CestnyTR/vitalwatch-python.git
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`.env` dosyasına — kardeş paketlerle aynı değişken isimleri:
|
|
48
|
+
|
|
49
|
+
```env
|
|
50
|
+
VITALWATCH_ENABLED=true
|
|
51
|
+
VITALWATCH_URL=https://vitalwatch.example.com
|
|
52
|
+
VITALWATCH_KEY=proje-anahtari
|
|
53
|
+
VITALWATCH_SECRET=<panelden alınan 64 karakterlik secret>
|
|
54
|
+
VITALWATCH_ENV=production
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Flask
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from flask import Flask
|
|
61
|
+
from vitalwatch.flask import VitalWatchFlask
|
|
62
|
+
|
|
63
|
+
app = Flask(__name__)
|
|
64
|
+
VitalWatchFlask(app)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Tek satır şunları kurar: yakalanmamış istisnalar (`teardown_request`), 5xx ve yavaş
|
|
68
|
+
istekler (`after_request`), süreç düzeyi kancalar (`sys.excepthook`,
|
|
69
|
+
`threading.excepthook`) ve 8 saatlik canlılık isteği.
|
|
70
|
+
|
|
71
|
+
- **Tek arıza, tek kayıt:** hata veren istek yalnızca stack'li `exception` açar;
|
|
72
|
+
aynı istek için ayrıca `http_5xx` gönderilmez (0.1.1+).
|
|
73
|
+
- **Kendi hata işleyiciniz varsa:** `@app.errorhandler(Exception)` ya da
|
|
74
|
+
`errorhandler(500)` tanımlıysa hata yine stack'iyle gelir. İşleyici 4xx dönerse
|
|
75
|
+
gönderilmez. Eskiden bu durumda hata kayboluyor, yalnızca stack'siz `http_5xx`
|
|
76
|
+
geliyordu.
|
|
77
|
+
- **`abort(4xx)` gönderilmez:** bilinçli yanıt, arıza değil.
|
|
78
|
+
- **Kurulum sırası serbest:** `VitalWatchFlask(app)` önce, `vitalwatch.init(...)` sonra
|
|
79
|
+
çağrılabilir; istek kancaları da süreç kancaları da (`sys.excepthook`,
|
|
80
|
+
`threading.excepthook`) güncel raporlayıcıyı çağrı anında çözer. Kurulumda
|
|
81
|
+
yapılandırma yoksa canlılık `init(...)` çağrılınca başlar.
|
|
82
|
+
- **İki kez kurmak zararsız:** aynı uygulamada ikinci `VitalWatchFlask(app)` hiçbir
|
|
83
|
+
şey eklemez; süreç kancaları süreç başına bir kez kurulur.
|
|
84
|
+
- **Uygulamayı düşürmez:** kurulum (bozuk ya da UTF-8 olmayan `.env` dahil)
|
|
85
|
+
hiçbir koşulda hata fırlatmaz.
|
|
86
|
+
- **Süreç kancalarını kapatmak:** `VitalWatchFlask(app, hook_process_errors=False)`
|
|
87
|
+
yalnızca istek kancalarını kurar.
|
|
88
|
+
|
|
89
|
+
### Django
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
# settings.py
|
|
93
|
+
MIDDLEWARE = [
|
|
94
|
+
"vitalwatch.django.VitalWatchMiddleware", # listenin başına yakın
|
|
95
|
+
# ...
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Ara katman yavaş ve 5xx istekleri ölçer, yakalanmamış istisnayı stack'iyle gönderir.
|
|
100
|
+
Hata iki yoldan görülür: Django'nun istisnayı 500'e çevirirken yolladığı
|
|
101
|
+
`got_request_exception` sinyali (görünümün yanında alttaki ara katmanlardan çıkan
|
|
102
|
+
hatalar da) ve `process_exception`. Kurallar Flask'la aynı:
|
|
103
|
+
|
|
104
|
+
- **Tek arıza, tek kayıt;** hata veren istek için ayrıca `http_5xx` açılmaz.
|
|
105
|
+
- **4xx gönderilmez:** `Http404`, `PermissionDenied`, `BadRequest`,
|
|
106
|
+
`SuspiciousOperation`.
|
|
107
|
+
- **Rota deseni gider:** `/urun/<int:urun_id>/`, gerçek id değil. `re_path`
|
|
108
|
+
desenlerinde baştaki `^` ve sondaki `$` atılır.
|
|
109
|
+
- **Hata yutulmaz:** `process_exception` `None` döner; Django'nun 500 sayfası ve
|
|
110
|
+
`handler500` olduğu gibi çalışır.
|
|
111
|
+
- **Süreç kancaları** ilk kurulumda bir kez açılır; kapatmak için
|
|
112
|
+
`VITALWATCH_HOOK_PROCESS = False`.
|
|
113
|
+
|
|
114
|
+
### FastAPI / Starlette (ASGI)
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from fastapi import FastAPI
|
|
118
|
+
from vitalwatch.asgi import VitalWatchASGIMiddleware
|
|
119
|
+
|
|
120
|
+
app = FastAPI()
|
|
121
|
+
app.add_middleware(VitalWatchASGIMiddleware)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Starlette'te aynı satır (`Starlette(middleware=[Middleware(VitalWatchASGIMiddleware)])` de
|
|
125
|
+
olur). Başka bir ASGI uygulaması doğrudan sarılabilir: `app = VitalWatchASGIMiddleware(app)`.
|
|
126
|
+
Saf ASGI ara katmanıdır; Starlette/FastAPI import anında yüklenmez.
|
|
127
|
+
|
|
128
|
+
- **Tek arıza, tek kayıt;** 4xx `HTTPException` ve doğrulama hataları (422)
|
|
129
|
+
gönderilmez. Bilinçli `HTTPException(5xx)` stack'siz `http_5xx` olarak düşer.
|
|
130
|
+
- **Rota deseni gider:** `/urun/{urun_id}`; `include_router` öneki ve `Mount`
|
|
131
|
+
yolu desene eklenir.
|
|
132
|
+
- **Kendi hata işleyiciniz varsa:** `@app.exception_handler(Exception)` hatayı
|
|
133
|
+
yine bizim katmanımızdan geçirir. Belirli bir sınıfa bağlı işleyici
|
|
134
|
+
(`@app.exception_handler(ValueError)`) 5xx dönerse hata yine stack'iyle gelir,
|
|
135
|
+
4xx dönerse gönderilmez. Ara katman sırası fark etmez (`add_middleware` ya da
|
|
136
|
+
`middleware=[...]` içinde herhangi bir yer). Elle sarılan uygulamada
|
|
137
|
+
(`VitalWatchASGIMiddleware(app)`) Starlette yığınını ilk istekte kurduğu için bu
|
|
138
|
+
ilk istekten sonra devreye girer; o ilk istekte 5xx stack'siz `http_5xx` olur.
|
|
139
|
+
- **Süre yanıtın son baytında durur:** `BackgroundTasks` ve yanıt sonrası işler
|
|
140
|
+
yavaş istek sayılmaz. Uzun akış (SSE, büyük indirme) son parçaya kadar sürer
|
|
141
|
+
ve yavaş sayılabilir.
|
|
142
|
+
- **İç içe katman tek kayıt açar:** `Mount` edilen alt uygulamada da
|
|
143
|
+
`VitalWatchASGIMiddleware` varsa istek yalnızca dıştakinde ölçülür.
|
|
144
|
+
- **Hata yutulmaz:** raporlanır ve yeniden fırlatılır; lifespan ve websocket
|
|
145
|
+
olduğu gibi geçer.
|
|
146
|
+
- **Süreç kancalarını kapatmak:**
|
|
147
|
+
`app.add_middleware(VitalWatchASGIMiddleware, hook_process_errors=False)`.
|
|
148
|
+
|
|
149
|
+
### Çerçevesiz
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
import vitalwatch
|
|
153
|
+
|
|
154
|
+
vitalwatch.hook_process() # kancalar + canlılık
|
|
155
|
+
vitalwatch.report(error) # elle bildirim
|
|
156
|
+
|
|
157
|
+
vitalwatch.init(ignore=(KeyboardInterrupt, "BenimBeklenenHatam")) # sınıf ya da ad
|
|
158
|
+
vitalwatch.start_heartbeat() # yalnızca canlılık (hook_process zaten başlatır)
|
|
159
|
+
vitalwatch.stop_heartbeat()
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`init()` ortam değişkenlerini okur; verilen argümanlar onları ezer. Çağrılmazsa ilk
|
|
163
|
+
kullanımda kendiliğinden kurulur.
|
|
164
|
+
|
|
165
|
+
### Kurulumu doğrulayın
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
vitalwatch-status
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Bu adım atlanmamalı. Paketin en pahalı arıza biçimi **sessiz çalışmamadır**: secret
|
|
172
|
+
eksik kopyalanmışsa hiçbir şey patlamaz, hiçbir log düşmez — hub geçersiz imzaya da
|
|
173
|
+
`204` döner. Kurulum aylarca çalışmıyor olabilir ve o sessizlik "sorun yok" sanılır.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
vitalwatch-status --test # gerçek bir sınama olayı — panelde hata olarak görünür
|
|
177
|
+
vitalwatch-status --vitalwatch # yalnızca canlılık isteği — panele hata düşürmez
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
`--test` tek bir kurulumu doğrularken doğru seçim. **Onlarca kurulumu gezen bir
|
|
181
|
+
güncelleme döngüsünde `--vitalwatch` kullanılır** — `--test` orada panele onlarca sahte hata
|
|
182
|
+
bırakır, yani izleme aracı kendi gürültüsünü üretir.
|
|
183
|
+
|
|
184
|
+
Verinin gerçekten ulaştığı yalnızca **hub panelinden** doğrulanır: proje satırındaki
|
|
185
|
+
bağlantı durumu `Bağlı` görünmelidir. Komut bunu kendi başına söyleyemez, çünkü hub
|
|
186
|
+
geçerli ile geçersiz imzayı dışarıya aynı yanıtla karşılar.
|
|
187
|
+
|
|
188
|
+
Komut ayrıca şunları gösterir:
|
|
189
|
+
|
|
190
|
+
- **`Sürüm etiketi`** — olaylara eklenecek `release` ve nereden bulunduğu:
|
|
191
|
+
`abc123def456 (kaynak: .git)`; kaynak `VITALWATCH_RELEASE`, bir CI/PaaS değişkeninin
|
|
192
|
+
adı, `.git` ya da `yok`. Ayrıntı: [Sürüm etiketi](#sürüm-etiketi-release).
|
|
193
|
+
- **`Güncel sürüm`** — GitHub etiketlerindeki en yeni kararlı sürüm (paket PyPI'da
|
|
194
|
+
değil). Kurulu sürümden yeniyse bir `Güncelleme var: pip install -U
|
|
195
|
+
--force-reinstall "vitalwatch @ git+…@vX.Y.Z"` satırı yazılır; bu bir uyarıdır,
|
|
196
|
+
çıkış kodunu değiştirmez. Ağ yoksa ya da GitHub hız sınırına takıldıysa
|
|
197
|
+
`denetlenemedi` yazar (2 sn zaman aşımı). Ağa hiç çıkılmaması için
|
|
198
|
+
`VITALWATCH_STATUS_OFFLINE=1` (`1`, `true`, `yes`, `on`, `evet`; büyük/küçük harf fark
|
|
199
|
+
etmez) — o durumda `Güncel sürüm` satırı hiç yazılmaz.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Yapılandırma
|
|
204
|
+
|
|
205
|
+
| Değişken | Varsayılan | Açıklama |
|
|
206
|
+
|---|---|---|
|
|
207
|
+
| `VITALWATCH_ENABLED` | `true` | `false` iken hiçbir veri gönderilmez |
|
|
208
|
+
| `VITALWATCH_URL` | — | Hub adresi (https) |
|
|
209
|
+
| `VITALWATCH_KEY` | — | Proje anahtarı |
|
|
210
|
+
| `VITALWATCH_SECRET` | — | 64 karakterlik imza secret'i |
|
|
211
|
+
| `VITALWATCH_ENV` | `APP_ENV` | `production` · `staging` · `local`. Takma adlar çevrilir: `prod`/`live` → production, `stage`/`stg`/`preprod`/`uat` → staging, `dev`/`development`/`test`/`testing` → local. Tanınmayan değeri hub reddeder; teşhis komutu hata verir |
|
|
212
|
+
| `VITALWATCH_RELEASE` | kendiliğinden | Sürüm etiketi. Boşsa CI/PaaS commit değişkenlerinden ya da `.git`'ten bulunur — aşağıya bakın |
|
|
213
|
+
| `VITALWATCH_STATUS_OFFLINE` | — | `1`/`true`/`yes`/`on`/`evet` iken `vitalwatch-status` güncelleme denetimi için ağa çıkmaz |
|
|
214
|
+
| `VITALWATCH_TIMEOUT` | `2.0` | Gönderim zaman aşımı, **saniye**. 100 ve üstü milisaniye sayılır — Node aynı adla ms bekliyor, `2000` yazan 2000 saniye beklemesin. Geçersiz, sıfır/eksi, NaN ya da sonsuz → 2 sn; sonuç 0.1–10 sn aralığına sıkıştırılır |
|
|
215
|
+
| `VITALWATCH_SLOW_REQUEST_MS` | `1000` | Yavaş istek eşiği |
|
|
216
|
+
|
|
217
|
+
Ortam değişkenleri `os.environ` ve `.env` / `.env.local` / `.env.<APP_ENV>`
|
|
218
|
+
dosyalarından okunur; süreç ortamı her zaman kazanır. Yalnızca `VITALWATCH_` önekli
|
|
219
|
+
anahtarlar okunur.
|
|
220
|
+
|
|
221
|
+
### Sürüm etiketi (`release`)
|
|
222
|
+
|
|
223
|
+
`VITALWATCH_RELEASE` neredeyse hiçbir kurulumda doldurulmuyordu; hub bu yüzden bir hatanın
|
|
224
|
+
**hangi deploy ile başladığını** söyleyemiyordu. Deploy'larımız çoğunlukla sunucuda
|
|
225
|
+
`git pull` + gunicorn yeniden başlatma: yeni süreç açılışta commit'i kendisi okur, deploy
|
|
226
|
+
sonrası ilk hatada panel yeni sürümü görür. Etiket kurulumda bir kez çözülür (olay başına
|
|
227
|
+
değil); ilk dolu kaynak kazanır:
|
|
228
|
+
|
|
229
|
+
1. `init(release=...)` ile açıkça verilen değer.
|
|
230
|
+
2. `VITALWATCH_RELEASE` — kırpılır, en çok 64 karakter, olduğu gibi.
|
|
231
|
+
3. Sırasıyla `GIT_COMMIT`, `GIT_SHA`, `COMMIT_SHA`, `SOURCE_VERSION`,
|
|
232
|
+
`VERCEL_GIT_COMMIT_SHA`, `RENDER_GIT_COMMIT`, `HEROKU_SLUG_COMMIT`, `CI_COMMIT_SHA`.
|
|
233
|
+
7–40 hane hex ise küçük harfle ilk 12 hane; değilse kırpılmış, en çok 64 karakter.
|
|
234
|
+
4. Çalışma dizinindeki git checkout'u: `.git/HEAD` → dal ref dosyası, yoksa
|
|
235
|
+
`packed-refs`; ayrık HEAD'de sha'nın kendisi. `.git` bir dosyaysa (submodule vb.)
|
|
236
|
+
`gitdir:` izlenir. Yalnızca geçerli 40 hane sha, küçük harfle ilk 12 hane.
|
|
237
|
+
`git` komutu çalıştırılmaz, dosyalar okunur; okunamazsa sessizce vazgeçilir.
|
|
238
|
+
`ref:` yalnızca `refs/` altını gösterebilir, `..` içeremez. **Git worktree'leri
|
|
239
|
+
(`commondir`) desteklenmez** — dal ref'i ortak dizinde durur ve bulunamaz; orada
|
|
240
|
+
`VITALWATCH_RELEASE` kullanın.
|
|
241
|
+
5. Hiçbiri yoksa etiket gönderilmez.
|
|
242
|
+
|
|
243
|
+
Kural Node ve Laravel paketleriyle aynı. Gunicorn'un çalışma dizini uygulama kökü
|
|
244
|
+
değilse (`--chdir` yoksa) 4. adım bir şey bulamaz; `vitalwatch-status` aynı dizinden
|
|
245
|
+
çalıştırılınca bunu `kaynak: yok` olarak gösterir.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Neler raporlanır
|
|
250
|
+
|
|
251
|
+
| Tür | Ne zaman |
|
|
252
|
+
|---|---|
|
|
253
|
+
| `exception` | Yakalanmamış istisna, `report()` çağrısı |
|
|
254
|
+
| `fatal` | `MemoryError`, `RecursionError`, `SystemError` — yorumlayıcının sınırına çarpmak |
|
|
255
|
+
| `http_5xx` | Yanıt kodu ≥ 500 |
|
|
256
|
+
| `slow_request` | Süre ≥ `VITALWATCH_SLOW_REQUEST_MS` |
|
|
257
|
+
|
|
258
|
+
Başarılı ve hızlı istekler **raporlanmaz**: her isteği göndermek izlenen uygulamaya da
|
|
259
|
+
hub'a da yük olurdu.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Davranış garantileri
|
|
264
|
+
|
|
265
|
+
1. **Hata yutulmaz.** Handler zinciri korunur, `raise` engellenmez.
|
|
266
|
+
2. **Süreç yönetimine karışılmaz.** `sys.exit` çağrılmaz, mevcut `excepthook` zincirlenir.
|
|
267
|
+
3. **Kendi hatasını raporlamaz.** Tüm SDK kodu `try/except` ile sarılır.
|
|
268
|
+
4. **Kullanıcı isteğini bekletmez.** Gönderim arka plan thread'inden, kısa zaman aşımıyla.
|
|
269
|
+
5. **Hub erişilemezse sessizce vazgeçilir.**
|
|
270
|
+
6. **`VITALWATCH_ENABLED=false` iken hiçbir veri gönderilmez.**
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Güncelleme ve sürümleme
|
|
275
|
+
|
|
276
|
+
Sürüm **sabitlenmez**: kurulan her zaman deponun son hâlidir. Karşılığında bir kural
|
|
277
|
+
zorunlu hâle gelir — **her yayında sürüm numarası yükseltilmelidir.**
|
|
278
|
+
|
|
279
|
+
Sebep ölçüldü: pip, doğrudan git URL'i verilen bir paketi depoyu klonlayıp metadata'sını
|
|
280
|
+
okuduktan sonra sürüm numarasına bakar. Numara kuruluyla aynıysa **kurulumu atlar** ve
|
|
281
|
+
`-U` bunu değiştirmez:
|
|
282
|
+
|
|
283
|
+
| Komut | Sürüm aynıysa | Sürüm yükselmişse |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| `pip install -r requirements.txt` | atlar | kurar |
|
|
286
|
+
| `pip install -U ...` | atlar | kurar |
|
|
287
|
+
| `pip install --force-reinstall ...` | kurar | kurar |
|
|
288
|
+
|
|
289
|
+
Yani numara yükseltilmeden yapılan bir yayın, kurulu projelere **hiç ulaşmaz** ve bu
|
|
290
|
+
sessizce olur — paketin bütün tasarımının karşı durduğu arıza biçimi.
|
|
291
|
+
|
|
292
|
+
Sürüm çıkarma sırası:
|
|
293
|
+
|
|
294
|
+
1. `pyproject.toml` içindeki `version` **ve** `src/vitalwatch/reporter.py` içindeki
|
|
295
|
+
`SDK_VERSION` birlikte yükseltilir. İkisi ayrışırsa panelde yanlış SDK sürümü görünür.
|
|
296
|
+
2. `CHANGELOG.md`'ye giriş.
|
|
297
|
+
3. `python -m unittest discover -s tests`
|
|
298
|
+
4. Commit, `git tag vX.Y.Z`, `git push origin vX.Y.Z`.
|
|
299
|
+
5. Kurulu projelerde `pip install -r requirements.txt`, ardından `vitalwatch-status` ile
|
|
300
|
+
doğrulama. Panelde SDK sürümünün yenilendiği görülmelidir.
|
|
301
|
+
|
|
302
|
+
Acil bir düzeltme sürüm numarası yükseltmeden dağıtılacaksa tek yol
|
|
303
|
+
`--force-reinstall`; ama o durumda panel eski sürüm numarasını göstermeye devam eder ve
|
|
304
|
+
hangi sunucunun güncellendiği izlenemez.
|
|
305
|
+
|
|
306
|
+
## Test
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# Çerçeve testleri için — yoksa 53 test sessizce atlanır
|
|
310
|
+
pip install "Flask==3.0.0" Django fastapi starlette httpx
|
|
311
|
+
python -m unittest discover -s tests
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Çıktıda `skipped=` görünüyorsa bir çerçeve kurulu değildir ve o entegrasyon
|
|
315
|
+
**sınanmamıştır** (Flask 17, Django 12, FastAPI/Starlette 24 test).
|
|
316
|
+
0.1.0'daki çift kayıt ve kaybolan hata tam bu yüzden fark edilmedi.
|
|
317
|
+
|
|
318
|
+
Testler hub'ın imza doğrulamasını (`VerifyProjectSignature`) ve gövde sınırlarını
|
|
319
|
+
birebir uygulayan sahte bir hub'a karşı koşar: imzanın gerçekten kabul edilip
|
|
320
|
+
edilmediği burada görülür, "204 aldım" demek yeterli değildir.
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# vitalwatch (Python)
|
|
2
|
+
|
|
3
|
+
[VitalWatch Hub](https://github.com/CestnyTR/vitalwatch-hub) için Python raporlayıcı: sunucu
|
|
4
|
+
hataları, yavaş istekler, canlılık.
|
|
5
|
+
|
|
6
|
+
Bağımlılık yok. Build adımı yok. Python 3.9+.
|
|
7
|
+
|
|
8
|
+
Kardeş paketler: `cestnytr/vitalwatch-laravel` (Laravel), `vitalwatch-node` (Node),
|
|
9
|
+
`t.js` (tarayıcı, hub reposunda `resources/sdk/t.js`).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Kapsam — ve neden bu kadar dar
|
|
14
|
+
|
|
15
|
+
Bu paket **yalnızca sunucu tarafını** kapsar. Tarayıcı hataları hub'dan servis edilen
|
|
16
|
+
`t.js` ile toplanır; o dosya bilinçli olarak pakete taşınmadı — hosted olması bir
|
|
17
|
+
düzeltmenin dakikalar içinde tüm sitelere yayılmasını sağlıyor, paket olsaydı her
|
|
18
|
+
düzeltme için bütün projelerin yeniden dağıtılması gerekirdi.
|
|
19
|
+
|
|
20
|
+
Toplanmayanlar — yapılandırmayla dahi açılamaz:
|
|
21
|
+
|
|
22
|
+
IP adresi · User-Agent · istek gövdesi · query string **değerleri** (yalnızca yol) ·
|
|
23
|
+
oturum verisi · çerez · ham SQL literalleri
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Kurulum
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install git+https://github.com/CestnyTR/vitalwatch-python.git
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`.env` dosyasına — kardeş paketlerle aynı değişken isimleri:
|
|
34
|
+
|
|
35
|
+
```env
|
|
36
|
+
VITALWATCH_ENABLED=true
|
|
37
|
+
VITALWATCH_URL=https://vitalwatch.example.com
|
|
38
|
+
VITALWATCH_KEY=proje-anahtari
|
|
39
|
+
VITALWATCH_SECRET=<panelden alınan 64 karakterlik secret>
|
|
40
|
+
VITALWATCH_ENV=production
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Flask
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from flask import Flask
|
|
47
|
+
from vitalwatch.flask import VitalWatchFlask
|
|
48
|
+
|
|
49
|
+
app = Flask(__name__)
|
|
50
|
+
VitalWatchFlask(app)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Tek satır şunları kurar: yakalanmamış istisnalar (`teardown_request`), 5xx ve yavaş
|
|
54
|
+
istekler (`after_request`), süreç düzeyi kancalar (`sys.excepthook`,
|
|
55
|
+
`threading.excepthook`) ve 8 saatlik canlılık isteği.
|
|
56
|
+
|
|
57
|
+
- **Tek arıza, tek kayıt:** hata veren istek yalnızca stack'li `exception` açar;
|
|
58
|
+
aynı istek için ayrıca `http_5xx` gönderilmez (0.1.1+).
|
|
59
|
+
- **Kendi hata işleyiciniz varsa:** `@app.errorhandler(Exception)` ya da
|
|
60
|
+
`errorhandler(500)` tanımlıysa hata yine stack'iyle gelir. İşleyici 4xx dönerse
|
|
61
|
+
gönderilmez. Eskiden bu durumda hata kayboluyor, yalnızca stack'siz `http_5xx`
|
|
62
|
+
geliyordu.
|
|
63
|
+
- **`abort(4xx)` gönderilmez:** bilinçli yanıt, arıza değil.
|
|
64
|
+
- **Kurulum sırası serbest:** `VitalWatchFlask(app)` önce, `vitalwatch.init(...)` sonra
|
|
65
|
+
çağrılabilir; istek kancaları da süreç kancaları da (`sys.excepthook`,
|
|
66
|
+
`threading.excepthook`) güncel raporlayıcıyı çağrı anında çözer. Kurulumda
|
|
67
|
+
yapılandırma yoksa canlılık `init(...)` çağrılınca başlar.
|
|
68
|
+
- **İki kez kurmak zararsız:** aynı uygulamada ikinci `VitalWatchFlask(app)` hiçbir
|
|
69
|
+
şey eklemez; süreç kancaları süreç başına bir kez kurulur.
|
|
70
|
+
- **Uygulamayı düşürmez:** kurulum (bozuk ya da UTF-8 olmayan `.env` dahil)
|
|
71
|
+
hiçbir koşulda hata fırlatmaz.
|
|
72
|
+
- **Süreç kancalarını kapatmak:** `VitalWatchFlask(app, hook_process_errors=False)`
|
|
73
|
+
yalnızca istek kancalarını kurar.
|
|
74
|
+
|
|
75
|
+
### Django
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# settings.py
|
|
79
|
+
MIDDLEWARE = [
|
|
80
|
+
"vitalwatch.django.VitalWatchMiddleware", # listenin başına yakın
|
|
81
|
+
# ...
|
|
82
|
+
]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Ara katman yavaş ve 5xx istekleri ölçer, yakalanmamış istisnayı stack'iyle gönderir.
|
|
86
|
+
Hata iki yoldan görülür: Django'nun istisnayı 500'e çevirirken yolladığı
|
|
87
|
+
`got_request_exception` sinyali (görünümün yanında alttaki ara katmanlardan çıkan
|
|
88
|
+
hatalar da) ve `process_exception`. Kurallar Flask'la aynı:
|
|
89
|
+
|
|
90
|
+
- **Tek arıza, tek kayıt;** hata veren istek için ayrıca `http_5xx` açılmaz.
|
|
91
|
+
- **4xx gönderilmez:** `Http404`, `PermissionDenied`, `BadRequest`,
|
|
92
|
+
`SuspiciousOperation`.
|
|
93
|
+
- **Rota deseni gider:** `/urun/<int:urun_id>/`, gerçek id değil. `re_path`
|
|
94
|
+
desenlerinde baştaki `^` ve sondaki `$` atılır.
|
|
95
|
+
- **Hata yutulmaz:** `process_exception` `None` döner; Django'nun 500 sayfası ve
|
|
96
|
+
`handler500` olduğu gibi çalışır.
|
|
97
|
+
- **Süreç kancaları** ilk kurulumda bir kez açılır; kapatmak için
|
|
98
|
+
`VITALWATCH_HOOK_PROCESS = False`.
|
|
99
|
+
|
|
100
|
+
### FastAPI / Starlette (ASGI)
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from fastapi import FastAPI
|
|
104
|
+
from vitalwatch.asgi import VitalWatchASGIMiddleware
|
|
105
|
+
|
|
106
|
+
app = FastAPI()
|
|
107
|
+
app.add_middleware(VitalWatchASGIMiddleware)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Starlette'te aynı satır (`Starlette(middleware=[Middleware(VitalWatchASGIMiddleware)])` de
|
|
111
|
+
olur). Başka bir ASGI uygulaması doğrudan sarılabilir: `app = VitalWatchASGIMiddleware(app)`.
|
|
112
|
+
Saf ASGI ara katmanıdır; Starlette/FastAPI import anında yüklenmez.
|
|
113
|
+
|
|
114
|
+
- **Tek arıza, tek kayıt;** 4xx `HTTPException` ve doğrulama hataları (422)
|
|
115
|
+
gönderilmez. Bilinçli `HTTPException(5xx)` stack'siz `http_5xx` olarak düşer.
|
|
116
|
+
- **Rota deseni gider:** `/urun/{urun_id}`; `include_router` öneki ve `Mount`
|
|
117
|
+
yolu desene eklenir.
|
|
118
|
+
- **Kendi hata işleyiciniz varsa:** `@app.exception_handler(Exception)` hatayı
|
|
119
|
+
yine bizim katmanımızdan geçirir. Belirli bir sınıfa bağlı işleyici
|
|
120
|
+
(`@app.exception_handler(ValueError)`) 5xx dönerse hata yine stack'iyle gelir,
|
|
121
|
+
4xx dönerse gönderilmez. Ara katman sırası fark etmez (`add_middleware` ya da
|
|
122
|
+
`middleware=[...]` içinde herhangi bir yer). Elle sarılan uygulamada
|
|
123
|
+
(`VitalWatchASGIMiddleware(app)`) Starlette yığınını ilk istekte kurduğu için bu
|
|
124
|
+
ilk istekten sonra devreye girer; o ilk istekte 5xx stack'siz `http_5xx` olur.
|
|
125
|
+
- **Süre yanıtın son baytında durur:** `BackgroundTasks` ve yanıt sonrası işler
|
|
126
|
+
yavaş istek sayılmaz. Uzun akış (SSE, büyük indirme) son parçaya kadar sürer
|
|
127
|
+
ve yavaş sayılabilir.
|
|
128
|
+
- **İç içe katman tek kayıt açar:** `Mount` edilen alt uygulamada da
|
|
129
|
+
`VitalWatchASGIMiddleware` varsa istek yalnızca dıştakinde ölçülür.
|
|
130
|
+
- **Hata yutulmaz:** raporlanır ve yeniden fırlatılır; lifespan ve websocket
|
|
131
|
+
olduğu gibi geçer.
|
|
132
|
+
- **Süreç kancalarını kapatmak:**
|
|
133
|
+
`app.add_middleware(VitalWatchASGIMiddleware, hook_process_errors=False)`.
|
|
134
|
+
|
|
135
|
+
### Çerçevesiz
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import vitalwatch
|
|
139
|
+
|
|
140
|
+
vitalwatch.hook_process() # kancalar + canlılık
|
|
141
|
+
vitalwatch.report(error) # elle bildirim
|
|
142
|
+
|
|
143
|
+
vitalwatch.init(ignore=(KeyboardInterrupt, "BenimBeklenenHatam")) # sınıf ya da ad
|
|
144
|
+
vitalwatch.start_heartbeat() # yalnızca canlılık (hook_process zaten başlatır)
|
|
145
|
+
vitalwatch.stop_heartbeat()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`init()` ortam değişkenlerini okur; verilen argümanlar onları ezer. Çağrılmazsa ilk
|
|
149
|
+
kullanımda kendiliğinden kurulur.
|
|
150
|
+
|
|
151
|
+
### Kurulumu doğrulayın
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
vitalwatch-status
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Bu adım atlanmamalı. Paketin en pahalı arıza biçimi **sessiz çalışmamadır**: secret
|
|
158
|
+
eksik kopyalanmışsa hiçbir şey patlamaz, hiçbir log düşmez — hub geçersiz imzaya da
|
|
159
|
+
`204` döner. Kurulum aylarca çalışmıyor olabilir ve o sessizlik "sorun yok" sanılır.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
vitalwatch-status --test # gerçek bir sınama olayı — panelde hata olarak görünür
|
|
163
|
+
vitalwatch-status --vitalwatch # yalnızca canlılık isteği — panele hata düşürmez
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`--test` tek bir kurulumu doğrularken doğru seçim. **Onlarca kurulumu gezen bir
|
|
167
|
+
güncelleme döngüsünde `--vitalwatch` kullanılır** — `--test` orada panele onlarca sahte hata
|
|
168
|
+
bırakır, yani izleme aracı kendi gürültüsünü üretir.
|
|
169
|
+
|
|
170
|
+
Verinin gerçekten ulaştığı yalnızca **hub panelinden** doğrulanır: proje satırındaki
|
|
171
|
+
bağlantı durumu `Bağlı` görünmelidir. Komut bunu kendi başına söyleyemez, çünkü hub
|
|
172
|
+
geçerli ile geçersiz imzayı dışarıya aynı yanıtla karşılar.
|
|
173
|
+
|
|
174
|
+
Komut ayrıca şunları gösterir:
|
|
175
|
+
|
|
176
|
+
- **`Sürüm etiketi`** — olaylara eklenecek `release` ve nereden bulunduğu:
|
|
177
|
+
`abc123def456 (kaynak: .git)`; kaynak `VITALWATCH_RELEASE`, bir CI/PaaS değişkeninin
|
|
178
|
+
adı, `.git` ya da `yok`. Ayrıntı: [Sürüm etiketi](#sürüm-etiketi-release).
|
|
179
|
+
- **`Güncel sürüm`** — GitHub etiketlerindeki en yeni kararlı sürüm (paket PyPI'da
|
|
180
|
+
değil). Kurulu sürümden yeniyse bir `Güncelleme var: pip install -U
|
|
181
|
+
--force-reinstall "vitalwatch @ git+…@vX.Y.Z"` satırı yazılır; bu bir uyarıdır,
|
|
182
|
+
çıkış kodunu değiştirmez. Ağ yoksa ya da GitHub hız sınırına takıldıysa
|
|
183
|
+
`denetlenemedi` yazar (2 sn zaman aşımı). Ağa hiç çıkılmaması için
|
|
184
|
+
`VITALWATCH_STATUS_OFFLINE=1` (`1`, `true`, `yes`, `on`, `evet`; büyük/küçük harf fark
|
|
185
|
+
etmez) — o durumda `Güncel sürüm` satırı hiç yazılmaz.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Yapılandırma
|
|
190
|
+
|
|
191
|
+
| Değişken | Varsayılan | Açıklama |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| `VITALWATCH_ENABLED` | `true` | `false` iken hiçbir veri gönderilmez |
|
|
194
|
+
| `VITALWATCH_URL` | — | Hub adresi (https) |
|
|
195
|
+
| `VITALWATCH_KEY` | — | Proje anahtarı |
|
|
196
|
+
| `VITALWATCH_SECRET` | — | 64 karakterlik imza secret'i |
|
|
197
|
+
| `VITALWATCH_ENV` | `APP_ENV` | `production` · `staging` · `local`. Takma adlar çevrilir: `prod`/`live` → production, `stage`/`stg`/`preprod`/`uat` → staging, `dev`/`development`/`test`/`testing` → local. Tanınmayan değeri hub reddeder; teşhis komutu hata verir |
|
|
198
|
+
| `VITALWATCH_RELEASE` | kendiliğinden | Sürüm etiketi. Boşsa CI/PaaS commit değişkenlerinden ya da `.git`'ten bulunur — aşağıya bakın |
|
|
199
|
+
| `VITALWATCH_STATUS_OFFLINE` | — | `1`/`true`/`yes`/`on`/`evet` iken `vitalwatch-status` güncelleme denetimi için ağa çıkmaz |
|
|
200
|
+
| `VITALWATCH_TIMEOUT` | `2.0` | Gönderim zaman aşımı, **saniye**. 100 ve üstü milisaniye sayılır — Node aynı adla ms bekliyor, `2000` yazan 2000 saniye beklemesin. Geçersiz, sıfır/eksi, NaN ya da sonsuz → 2 sn; sonuç 0.1–10 sn aralığına sıkıştırılır |
|
|
201
|
+
| `VITALWATCH_SLOW_REQUEST_MS` | `1000` | Yavaş istek eşiği |
|
|
202
|
+
|
|
203
|
+
Ortam değişkenleri `os.environ` ve `.env` / `.env.local` / `.env.<APP_ENV>`
|
|
204
|
+
dosyalarından okunur; süreç ortamı her zaman kazanır. Yalnızca `VITALWATCH_` önekli
|
|
205
|
+
anahtarlar okunur.
|
|
206
|
+
|
|
207
|
+
### Sürüm etiketi (`release`)
|
|
208
|
+
|
|
209
|
+
`VITALWATCH_RELEASE` neredeyse hiçbir kurulumda doldurulmuyordu; hub bu yüzden bir hatanın
|
|
210
|
+
**hangi deploy ile başladığını** söyleyemiyordu. Deploy'larımız çoğunlukla sunucuda
|
|
211
|
+
`git pull` + gunicorn yeniden başlatma: yeni süreç açılışta commit'i kendisi okur, deploy
|
|
212
|
+
sonrası ilk hatada panel yeni sürümü görür. Etiket kurulumda bir kez çözülür (olay başına
|
|
213
|
+
değil); ilk dolu kaynak kazanır:
|
|
214
|
+
|
|
215
|
+
1. `init(release=...)` ile açıkça verilen değer.
|
|
216
|
+
2. `VITALWATCH_RELEASE` — kırpılır, en çok 64 karakter, olduğu gibi.
|
|
217
|
+
3. Sırasıyla `GIT_COMMIT`, `GIT_SHA`, `COMMIT_SHA`, `SOURCE_VERSION`,
|
|
218
|
+
`VERCEL_GIT_COMMIT_SHA`, `RENDER_GIT_COMMIT`, `HEROKU_SLUG_COMMIT`, `CI_COMMIT_SHA`.
|
|
219
|
+
7–40 hane hex ise küçük harfle ilk 12 hane; değilse kırpılmış, en çok 64 karakter.
|
|
220
|
+
4. Çalışma dizinindeki git checkout'u: `.git/HEAD` → dal ref dosyası, yoksa
|
|
221
|
+
`packed-refs`; ayrık HEAD'de sha'nın kendisi. `.git` bir dosyaysa (submodule vb.)
|
|
222
|
+
`gitdir:` izlenir. Yalnızca geçerli 40 hane sha, küçük harfle ilk 12 hane.
|
|
223
|
+
`git` komutu çalıştırılmaz, dosyalar okunur; okunamazsa sessizce vazgeçilir.
|
|
224
|
+
`ref:` yalnızca `refs/` altını gösterebilir, `..` içeremez. **Git worktree'leri
|
|
225
|
+
(`commondir`) desteklenmez** — dal ref'i ortak dizinde durur ve bulunamaz; orada
|
|
226
|
+
`VITALWATCH_RELEASE` kullanın.
|
|
227
|
+
5. Hiçbiri yoksa etiket gönderilmez.
|
|
228
|
+
|
|
229
|
+
Kural Node ve Laravel paketleriyle aynı. Gunicorn'un çalışma dizini uygulama kökü
|
|
230
|
+
değilse (`--chdir` yoksa) 4. adım bir şey bulamaz; `vitalwatch-status` aynı dizinden
|
|
231
|
+
çalıştırılınca bunu `kaynak: yok` olarak gösterir.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Neler raporlanır
|
|
236
|
+
|
|
237
|
+
| Tür | Ne zaman |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `exception` | Yakalanmamış istisna, `report()` çağrısı |
|
|
240
|
+
| `fatal` | `MemoryError`, `RecursionError`, `SystemError` — yorumlayıcının sınırına çarpmak |
|
|
241
|
+
| `http_5xx` | Yanıt kodu ≥ 500 |
|
|
242
|
+
| `slow_request` | Süre ≥ `VITALWATCH_SLOW_REQUEST_MS` |
|
|
243
|
+
|
|
244
|
+
Başarılı ve hızlı istekler **raporlanmaz**: her isteği göndermek izlenen uygulamaya da
|
|
245
|
+
hub'a da yük olurdu.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Davranış garantileri
|
|
250
|
+
|
|
251
|
+
1. **Hata yutulmaz.** Handler zinciri korunur, `raise` engellenmez.
|
|
252
|
+
2. **Süreç yönetimine karışılmaz.** `sys.exit` çağrılmaz, mevcut `excepthook` zincirlenir.
|
|
253
|
+
3. **Kendi hatasını raporlamaz.** Tüm SDK kodu `try/except` ile sarılır.
|
|
254
|
+
4. **Kullanıcı isteğini bekletmez.** Gönderim arka plan thread'inden, kısa zaman aşımıyla.
|
|
255
|
+
5. **Hub erişilemezse sessizce vazgeçilir.**
|
|
256
|
+
6. **`VITALWATCH_ENABLED=false` iken hiçbir veri gönderilmez.**
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Güncelleme ve sürümleme
|
|
261
|
+
|
|
262
|
+
Sürüm **sabitlenmez**: kurulan her zaman deponun son hâlidir. Karşılığında bir kural
|
|
263
|
+
zorunlu hâle gelir — **her yayında sürüm numarası yükseltilmelidir.**
|
|
264
|
+
|
|
265
|
+
Sebep ölçüldü: pip, doğrudan git URL'i verilen bir paketi depoyu klonlayıp metadata'sını
|
|
266
|
+
okuduktan sonra sürüm numarasına bakar. Numara kuruluyla aynıysa **kurulumu atlar** ve
|
|
267
|
+
`-U` bunu değiştirmez:
|
|
268
|
+
|
|
269
|
+
| Komut | Sürüm aynıysa | Sürüm yükselmişse |
|
|
270
|
+
|---|---|---|
|
|
271
|
+
| `pip install -r requirements.txt` | atlar | kurar |
|
|
272
|
+
| `pip install -U ...` | atlar | kurar |
|
|
273
|
+
| `pip install --force-reinstall ...` | kurar | kurar |
|
|
274
|
+
|
|
275
|
+
Yani numara yükseltilmeden yapılan bir yayın, kurulu projelere **hiç ulaşmaz** ve bu
|
|
276
|
+
sessizce olur — paketin bütün tasarımının karşı durduğu arıza biçimi.
|
|
277
|
+
|
|
278
|
+
Sürüm çıkarma sırası:
|
|
279
|
+
|
|
280
|
+
1. `pyproject.toml` içindeki `version` **ve** `src/vitalwatch/reporter.py` içindeki
|
|
281
|
+
`SDK_VERSION` birlikte yükseltilir. İkisi ayrışırsa panelde yanlış SDK sürümü görünür.
|
|
282
|
+
2. `CHANGELOG.md`'ye giriş.
|
|
283
|
+
3. `python -m unittest discover -s tests`
|
|
284
|
+
4. Commit, `git tag vX.Y.Z`, `git push origin vX.Y.Z`.
|
|
285
|
+
5. Kurulu projelerde `pip install -r requirements.txt`, ardından `vitalwatch-status` ile
|
|
286
|
+
doğrulama. Panelde SDK sürümünün yenilendiği görülmelidir.
|
|
287
|
+
|
|
288
|
+
Acil bir düzeltme sürüm numarası yükseltmeden dağıtılacaksa tek yol
|
|
289
|
+
`--force-reinstall`; ama o durumda panel eski sürüm numarasını göstermeye devam eder ve
|
|
290
|
+
hangi sunucunun güncellendiği izlenemez.
|
|
291
|
+
|
|
292
|
+
## Test
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Çerçeve testleri için — yoksa 53 test sessizce atlanır
|
|
296
|
+
pip install "Flask==3.0.0" Django fastapi starlette httpx
|
|
297
|
+
python -m unittest discover -s tests
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Çıktıda `skipped=` görünüyorsa bir çerçeve kurulu değildir ve o entegrasyon
|
|
301
|
+
**sınanmamıştır** (Flask 17, Django 12, FastAPI/Starlette 24 test).
|
|
302
|
+
0.1.0'daki çift kayıt ve kaybolan hata tam bu yüzden fark edilmedi.
|
|
303
|
+
|
|
304
|
+
Testler hub'ın imza doğrulamasını (`VerifyProjectSignature`) ve gövde sınırlarını
|
|
305
|
+
birebir uygulayan sahte bir hub'a karşı koşar: imzanın gerçekten kabul edilip
|
|
306
|
+
edilmediği burada görülür, "204 aldım" demek yeterli değildir.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "vitalwatch"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "VitalWatch Hub için Python raporlayıcı — sunucu hataları, yavaş istekler, canlılık"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "CestnyTR" }]
|
|
12
|
+
requires-python = ">=3.9"
|
|
13
|
+
keywords = ["monitoring", "error-tracking", "flask", "wsgi", "vitalwatch"]
|
|
14
|
+
|
|
15
|
+
# Bağımlılık YOK ve olmayacak: paket izlenen projelere kurulur, her bağımlılık
|
|
16
|
+
# orada bir sürüm çakışması riskidir. Flask entegrasyonu flask'ı yalnızca
|
|
17
|
+
# kullanıldığı anda ve kendi içinde import eder.
|
|
18
|
+
dependencies = []
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/CestnyTR/vitalwatch-python"
|
|
22
|
+
Hub = "https://github.com/CestnyTR/vitalwatch-hub"
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
vitalwatch-status = "vitalwatch.cli:main"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools.packages.find]
|
|
28
|
+
where = ["src"]
|