vitalwatch (Python)
VitalWatch Hub için Python raporlayıcı: sunucu
hataları, yavaş istekler, canlılık. Ayrıca sunucunun kendisini izleyen
vitalwatch-agent: web sunucusu, PHP-FPM, veritabanı,
systemd, Docker, OOM ve disk.
Bağımlılık yok. Build adımı yok. Python 3.9+.
Kardeş paketler: cestnytr/vitalwatch-laravel (Laravel), vitalwatch-node (Node),
t.js (tarayıcı, hub reposunda resources/sdk/t.js).
Kapsam — ve neden bu kadar dar
Bu paket yalnızca sunucu tarafını kapsar. Tarayıcı hataları hub'dan servis edilen
t.js ile toplanır; o dosya bilinçli olarak pakete taşınmadı — hosted olması bir
düzeltmenin dakikalar içinde tüm sitelere yayılmasını sağlıyor, paket olsaydı her
düzeltme için bütün projelerin yeniden dağıtılması gerekirdi.
Toplanmayanlar — yapılandırmayla dahi açılamaz:
IP adresi · User-Agent · istek gövdesi · query string değerleri (yalnızca yol) · oturum verisi · çerez · ham SQL literalleri
Kurulum
pip install vitalwatch
.env dosyasına — kardeş paketlerle aynı değişken isimleri:
VITALWATCH_ENABLED=true
VITALWATCH_URL=https://vitalwatch.example.com
VITALWATCH_KEY=proje-anahtari
VITALWATCH_SECRET=<panelden alınan 64 karakterlik secret>
VITALWATCH_ENV=production
Flask
from flask import Flask
from vitalwatch.flask import VitalWatchFlask
app = Flask(__name__)
VitalWatchFlask(app)
Tek satır şunları kurar: yakalanmamış istisnalar (teardown_request), 5xx ve yavaş
istekler (after_request), süreç düzeyi kancalar (sys.excepthook,
threading.excepthook) ve 8 saatlik canlılık isteği.
- Tek arıza, tek kayıt: hata veren istek yalnızca stack'li
exceptionaçar; aynı istek için ayrıcahttp_5xxgönderilmez (0.1.1+). - Kendi hata işleyiciniz varsa:
@app.errorhandler(Exception)ya daerrorhandler(500)tanımlıysa hata yine stack'iyle gelir. İşleyici 4xx dönerse gönderilmez. Eskiden bu durumda hata kayboluyor, yalnızca stack'sizhttp_5xxgeliyordu. abort(4xx)gönderilmez: bilinçli yanıt, arıza değil.- Kurulum sırası serbest:
VitalWatchFlask(app)önce,vitalwatch.init(...)sonra çağrılabilir; istek kancaları da süreç kancaları da (sys.excepthook,threading.excepthook) güncel raporlayıcıyı çağrı anında çözer. Kurulumda yapılandırma yoksa canlılıkinit(...)çağrılınca başlar. - İki kez kurmak zararsız: aynı uygulamada ikinci
VitalWatchFlask(app)hiçbir şey eklemez; süreç kancaları süreç başına bir kez kurulur. - Uygulamayı düşürmez: kurulum (bozuk ya da UTF-8 olmayan
.envdahil) hiçbir koşulda hata fırlatmaz. - Süreç kancalarını kapatmak:
VitalWatchFlask(app, hook_process_errors=False)yalnızca istek kancalarını kurar.
Django
# settings.py
MIDDLEWARE = [
"vitalwatch.django.VitalWatchMiddleware", # listenin başına yakın
# ...
]
Ara katman yavaş ve 5xx istekleri ölçer, yakalanmamış istisnayı stack'iyle gönderir.
Hata iki yoldan görülür: Django'nun istisnayı 500'e çevirirken yolladığı
got_request_exception sinyali (görünümün yanında alttaki ara katmanlardan çıkan
hatalar da) ve process_exception. Kurallar Flask'la aynı:
- Tek arıza, tek kayıt; hata veren istek için ayrıca
http_5xxaçılmaz. - 4xx gönderilmez:
Http404,PermissionDenied,BadRequest,SuspiciousOperation. - Rota deseni gider:
/urun/<int:urun_id>/, gerçek id değil.re_pathdesenlerinde baştaki^ve sondaki$atılır. - Hata yutulmaz:
process_exceptionNonedöner; Django'nun 500 sayfası vehandler500olduğu gibi çalışır. - Süreç kancaları ilk kurulumda bir kez açılır; kapatmak için
VITALWATCH_HOOK_PROCESS = False.
FastAPI / Starlette (ASGI)
from fastapi import FastAPI
from vitalwatch.asgi import VitalWatchASGIMiddleware
app = FastAPI()
app.add_middleware(VitalWatchASGIMiddleware)
Starlette'te aynı satır (Starlette(middleware=[Middleware(VitalWatchASGIMiddleware)]) de
olur). Başka bir ASGI uygulaması doğrudan sarılabilir: app = VitalWatchASGIMiddleware(app).
Saf ASGI ara katmanıdır; Starlette/FastAPI import anında yüklenmez.
- Tek arıza, tek kayıt; 4xx
HTTPExceptionve doğrulama hataları (422) gönderilmez. BilinçliHTTPException(5xx)stack'sizhttp_5xxolarak düşer. - Rota deseni gider:
/urun/{urun_id};include_routeröneki veMountyolu desene eklenir. - Kendi hata işleyiciniz varsa:
@app.exception_handler(Exception)hatayı yine bizim katmanımızdan geçirir. Belirli bir sınıfa bağlı işleyici (@app.exception_handler(ValueError)) 5xx dönerse hata yine stack'iyle gelir, 4xx dönerse gönderilmez. Ara katman sırası fark etmez (add_middlewareya damiddleware=[...]içinde herhangi bir yer). Elle sarılan uygulamada (VitalWatchASGIMiddleware(app)) Starlette yığınını ilk istekte kurduğu için bu ilk istekten sonra devreye girer; o ilk istekte 5xx stack'sizhttp_5xxolur. - Süre yanıtın son baytında durur:
BackgroundTasksve yanıt sonrası işler yavaş istek sayılmaz. Uzun akış (SSE, büyük indirme) son parçaya kadar sürer ve yavaş sayılabilir. - İç içe katman tek kayıt açar:
Mountedilen alt uygulamada daVitalWatchASGIMiddlewarevarsa istek yalnızca dıştakinde ölçülür. - Hata yutulmaz: raporlanır ve yeniden fırlatılır; lifespan ve websocket olduğu gibi geçer.
- Süreç kancalarını kapatmak:
app.add_middleware(VitalWatchASGIMiddleware, hook_process_errors=False).
Çerçevesiz
import vitalwatch
vitalwatch.hook_process() # kancalar + canlılık
vitalwatch.report(error) # elle bildirim
vitalwatch.init(ignore=(KeyboardInterrupt, "BenimBeklenenHatam")) # sınıf ya da ad
vitalwatch.start_heartbeat() # yalnızca canlılık (hook_process zaten başlatır)
vitalwatch.stop_heartbeat()
init() ortam değişkenlerini okur; verilen argümanlar onları ezer. Çağrılmazsa ilk
kullanımda kendiliğinden kurulur.
Kurulumu doğrulayın
vitalwatch-status
Bu adım atlanmamalı. Paketin en pahalı arıza biçimi sessiz çalışmamadır: secret
eksik kopyalanmışsa hiçbir şey patlamaz, hiçbir log düşmez — hub geçersiz imzaya da
204 döner. Kurulum aylarca çalışmıyor olabilir ve o sessizlik "sorun yok" sanılır.
vitalwatch-status --test # gerçek bir sınama olayı — panelde hata olarak görünür
vitalwatch-status --vitalwatch # yalnızca canlılık isteği — panele hata düşürmez
--test tek bir kurulumu doğrularken doğru seçim. Onlarca kurulumu gezen bir
güncelleme döngüsünde --vitalwatch kullanılır — --test orada panele onlarca sahte hata
bırakır, yani izleme aracı kendi gürültüsünü üretir.
Verinin gerçekten ulaştığı yalnızca hub panelinden doğrulanır: proje satırındaki
bağlantı durumu Bağlı görünmelidir. Komut bunu kendi başına söyleyemez, çünkü hub
geçerli ile geçersiz imzayı dışarıya aynı yanıtla karşılar.
Komut ayrıca şunları gösterir:
Sürüm etiketi— olaylara eklenecekreleaseve nereden bulunduğu:abc123def456 (kaynak: .git); kaynakVITALWATCH_RELEASE, bir CI/PaaS değişkeninin adı,.gitya dayok. Ayrıntı: Sürüm etiketi.Güncel sürüm— PyPI'daki en yeni kararlı sürüm (info.version). Kurulu sürümden yeniyse birGüncelleme var: pip install -U vitalwatchsatırı yazılır; bu bir uyarıdır, çıkış kodunu değiştirmez. Ağ yoksa ya da PyPI yanıt vermezsedenetlenemediyazar (2 sn zaman aşımı). Ağa hiç çıkılmaması içinVITALWATCH_STATUS_OFFLINE=1(1,true,yes,on,evet; büyük/küçük harf fark etmez) — o durumdaGüncel sürümsatırı hiç yazılmaz.
Yapılandırma
| Değişken | Varsayılan | Açıklama |
|---|---|---|
VITALWATCH_ENABLED |
true |
false iken hiçbir veri gönderilmez |
VITALWATCH_URL |
— | Hub adresi (https) |
VITALWATCH_KEY |
— | Proje anahtarı |
VITALWATCH_SECRET |
— | 64 karakterlik imza secret'i |
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 |
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 |
VITALWATCH_STATUS_OFFLINE |
— | 1/true/yes/on/evet iken vitalwatch-status güncelleme denetimi için ağa çıkmaz |
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 |
VITALWATCH_SLOW_REQUEST_MS |
1000 |
Yavaş istek eşiği |
Ortam değişkenleri os.environ ve .env / .env.local / .env.<APP_ENV>
dosyalarından okunur; süreç ortamı her zaman kazanır. Yalnızca VITALWATCH_ önekli
anahtarlar okunur.
Sürüm etiketi (release)
VITALWATCH_RELEASE neredeyse hiçbir kurulumda doldurulmuyordu; hub bu yüzden bir hatanın
hangi deploy ile başladığını söyleyemiyordu. Deploy'larımız çoğunlukla sunucuda
git pull + gunicorn yeniden başlatma: yeni süreç açılışta commit'i kendisi okur, deploy
sonrası ilk hatada panel yeni sürümü görür. Etiket kurulumda bir kez çözülür (olay başına
değil); ilk dolu kaynak kazanır:
init(release=...)ile açıkça verilen değer.VITALWATCH_RELEASE— kırpılır, en çok 64 karakter, olduğu gibi.- Sırasıyla
GIT_COMMIT,GIT_SHA,COMMIT_SHA,SOURCE_VERSION,VERCEL_GIT_COMMIT_SHA,RENDER_GIT_COMMIT,HEROKU_SLUG_COMMIT,CI_COMMIT_SHA. 7–40 hane hex ise küçük harfle ilk 12 hane; değilse kırpılmış, en çok 64 karakter. - Çalışma dizinindeki git checkout'u:
.git/HEAD→ dal ref dosyası, yoksapacked-refs; ayrık HEAD'de sha'nın kendisi..gitbir dosyaysa (submodule vb.)gitdir:izlenir. Yalnızca geçerli 40 hane sha, küçük harfle ilk 12 hane.gitkomutu çalıştırılmaz, dosyalar okunur; okunamazsa sessizce vazgeçilir.ref:yalnızcarefs/altını gösterebilir,..içeremez. Git worktree'leri (commondir) desteklenmez — dal ref'i ortak dizinde durur ve bulunamaz; oradaVITALWATCH_RELEASEkullanın. - Hiçbiri yoksa etiket gönderilmez.
Kural Node ve Laravel paketleriyle aynı. Gunicorn'un çalışma dizini uygulama kökü
değilse (--chdir yoksa) 4. adım bir şey bulamaz; vitalwatch-status aynı dizinden
çalıştırılınca bunu kaynak: yok olarak gösterir.
Neler raporlanır
| Tür | Ne zaman |
|---|---|
exception |
Yakalanmamış istisna, report() çağrısı |
fatal |
MemoryError, RecursionError, SystemError — yorumlayıcının sınırına çarpmak |
http_5xx |
Yanıt kodu ≥ 500 |
slow_request |
Süre ≥ VITALWATCH_SLOW_REQUEST_MS |
Başarılı ve hızlı istekler raporlanmaz: her isteği göndermek izlenen uygulamaya da hub'a da yük olurdu.
Sunucu ajanı (vitalwatch-agent)
SDK uygulamanın içinden bakar. Uygulamanın dışında kalan arızalar — nginx'in
502/504'ü, PHP-FPM'in pm.max_children sınırı, PostgreSQL FATAL, düşen bir systemd
servisi, sürekli yeniden başlayan bir Docker konteyneri, OOM killer, dolan disk — ancak
sunucudan görülür. vitalwatch-agent sunucuda servis olarak çalışır, bunları izler ve
hata olayı olarak hub'ın sunucu ucuna gönderir. Dil bağımsızdır: .NET, Go ya da statik
site — sunucuda ne çalışıyorsa onun web sunucusu, veritabanı ve servis yöneticisi izlenir.
Aynı paketle gelir; bağımlılık yok. Önerilen: her sunucu için hub'da ayrı bir proje
(ör. vps-ornek), beyanı agent.
Kurulum
sudo python3 -m venv /opt/vitalwatch
sudo /opt/vitalwatch/bin/pip install vitalwatch
sudo ln -s /opt/vitalwatch/bin/vitalwatch-agent /usr/local/bin/vitalwatch-agent
sudo install -d -m 700 /etc/vitalwatch
sudo nano /etc/vitalwatch/agent.ini # aşağıdaki örnek
sudo chmod 600 /etc/vitalwatch/agent.ini
sudo vitalwatch-agent check # kaynaklar ve yapılandırma
sudo vitalwatch-agent check --test # panele bir sınama olayı düşürür
sudo sh -c 'vitalwatch-agent systemd > /etc/systemd/system/vitalwatch-agent.service'
sudo systemctl daemon-reload && sudo systemctl enable --now vitalwatch-agent
Sanal ortam /opt altında olmalı: ProtectHome=yes ev dizinlerini, PrivateTmp=yes
/tmp'yi servisten gizler. systemd komutu çalışan kurulumun yorumlayıcı yolunu yazar;
yol ev dizinindeyse ya da /tmp altındaysa ilgili korumayı gevşetip yorum satırıyla
belirtir.
/etc/vitalwatch/agent.ini
[hub]
url = https://vitalwatch.example.com
key = vps-anahtari
secret = <panelden alınan 64 karakter>
env = production
[sources]
# hepsi varsayılan "auto": varsa ve okunabiliyorsa açık. "on": yoksa check hata verir.
nginx = auto
apache = auto
plesk = auto
php_fpm = auto
postgresql = auto
mysql = auto
mongodb = auto
redis = auto
journal = auto
systemd = auto
docker = auto
disk = auto
journal_errors = off ; tüm err seviyesi journald satırları (gürültülü)
docker_logs = ; logu izlenecek konteyner adları, virgülle
[disk]
threshold = 90
[ignore]
hosts = ; hub'ın kendi host'u her zaman eklenir
patterns = ; satır başına bir düzenli ifade; ham satır eşleşirse atılır
[log:plesk-panel]
path = /var/log/plesk/panel.log
pattern = \b(ERR|CRIT|ALERT|EMERG)\b
kind = log_error
Yol sırası: --config → VITALWATCH_AGENT_CONFIG → /etc/vitalwatch/agent.ini.
VITALWATCH_URL, VITALWATCH_KEY, VITALWATCH_SECRET, VITALWATCH_ENV ve
VITALWATCH_ENABLED ortam değişkenleri [hub]'ı ezer. Ajan .env dosyası okumaz:
check bir proje dizininde çalıştırılınca o projenin anahtarını almasın. Satır sonu
yorumu yalnızca ; (düzenli ifadelerde # geçebilir). Durum dosyası
/var/lib/vitalwatch-agent/state.json (VITALWATCH_AGENT_STATE_DIR ile değişir).
Komutlar
| Komut | Ne yapar |
|---|---|
vitalwatch-agent run |
Servis olarak çalışır. SIGTERM'de alt süreçleri kapatır, kuyruğu son kez gönderir, durumu kaydeder |
vitalwatch-agent check |
Her kaynağı bulundu / bulunamadı / okunamıyor / kapalı olarak listeler; hub yapılandırmasını denetler (secret 64 karakter, https, ortam adı) |
vitalwatch-agent check --test |
Ek olarak bir log_error sınama olayı gönderir ve HTTP durumunu olduğu gibi yazar |
vitalwatch-agent systemd |
Sertleştirilmiş birim dosyasını yazdırır: root, ProtectSystem=strict, ReadWritePaths=/var/lib/vitalwatch-agent, NoNewPrivileges, ProtectHome, PrivateTmp, Restart=always |
Servis root çalışır, çünkü Plesk vhost logları ve Docker soketi başka türlü okunamıyor.
Ajan durum dosyası dışında hiçbir yere yazmaz; yalnızca journalctl, systemctl --failed,
docker events ve docker logs komutlarını okumak için çalıştırır. journalctl ya da
docker yoksa veya izin yoksa stderr'e tek bir uyarı yazar ve çalışmaya devam eder.
Ne toplanır
| Tür | Kaynak | Örnek |
|---|---|---|
web_server |
/var/log/nginx/*error*.log, /var/log/apache2/*error*.log, /var/log/httpd/*error*, Plesk /var/www/vhosts/system/*/logs/{error_log,proxy_error_log} |
[ornek.com] upstream timed out … while reading response header from upstream (+ route: GET /api/x, status: 504) |
php_fpm |
/var/log/php*-fpm.log, /var/log/php-fpm/*.log, /opt/plesk/php/*/var/log/php-fpm.log |
[pool www] server reached pm.max_children setting (5), consider raising it |
database |
/var/log/postgresql/*.log, /var/log/mysql/error.log, /var/log/mariadb/*.log, /var/log/mysqld.log, /var/log/mongodb/mongod.log, /var/log/redis/*.log |
FATAL: remaining connection slots are reserved … |
service_failed |
journald + 5 dakikada bir systemctl --failed |
php8.4-fpm.service: Failed with result 'exit-code' |
container_failed |
docker events |
api: exited with code 137, api: restart loop (3 in 10 min), api: unhealthy, api: killed by OOM |
oom |
journald (çekirdek, systemd-oomd) | Out of memory: Killed process <n> (php-fpm8.4) |
kernel |
journald (çekirdek) | php-fpm8.4[<n>]: segfault in libc.so.6, disk G/Ç hataları |
disk_full |
/proc/mounts'taki gerçek dosya sistemleri |
/var: disk 93% full, /: inodes 91% used — bağlama noktası başına saatte en fazla bir |
log_error |
[log:<ad>] bölümleri, docker_logs, journal_errors = on |
desen eşleşen satır |
- Her log ilk görüldüğünde sonundan okunur; geçmiş içe aktarılmaz. Konumlar (inode + ofset) ve journald imleci durum dosyasında tutulur; log döndürme ve kırpılma algılanır. Glob'lar dakikada bir yeniden taranır: Plesk'te yeni açılan site yeniden başlatma gerektirmeden izlenir.
- Gürültü elenir: 404'lerin
open() … failed'ı, TLS el sıkışma hataları,[warn], PHP uyarıları (yalnızcaFatal error/Parse errorgelir), uygulama düzeyi SQL hataları (SDK'nın işi),docker stop'un ürettiği çıkış kodları. - Aynı mesaj dakikada en fazla 20, toplam dakikada en fazla 300 olay. Gönderim 5 sn'de bir ya da 25 olayda; gövde 8 KB ve istek başına 8 olaya bölünür. Hub erişilemezse en fazla 1000 olay bekletilir ve üstel geri çekilmeyle yeniden denenir.
- 5 dakikada bir canlılık isteği (
{"events": [], "runtime": "agent", …}): ajan durursa projenin sunucu kanalı susar ve hub'ın kurulum sağlığı bunu gösterir. - Hub'ın kendi alan adı (
url'in host'u) her zaman yok sayılır: hub aynı sunucudaysa kendi hatası ajanı, ajanın gönderimi yeni hatayı tetiklemesin.
Bilinçli olarak toplanmayanlar
- IP adresleri — her satırda
[ip]olur; nginx'inclient:alanı tamamen silinir. - Query string ve fragment — istek satırından, URL'lerden ve yollardan atılır;
routeyalnızcaGET /yoltaşır. referrer/referervehostbaşlıkları — tamamen silinir. Site adı istemcinin yazdığıhost'tan değil, yapılandırmadakiserver_name'den ya da Plesk yolundan alınır.- Ardından SDK'nın maskesi: e-posta, kart, telefon, TC kimlik, IBAN, uzun jetonlar;
veritabanı mesajlarındaki tırnaklı değerler
?olur. - SSH / kimlik doğrulama logları (her satır IP taşır, IP'siz hâli anlamsız),
erişim logları (
access.log— hata değil trafik; ziyaret modülü zaten var), posta logları (alıcı adresleri) hiç okunmaz.journal_errors = onmodunda dasshd,sudo,postfix,dovecotgibi kaynaklar atlanır. - CPU/RAM/disk grafiği, sürekli metrik ve süreç listesi yoktur: yalnızca eşik aşıldığında tek olay.
Davranış garantileri
- Hata yutulmaz. Handler zinciri korunur,
raiseengellenmez. - Süreç yönetimine karışılmaz.
sys.exitçağrılmaz, mevcutexcepthookzincirlenir. - Kendi hatasını raporlamaz. Tüm SDK kodu
try/exceptile sarılır. - Kullanıcı isteğini bekletmez. Gönderim arka plan thread'inden, kısa zaman aşımıyla.
- Hub erişilemezse sessizce vazgeçilir.
VITALWATCH_ENABLED=falseiken hiçbir veri gönderilmez.
Güncelleme ve sürümleme
Paket PyPI'dadır: pip install -U vitalwatch en yeni kararlı sürümü kurar. Sürüm
sabitlenmezse kurulan her zaman son yayındır; karşılığında bir kural zorunlu hâle
gelir — her yayında sürüm numarası yükseltilmelidir. pip, numarası kuruluyla aynı
olan paketi yeniden kurmaz; PyPI aynı numarayla ikinci yüklemeyi zaten reddeder.
Numara yükseltilmeden yapılan bir düzeltme kurulu projelere hiç ulaşmaz ve bu
sessizce olur — paketin bütün tasarımının karşı durduğu arıza biçimi.
Sürüm çıkarma sırası:
pyproject.tomliçindekiversionvesrc/vitalwatch/reporter.pyiçindekiSDK_VERSIONbirlikte yükseltilir. İkisi ayrışırsa panelde yanlış SDK sürümü görünür.CHANGELOG.md'ye giriş.python -m pytest -q- Commit,
git tag vX.Y.Z,git push origin vX.Y.Z. Etiketpublishiş akışını tetikler: testler geçerse ve etiket paket sürümüyle eşleşirse PyPI'ye yüklenir. - Kurulu projelerde
pip install -U vitalwatch, ardındanvitalwatch-statusile doğrulama. Panelde SDK sürümünün yenilendiği görülmelidir. Sunucu ajanı için/opt/vitalwatch/bin/pip install -U vitalwatch && systemctl restart vitalwatch-agent.
Test
# Çerçeve testleri için — yoksa 53 test sessizce atlanır
pip install "Flask==3.0.0" Django fastapi starlette httpx
python -m unittest discover -s tests
Çıktıda skipped= görünüyorsa bir çerçeve kurulu değildir ve o entegrasyon
sınanmamıştır (Flask 17, Django 12, FastAPI/Starlette 24 test).
0.1.0'daki çift kayıt ve kaybolan hata tam bu yüzden fark edilmedi.
Testler hub'ın imza doğrulamasını (VerifyProjectSignature) ve gövde sınırlarını
birebir uygulayan sahte bir hub'a karşı koşar: imzanın gerçekten kabul edilip
edilmediği burada görülür, "204 aldım" demek yeterli değildir.
Metadata
Release files for vitalwatch 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| vitalwatch-0.2.1.tar.gz | 106.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vitalwatch-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 185.9 kB
Release files / vitalwatch-0.2.1.tar.gz
| Download URL | vitalwatch-0.2.1.tar.gz |
|---|---|
| Size | 106.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0d0f78837eabeb6c57cd7a56e9bf284b03713416e55d895f1501e0ffe0f96f0f
|
|
BLAKE2b-256 checksum How to use checksums |
e9900eb0719e4bd1fe0e79f120379f11388aad2c7dade3855f6f2b7e1168aef8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / vitalwatch-0.2.1-py3-none-any.whl
| Download URL | vitalwatch-0.2.1-py3-none-any.whl |
|---|---|
| Size | 79.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
86648fc5164f5463168f7277e33c315a7e8c2367a787ac63e6ad914129647aa2
|
|
BLAKE2b-256 checksum How to use checksums |
dfe92c80468bccb59e9f87c003cff636a364c7ed2b05396cd7cbc222eed27718
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for vitalwatch 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for vitalwatch-0.2.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.