classic-health-checks 0.0.1__py3-none-any.whl

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
+ from .health_check import HealthCheck
2
+ from .settings import HealthCheckSettings, HealthCheckSettingsMixin
@@ -0,0 +1,46 @@
1
+ import time
2
+ from logging import Logger
3
+ from pathlib import Path
4
+
5
+ from .settings import HealthCheckSettingsMixin
6
+
7
+
8
+ class HealthCheck:
9
+ """
10
+ Задача для выполнения проверки работоспособности путем обновления
11
+ временной метки файла.
12
+
13
+ Этот класс реализует простую проверку жизнеспособности (liveness probe).
14
+ При запуске метода `run` он периодически обновляет указанный файл
15
+ в файловой системе. Внешняя система мониторинга может отслеживать
16
+ время последнего изменения этого файла, чтобы убедиться, что сервис
17
+ активен и не завис.
18
+
19
+ Аргументы:
20
+ logger: Экземпляр стандартного логгера для вывода отладочных сообщений.
21
+ settings: Объект конфигурации с параметрами для проверки.
22
+ """
23
+
24
+ def __init__(
25
+ self,
26
+ logger: Logger,
27
+ settings: HealthCheckSettingsMixin,
28
+ ) -> None:
29
+ self.logger = logger
30
+ self.filepath = Path(settings.HEALTHCHECK_FILE_PATH)
31
+ self.interval = settings.HEALTHCHECK_INTERVAL
32
+ self.filepath.parent.mkdir(parents=True, exist_ok=True)
33
+
34
+ def run(self) -> None:
35
+ """
36
+ Запускает бесконечный цикл проверки работоспособности.
37
+
38
+ Этот метод выполняет бесконечный цикл, в котором:
39
+ 1. Обновляет временную метку файла проверки.
40
+ 2. Приостанавливает выполнение на заданный интервал.
41
+ 3. Логирует отладочное сообщение.
42
+ """
43
+ while True:
44
+ self.filepath.touch()
45
+ time.sleep(self.interval)
46
+ self.logger.debug('Healthcheck file written')
@@ -0,0 +1,18 @@
1
+ from pydantic_settings import BaseSettings
2
+
3
+
4
+ class HealthCheckSettingsMixin:
5
+ """
6
+ Настройки конфигурации для задачи проверки работоспособности.
7
+
8
+ Эти настройки могут быть загружены из переменных окружения или .env файла.
9
+ """
10
+ HEALTHCHECK_FILE_PATH: str
11
+ """Путь к файлу, используемому для проверки работоспособности."""
12
+
13
+ HEALTHCHECK_INTERVAL: float = 10.0
14
+ """Интервал в секундах между обновлениями файла проверки."""
15
+
16
+
17
+ class HealthCheckSettings(HealthCheckSettingsMixin, BaseSettings):
18
+ pass
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: classic-health-checks
3
+ Version: 0.0.1
4
+ Summary: Simple health-checks
5
+ Author-email: Sergei Variasov <variasov@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/variasov/classic-health-checks
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 4 - Beta
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Provides-Extra: dev
14
+ Requires-Dist: build~=1.2.2.post1; extra == "dev"
15
+ Requires-Dist: pytest==8.3.4; extra == "dev"
16
+ Requires-Dist: pytest-cov==6.0.0; extra == "dev"
17
+ Requires-Dist: isort==6.0.0; extra == "dev"
18
+ Requires-Dist: yapf==0.43.0; extra == "dev"
19
+ Requires-Dist: flake8==7.1.1; extra == "dev"
20
+ Requires-Dist: Flake8-pyproject==1.2.3; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # Classic Health Checks
24
+
25
+ [![PyPI version](https://badge.fury.io/py/classic-health-checks.svg)](https://badge.fury.io/py/classic-health-checks)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
27
+
28
+ Простая реализация проверки работоспособности сервиса (liveness probe) через обновление временной метки файла.
29
+
30
+ Этот пакет предоставляет задачу, которая может быть запущена в отдельном потоке или гринлете для периодического обновления файла на диске. Внешние системы мониторинга, такие как Kubernetes или systemd, могут отслеживать время последнего изменения этого файла, чтобы убедиться, что сервис активен и не завис.
31
+
32
+ ## Установка
33
+
34
+ ```bash
35
+ pip install classic-health-checks
36
+ ```
37
+
38
+ ## Использование (Usage)
39
+
40
+ Вот минимальный пример использования `HealthCheck` в отдельном потоке.
41
+
42
+
43
+ ### Использование с `gevent`
44
+
45
+ Для использования с `gevent` убедитесь, что он установлен:
46
+ ```bash
47
+ pip install gevent
48
+ ```
49
+
50
+ `HealthCheck` легко интегрируется с `gevent`. Инициализируем и запускаем run в гринлете.
51
+ ```python
52
+ import gevent
53
+ from gevent.monkey import patch_all
54
+
55
+ patch_all()
56
+
57
+ import logging
58
+ from pydantic_settings import BaseSettings
59
+ from classic.health_checks import HealthCheck, HealthCheckSettingsMixin
60
+
61
+ # Настройте базовый логгер
62
+ logging.basicConfig(
63
+ level=logging.DEBUG,
64
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
65
+ )
66
+ logger = logging.getLogger(__name__)
67
+
68
+ class AppSettings(HealthCheckSettingsMixin, BaseSettings):
69
+ ...
70
+
71
+ settings = AppSettings(HEALTHCHECK_FILE_PATH='/tmp/healthcheck')
72
+
73
+ # 1. Создаем экземпляр
74
+
75
+ health_check = HealthCheck(
76
+ logger=logger,
77
+ settings=settings,
78
+ )
79
+
80
+ # 2. Запускаем HealthCheck и другие задачи в своих гринлетах
81
+
82
+ # Псевдо-задачи для примера
83
+ class LongRunningTask:
84
+ def __init__(self, name: str):
85
+ self.name = name
86
+ def run(self):
87
+ logger.info(f"Задача '{self.name}' запущена.")
88
+ while True:
89
+ gevent.sleep(60)
90
+
91
+ task1 = LongRunningTask("Обработчик сообщений")
92
+ task2 = LongRunningTask("Сборщик метрик")
93
+
94
+ all_greenlets = [
95
+ gevent.spawn(health_check.run),
96
+ gevent.spawn(task1.run),
97
+ gevent.spawn(task2.run),
98
+ ]
99
+
100
+ logger.info(f"Запущено {len(all_greenlets)} гринлетов, включая HealthCheck.")
101
+
102
+ # 3. Ожидаем завершения всех задач и обрабатываем остановку
103
+ try:
104
+ gevent.joinall(all_greenlets, raise_error=True)
105
+ except (KeyboardInterrupt, SystemExit):
106
+ logger.info("Получен сигнал остановки, завершаем все гринлеты...")
107
+ gevent.killall(all_greenlets)
108
+ logger.info("Приложение остановлено.")
109
+
110
+ ```
111
+
112
+ > **Подсказка:** "Сигнал остановки" обычно отправляется нажатием `Ctrl+C` в терминале, где запущен скрипт.
113
+
114
+ ### Интеграция с Kubernetes
115
+
116
+ Вы можете использовать этот механизм для настройки `livenessProbe` в вашем Helm-чарте:
117
+
118
+ ```yaml
119
+ # ... внутри spec.template.spec.containers[]
120
+ # Добавляем переменную окружения, чтобы она была доступна в livenessProbe
121
+ env:
122
+ - name: HEALTHCHECK_FILE_PATH
123
+ value: /tmp/my_app_healthy
124
+
125
+
126
+ envsFromSecret:
127
+ secret-envs:
128
+ ...
129
+ livenessProbe:
130
+ exec:
131
+ command:
132
+ - /bin/sh
133
+ - -c
134
+ - "[ $(($(date +%s) - $(stat -c %Y $HEALTHCHECK_FILE_PATH))) -le 10 ]"
135
+ periodSeconds: 10
136
+ initialDelaySeconds: 30
137
+ failureThreshold: 3
138
+ ```
@@ -0,0 +1,8 @@
1
+ classic/health_checks/__init__.py,sha256=T5w_I9QTG8iAt91UCUhDyGTUY7QZ92nvEEHC9-moGHo,106
2
+ classic/health_checks/health_check.py,sha256=w3zUt7uSL61O-GKsipyLUJnpgxOQF7Q3YwTmOY9nbMg,2137
3
+ classic/health_checks/settings.py,sha256=AINmmz9EUo-w8Q8xT4LMbuvJk_0AO0g4K6wQWFw6Iy8,735
4
+ classic_health_checks-0.0.1.dist-info/licenses/LICENSE,sha256=NJlZYf1BWmSV82IG29S9QdVpNjUsMMIeMwAtJpkkU9w,1071
5
+ classic_health_checks-0.0.1.dist-info/METADATA,sha256=1Jpn-08_ebaOePLl7FgLPsN5r3St-bxXsAvyNYs2OYk,5016
6
+ classic_health_checks-0.0.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
7
+ classic_health_checks-0.0.1.dist-info/top_level.txt,sha256=NGd9e95FycaETli7Cs0MwFTtdjK6EYJ3tq_ErbSLNZg,8
8
+ classic_health_checks-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Sergei Variasov
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 @@
1
+ classic