django-health-check 3.20.7__tar.gz → 3.21.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. {django_health_check-3.20.7 → django_health_check-3.21.0}/PKG-INFO +8 -1
  2. django_health_check-3.21.0/health_check/__init__.py +30 -0
  3. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/_version.py +3 -3
  4. django_health_check-3.21.0/health_check/backends.py +101 -0
  5. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/cache/apps.py +1 -1
  6. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/cache/backends.py +21 -12
  7. django_health_check-3.21.0/health_check/contrib/celery/__init__.py +3 -0
  8. django_health_check-3.21.0/health_check/contrib/celery/apps.py +31 -0
  9. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/celery/backends.py +6 -2
  10. django_health_check-3.21.0/health_check/contrib/celery_ping/apps.py +19 -0
  11. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/celery_ping/backends.py +16 -5
  12. django_health_check-3.21.0/health_check/contrib/db_heartbeat/apps.py +19 -0
  13. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/db_heartbeat/backends.py +16 -4
  14. django_health_check-3.21.0/health_check/contrib/mail/apps.py +19 -0
  15. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/mail/backends.py +22 -6
  16. django_health_check-3.21.0/health_check/contrib/migrations/apps.py +19 -0
  17. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/migrations/backends.py +6 -2
  18. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/psutil/apps.py +7 -0
  19. django_health_check-3.21.0/health_check/contrib/psutil/backends.py +63 -0
  20. django_health_check-3.21.0/health_check/contrib/rabbitmq/__init__.py +3 -0
  21. django_health_check-3.21.0/health_check/contrib/rabbitmq/apps.py +19 -0
  22. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/rabbitmq/backends.py +12 -5
  23. django_health_check-3.21.0/health_check/contrib/redis/__init__.py +3 -0
  24. django_health_check-3.21.0/health_check/contrib/redis/apps.py +19 -0
  25. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/redis/backends.py +18 -7
  26. django_health_check-3.21.0/health_check/contrib/s3boto3_storage/apps.py +19 -0
  27. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/s3boto3_storage/backends.py +5 -1
  28. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/s3boto_storage/apps.py +8 -0
  29. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/s3boto_storage/backends.py +4 -0
  30. django_health_check-3.21.0/health_check/db/apps.py +20 -0
  31. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/db/backends.py +6 -2
  32. django_health_check-3.21.0/health_check/deprecation.py +35 -0
  33. django_health_check-3.21.0/health_check/management/commands/health_check.py +92 -0
  34. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/mixins.py +10 -8
  35. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/storage/backends.py +19 -20
  36. django_health_check-3.21.0/health_check/templates/health_check/index.html +171 -0
  37. django_health_check-3.21.0/health_check/urls.py +18 -0
  38. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/views.py +45 -2
  39. {django_health_check-3.20.7 → django_health_check-3.21.0}/pyproject.toml +19 -4
  40. django_health_check-3.20.7/health_check/__init__.py +0 -6
  41. django_health_check-3.20.7/health_check/backends.py +0 -64
  42. django_health_check-3.20.7/health_check/contrib/celery/apps.py +0 -28
  43. django_health_check-3.20.7/health_check/contrib/celery_ping/apps.py +0 -12
  44. django_health_check-3.20.7/health_check/contrib/db_heartbeat/apps.py +0 -12
  45. django_health_check-3.20.7/health_check/contrib/mail/apps.py +0 -12
  46. django_health_check-3.20.7/health_check/contrib/migrations/apps.py +0 -12
  47. django_health_check-3.20.7/health_check/contrib/psutil/backends.py +0 -36
  48. django_health_check-3.20.7/health_check/contrib/rabbitmq/apps.py +0 -12
  49. django_health_check-3.20.7/health_check/contrib/redis/apps.py +0 -12
  50. django_health_check-3.20.7/health_check/contrib/s3boto3_storage/apps.py +0 -12
  51. django_health_check-3.20.7/health_check/db/apps.py +0 -13
  52. django_health_check-3.20.7/health_check/management/__init__.py +0 -0
  53. django_health_check-3.20.7/health_check/management/commands/__init__.py +0 -0
  54. django_health_check-3.20.7/health_check/management/commands/health_check.py +0 -30
  55. django_health_check-3.20.7/health_check/storage/__init__.py +0 -0
  56. django_health_check-3.20.7/health_check/templates/health_check/index.html +0 -79
  57. django_health_check-3.20.7/health_check/urls.py +0 -10
  58. {django_health_check-3.20.7 → django_health_check-3.21.0}/LICENSE +0 -0
  59. {django_health_check-3.20.7 → django_health_check-3.21.0}/README.md +0 -0
  60. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/cache/__init__.py +0 -0
  61. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/conf.py +0 -0
  62. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/__init__.py +0 -0
  63. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/contrib/celery/tasks.py +0 -0
  64. {django_health_check-3.20.7/health_check/contrib/celery → django_health_check-3.21.0/health_check/contrib/celery_ping}/__init__.py +0 -0
  65. {django_health_check-3.20.7/health_check/contrib/celery_ping → django_health_check-3.21.0/health_check/contrib/db_heartbeat}/__init__.py +0 -0
  66. {django_health_check-3.20.7/health_check/contrib/db_heartbeat → django_health_check-3.21.0/health_check/contrib/mail}/__init__.py +0 -0
  67. {django_health_check-3.20.7/health_check/contrib/mail → django_health_check-3.21.0/health_check/contrib/migrations}/__init__.py +0 -0
  68. {django_health_check-3.20.7/health_check/contrib/migrations → django_health_check-3.21.0/health_check/contrib/psutil}/__init__.py +0 -0
  69. {django_health_check-3.20.7/health_check/contrib/psutil → django_health_check-3.21.0/health_check/contrib/s3boto3_storage}/__init__.py +0 -0
  70. {django_health_check-3.20.7/health_check/contrib/rabbitmq → django_health_check-3.21.0/health_check/contrib/s3boto_storage}/__init__.py +0 -0
  71. {django_health_check-3.20.7/health_check/contrib/redis → django_health_check-3.21.0/health_check/db}/__init__.py +0 -0
  72. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/db/migrations/0001_initial.py +0 -0
  73. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/db/migrations/0002_alter_testmodel_options.py +0 -0
  74. {django_health_check-3.20.7/health_check/contrib/s3boto3_storage → django_health_check-3.21.0/health_check/db/migrations}/__init__.py +0 -0
  75. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/db/models.py +0 -0
  76. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/exceptions.py +0 -0
  77. {django_health_check-3.20.7/health_check/contrib/s3boto_storage → django_health_check-3.21.0/health_check/management}/__init__.py +0 -0
  78. {django_health_check-3.20.7/health_check/db → django_health_check-3.21.0/health_check/management/commands}/__init__.py +0 -0
  79. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/plugins.py +0 -0
  80. {django_health_check-3.20.7/health_check/db/migrations → django_health_check-3.21.0/health_check/storage}/__init__.py +0 -0
  81. {django_health_check-3.20.7 → django_health_check-3.21.0}/health_check/storage/apps.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-health-check
3
- Version: 3.20.7
3
+ Version: 3.21.0
4
4
  Summary: Monitor the health of your Django app and its connected services.
5
5
  Keywords: django,postgresql
6
6
  Author-email: Kristian Ollegaard <kristian@oellegaard.com>, Johannes Maron <johannes@maron.family>
@@ -28,12 +28,19 @@ Classifier: Topic :: System :: Monitoring
28
28
  Classifier: Topic :: Utilities
29
29
  License-File: LICENSE
30
30
  Requires-Dist: Django>=4.2
31
+ Requires-Dist: psutil
32
+ Requires-Dist: celery>=5.0.0 ; extra == "celery"
33
+ Requires-Dist: kombu>=5.0.0 ; extra == "rabbitmq"
34
+ Requires-Dist: redis>=3.0.0 ; extra == "redis"
31
35
  Project-URL: Changelog, https://github.com/codingjoe/django-health-check/releases
32
36
  Project-URL: Documentation, https://codingjoe.dev/django-health-check/
33
37
  Project-URL: Homepage, https://codingjoe.dev/django-health-check/
34
38
  Project-URL: Issues, https://github.com/codingjoe/django-health-check/issues
35
39
  Project-URL: Releasenotes, https://github.com/codingjoe/django-health-check/releases/latest
36
40
  Project-URL: Source, https://github.com/codingjoe/django-health-check
41
+ Provides-Extra: celery
42
+ Provides-Extra: rabbitmq
43
+ Provides-Extra: redis
37
44
 
38
45
  <p align="center">
39
46
  <picture>
@@ -0,0 +1,30 @@
1
+ """Monitor the health of your Django app and its connected services."""
2
+
3
+ from . import _version # noqa
4
+ from .cache.backends import CacheBackend as Cache
5
+ from .contrib.mail.backends import MailHealthCheck as Mail
6
+ from .contrib.psutil.backends import DiskUsage as Disk, MemoryUsage as Memory
7
+ from .contrib.db_heartbeat.backends import DatabaseHeartBeatCheck as Database
8
+ from .storage.backends import StorageHealthCheck as Storage
9
+ from .backends import HealthCheck
10
+
11
+ __version__ = _version.__version__
12
+ VERSION = _version.__version_tuple__
13
+
14
+ Cache.__qualname__ = "Cache"
15
+ Database.__qualname__ = "Database"
16
+ Disk.__qualname__ = "Disk"
17
+ Mail.__qualname__ = "Mail"
18
+ Storage.__qualname__ = "Storage"
19
+ Memory.__qualname__ = "Memory"
20
+ __all__ = [
21
+ "__version__",
22
+ "VERSION",
23
+ "Cache",
24
+ "Database",
25
+ "Disk",
26
+ "Mail",
27
+ "Storage",
28
+ "Memory",
29
+ "HealthCheck",
30
+ ]
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '3.20.7'
32
- __version_tuple__ = version_tuple = (3, 20, 7)
31
+ __version__ = version = '3.21.0'
32
+ __version_tuple__ = version_tuple = (3, 21, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g1c04d5acb'
34
+ __commit_id__ = commit_id = 'gae94a27bd'
@@ -0,0 +1,101 @@
1
+ import dataclasses
2
+ import logging
3
+ import warnings
4
+ from timeit import default_timer as timer
5
+
6
+ from health_check.exceptions import HealthCheckException
7
+
8
+ logger = logging.getLogger("health-check")
9
+
10
+
11
+ @dataclasses.dataclass()
12
+ class HealthCheck:
13
+ """
14
+ Base class for all health check backends.
15
+
16
+ To create your own health check backend, subclass this class
17
+ and implement the ``check_status`` method.
18
+ """
19
+
20
+ critical_service: bool = dataclasses.field(init=False, default=True, repr=False)
21
+ errors: list[HealthCheckException] = dataclasses.field(init=False, default_factory=list, repr=False)
22
+
23
+ def check_status(self):
24
+ """
25
+ Execute the health check logic.
26
+
27
+ This method should be overridden by subclasses to implement
28
+ specific health check logic. If the check fails, it should
29
+ call `self.add_error` with an appropriate error message or
30
+ raise a `HealthCheckException`.
31
+
32
+ Raises:
33
+ HealthCheckException: If the health check fails.
34
+ ServiceWarning: If the health check encounters a warning condition.
35
+
36
+ """
37
+ raise NotImplementedError
38
+
39
+ def run_check(self):
40
+ start = timer()
41
+ self.errors = []
42
+ try:
43
+ self.check_status()
44
+ except HealthCheckException as e:
45
+ self.add_error(e, e)
46
+ except BaseException:
47
+ logger.exception("Unexpected Error!")
48
+ raise
49
+ finally:
50
+ self.time_taken = timer() - start
51
+
52
+ def add_error(self, error, cause=None):
53
+ if isinstance(error, HealthCheckException):
54
+ pass
55
+ elif isinstance(error, str):
56
+ msg = error
57
+ error = HealthCheckException(msg)
58
+ else:
59
+ msg = "unknown error"
60
+ error = HealthCheckException(msg)
61
+ if isinstance(cause, BaseException):
62
+ logger.exception(str(error))
63
+ else:
64
+ logger.error(str(error))
65
+ self.errors.append(error)
66
+
67
+ def pretty_status(self):
68
+ if self.errors:
69
+ return "\n".join(str(e) for e in self.errors)
70
+ return "OK"
71
+
72
+ @property
73
+ def status(self):
74
+ return int(not self.errors)
75
+
76
+ def __repr__(self):
77
+ if hasattr(self, "identifier"):
78
+ warnings.warn(
79
+ "`identifier()` method is deprecated: implement `__repr__()` instead to return a stable identifier. Action: update your backend class to implement `__repr__` and remove `identifier()`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
80
+ DeprecationWarning,
81
+ )
82
+ return self.identifier()
83
+
84
+ return self.__class__.__name__
85
+
86
+
87
+ class BaseHealthCheck(HealthCheck):
88
+ """
89
+ Deprecated base class for health check backends.
90
+
91
+ This class is maintained for backward compatibility.
92
+ New health check backends should inherit from `HealthCheck` instead.
93
+ """
94
+
95
+ def __init_subclass__(cls, **kwargs):
96
+ warnings.warn(
97
+ f"{cls.__name__} inherits from deprecated `BaseHealthCheck`: inherit from `HealthCheck` instead. Action: update subclass to inherit from `health_check.backends.HealthCheck`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
98
+ DeprecationWarning,
99
+ stacklevel=2,
100
+ )
101
+ super().__init_subclass__(**kwargs)
@@ -11,4 +11,4 @@ class HealthCheckConfig(AppConfig):
11
11
  from .backends import CacheBackend
12
12
 
13
13
  for backend in settings.CACHES:
14
- plugin_dir.register(CacheBackend, backend=backend)
14
+ plugin_dir.register(CacheBackend, alias=backend)
@@ -1,7 +1,10 @@
1
+ import dataclasses
2
+ import datetime
3
+
1
4
  from django.conf import settings
2
5
  from django.core.cache import CacheKeyWarning, caches
3
6
 
4
- from health_check.backends import BaseHealthCheckBackend
7
+ from health_check.backends import HealthCheck
5
8
  from health_check.exceptions import ServiceReturnedUnexpectedResult, ServiceUnavailable
6
9
 
7
10
  try:
@@ -17,21 +20,27 @@ except ModuleNotFoundError:
17
20
  pass
18
21
 
19
22
 
20
- class CacheBackend(BaseHealthCheckBackend):
21
- def __init__(self, backend="default"):
22
- super().__init__()
23
- self.backend = backend
24
- self.cache_key = getattr(settings, "HEALTHCHECK_CACHE_KEY", "djangohealthcheck_test")
23
+ @dataclasses.dataclass
24
+ class CacheBackend(HealthCheck):
25
+ """
26
+ Check that the cache backend is able to set and get a value.
25
27
 
26
- def identifier(self):
27
- return f"Cache backend: {self.backend}"
28
+ Args:
29
+ alias: The cache alias to test against.
28
30
 
29
- def check_status(self):
30
- cache = caches[self.backend]
31
+ """
31
32
 
33
+ alias: str = dataclasses.field(default="default")
34
+ cache_key: str = dataclasses.field(
35
+ default=getattr(settings, "HEALTHCHECK_CACHE_KEY", "djangohealthcheck_test"), repr=False
36
+ )
37
+
38
+ def check_status(self):
39
+ cache = caches[self.alias]
40
+ ts = datetime.datetime.now().timestamp()
32
41
  try:
33
- cache.set(self.cache_key, "itworks")
34
- if not cache.get(self.cache_key) == "itworks":
42
+ cache.set(self.cache_key, f"itworks-{ts}")
43
+ if not cache.get(self.cache_key) == f"itworks-{ts}":
35
44
  raise ServiceUnavailable(f"Cache key {self.cache_key} does not match")
36
45
  except CacheKeyWarning as e:
37
46
  self.add_error(ServiceReturnedUnexpectedResult("Cache key warning"), e)
@@ -0,0 +1,3 @@
1
+ from ..celery_ping.backends import CeleryPingHealthCheck as Ping
2
+
3
+ __all__ = ["Ping"]
@@ -0,0 +1,31 @@
1
+ import warnings
2
+
3
+ from celery import current_app
4
+ from django.apps import AppConfig
5
+ from django.conf import settings
6
+
7
+ from health_check.plugins import plugin_dir
8
+
9
+
10
+ class HealthCheckConfig(AppConfig):
11
+ name = "health_check.contrib.celery"
12
+
13
+ def ready(self):
14
+ from .backends import CeleryHealthCheck
15
+
16
+ warnings.warn(
17
+ "The `health_check.contrib.celery` app is deprecated: checks are now configured via `HealthCheckView`. Action: remove this sub-app from `INSTALLED_APPS` and add the Celery check(s) to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
18
+ DeprecationWarning,
19
+ )
20
+
21
+ if hasattr(settings, "HEALTHCHECK_CELERY_TIMEOUT"):
22
+ warnings.warn(
23
+ "`HEALTHCHECK_CELERY_TIMEOUT` setting is deprecated: it was split into separate timeouts. Action: replace it with `HEALTHCHECK_CELERY_RESULT_TIMEOUT` and `HEALTHCHECK_CELERY_QUEUE_TIMEOUT`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
24
+ DeprecationWarning,
25
+ )
26
+
27
+ for queue in current_app.amqp.queues:
28
+ celery_class_name = "CeleryHealthCheck" + queue.title()
29
+
30
+ celery_class = type(celery_class_name, (CeleryHealthCheck,), {"queue": queue})
31
+ plugin_dir.register(celery_class)
@@ -1,13 +1,17 @@
1
1
  from celery.exceptions import TaskRevokedError, TimeoutError
2
2
  from django.conf import settings
3
3
 
4
- from health_check.backends import BaseHealthCheckBackend
4
+ from health_check.backends import HealthCheck
5
+ from health_check.deprecation import deprecated
5
6
  from health_check.exceptions import ServiceReturnedUnexpectedResult, ServiceUnavailable
6
7
 
7
8
  from .tasks import add
8
9
 
9
10
 
10
- class CeleryHealthCheck(BaseHealthCheckBackend):
11
+ @deprecated(
12
+ "`CeleryHealthCheck` is deprecated: use `health_check.contrib.celery.Ping` (or the new view-based Celery ping check) instead. Action: remove legacy CeleryHealthCheck subclasses and configure `HealthCheckView` with the new Celery ping check in your `checks` list. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md)."
13
+ )
14
+ class CeleryHealthCheck(HealthCheck):
11
15
  def check_status(self):
12
16
  timeout = getattr(settings, "HEALTHCHECK_CELERY_TIMEOUT", 3)
13
17
  result_timeout = getattr(settings, "HEALTHCHECK_CELERY_RESULT_TIMEOUT", timeout)
@@ -0,0 +1,19 @@
1
+ import warnings
2
+
3
+ from django.apps import AppConfig
4
+
5
+ from health_check.plugins import plugin_dir
6
+
7
+
8
+ class HealthCheckConfig(AppConfig):
9
+ name = "health_check.contrib.celery_ping"
10
+
11
+ def ready(self):
12
+ from .backends import CeleryPingHealthCheck
13
+
14
+ warnings.warn(
15
+ "The `health_check.contrib.celery_ping` app is deprecated: checks are now configured via `HealthCheckView`. Action: remove this sub-app from `INSTALLED_APPS` and add `health_check.contrib.celery.Ping` or the appropriate ping check to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
16
+ DeprecationWarning,
17
+ )
18
+
19
+ plugin_dir.register(CeleryPingHealthCheck)
@@ -1,18 +1,29 @@
1
+ import dataclasses
2
+ import datetime
3
+
1
4
  from celery.app import default_app as app
2
5
  from django.conf import settings
3
6
 
4
- from health_check.backends import BaseHealthCheckBackend
7
+ from health_check.backends import HealthCheck
5
8
  from health_check.exceptions import ServiceUnavailable
6
9
 
7
10
 
8
- class CeleryPingHealthCheck(BaseHealthCheckBackend):
11
+ @dataclasses.dataclass
12
+ class CeleryPingHealthCheck(HealthCheck):
13
+ """
14
+ Check Celery worker availability using the ping control command.
15
+
16
+ Args:
17
+ timeout: Timeout duration for the ping command.
18
+
19
+ """
20
+
9
21
  CORRECT_PING_RESPONSE = {"ok": "pong"}
22
+ timeout: datetime.timedelta = datetime.timedelta(seconds=getattr(settings, "HEALTHCHECK_CELERY_PING_TIMEOUT", 1))
10
23
 
11
24
  def check_status(self):
12
- timeout = getattr(settings, "HEALTHCHECK_CELERY_PING_TIMEOUT", 1)
13
-
14
25
  try:
15
- ping_result = app.control.ping(timeout=timeout)
26
+ ping_result = app.control.ping(timeout=self.timeout.total_seconds())
16
27
  except OSError as e:
17
28
  self.add_error(ServiceUnavailable("IOError"), e)
18
29
  except NotImplementedError as exc:
@@ -0,0 +1,19 @@
1
+ import warnings
2
+
3
+ from django.apps import AppConfig
4
+
5
+ from health_check.plugins import plugin_dir
6
+
7
+
8
+ class HealthCheckConfig(AppConfig):
9
+ name = "health_check.contrib.db_heartbeat"
10
+
11
+ def ready(self):
12
+ from .backends import DatabaseHeartBeatCheck
13
+
14
+ warnings.warn(
15
+ "The `health_check.contrib.db_heartbeat` app is deprecated: checks are now configured via `HealthCheckView`. Action: remove this sub-app from `INSTALLED_APPS` and add `health_check.contrib.db_heartbeat.DatabaseHeartBeatCheck` to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
16
+ DeprecationWarning,
17
+ )
18
+
19
+ plugin_dir.register(DatabaseHeartBeatCheck)
@@ -1,7 +1,9 @@
1
- from django.db import connection
1
+ import dataclasses
2
+
3
+ from django.db import connections
2
4
  from django.db.models import Expression
3
5
 
4
- from health_check.backends import BaseHealthCheckBackend
6
+ from health_check.backends import HealthCheck
5
7
  from health_check.exceptions import ServiceUnavailable
6
8
 
7
9
 
@@ -15,10 +17,20 @@ class SelectOne(Expression):
15
17
  return "SELECT 1 FROM DUAL", []
16
18
 
17
19
 
18
- class DatabaseHeartBeatCheck(BaseHealthCheckBackend):
19
- """Health check that runs a simple SELECT 1; query to test if the database connection is alive."""
20
+ @dataclasses.dataclass
21
+ class DatabaseHeartBeatCheck(HealthCheck):
22
+ """
23
+ Check database connectivity by executing a simple SELECT 1 query.
24
+
25
+ Args:
26
+ alias: The alias of the database connection to check.
27
+
28
+ """
29
+
30
+ alias: str = dataclasses.field(default="default")
20
31
 
21
32
  def check_status(self):
33
+ connection = connections[self.alias]
22
34
  try:
23
35
  result = None
24
36
  compiler = connection.ops.compiler("SQLCompiler")(SelectOne(), connection, None)
@@ -0,0 +1,19 @@
1
+ import warnings
2
+
3
+ from django.apps import AppConfig
4
+
5
+ from health_check.plugins import plugin_dir
6
+
7
+
8
+ class HealthCheckConfig(AppConfig):
9
+ name = "health_check.contrib.mail"
10
+
11
+ def ready(self):
12
+ from .backends import MailHealthCheck
13
+
14
+ warnings.warn(
15
+ "The `health_check.contrib.mail` app is deprecated: checks are now configured via `HealthCheckView`. Action: remove this sub-app from `INSTALLED_APPS` and add `health_check.Mail` to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
16
+ DeprecationWarning,
17
+ )
18
+
19
+ plugin_dir.register(MailHealthCheck)
@@ -1,6 +1,9 @@
1
+ import dataclasses
2
+ import datetime
1
3
  import logging
2
4
  import smtplib
3
5
 
6
+ from django.conf import settings
4
7
  from django.core.mail import get_connection
5
8
  from django.core.mail.backends.base import BaseEmailBackend
6
9
 
@@ -9,13 +12,26 @@ from health_check import backends, conf, exceptions
9
12
  logger = logging.getLogger(__name__)
10
13
 
11
14
 
12
- class MailHealthCheck(backends.BaseHealthCheckBackend):
13
- """Check that mail backend is working."""
15
+ @dataclasses.dataclass
16
+ class MailHealthCheck(backends.HealthCheck):
17
+ """
18
+ Check that mail backend is able to open and close connection.
19
+
20
+ Args:
21
+ backend: The email backend to test against.
22
+ timeout: Timeout for connection to mail server.
23
+
24
+ """
25
+
26
+ backend: str = settings.EMAIL_BACKEND
27
+ timeout: datetime.timedelta = dataclasses.field(
28
+ default=datetime.timedelta(seconds=conf.HEALTH_CHECK.get("MAIL_TIMEOUT", 15)),
29
+ repr=False,
30
+ )
14
31
 
15
32
  def check_status(self) -> None:
16
- """Open and close connection with email server."""
17
- connection: BaseEmailBackend = get_connection(fail_silently=False)
18
- connection.timeout = conf.HEALTH_CHECK.get("MAIL_TIMEOUT", 15)
33
+ connection: BaseEmailBackend = get_connection(self.backend, fail_silently=False)
34
+ connection.timeout = self.timeout.total_seconds()
19
35
  logger.debug("Trying to open connection to mail backend.")
20
36
  try:
21
37
  connection.open()
@@ -42,4 +58,4 @@ class MailHealthCheck(backends.BaseHealthCheckBackend):
42
58
  )
43
59
  finally:
44
60
  connection.close()
45
- logger.debug("Connection established. Mail backend is healthy.")
61
+ logger.debug("Connection established. Mail backend %r is healthy.", self.backend)
@@ -0,0 +1,19 @@
1
+ import warnings
2
+
3
+ from django.apps import AppConfig
4
+
5
+ from health_check.plugins import plugin_dir
6
+
7
+
8
+ class HealthCheckConfig(AppConfig):
9
+ name = "health_check.contrib.migrations"
10
+
11
+ def ready(self):
12
+ from .backends import MigrationsHealthCheck
13
+
14
+ warnings.warn(
15
+ "The `health_check.contrib.migrations` app is deprecated: checks are now configured via `HealthCheckView`. Action: remove this sub-app from `INSTALLED_APPS` and add the migration check to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
16
+ DeprecationWarning,
17
+ )
18
+
19
+ plugin_dir.register(MigrationsHealthCheck)
@@ -4,13 +4,17 @@ from django.conf import settings
4
4
  from django.db import DEFAULT_DB_ALIAS, DatabaseError, connections
5
5
  from django.db.migrations.executor import MigrationExecutor
6
6
 
7
- from health_check.backends import BaseHealthCheckBackend
7
+ from health_check.backends import HealthCheck
8
+ from health_check.deprecation import deprecated
8
9
  from health_check.exceptions import ServiceUnavailable
9
10
 
10
11
  logger = logging.getLogger(__name__)
11
12
 
12
13
 
13
- class MigrationsHealthCheck(BaseHealthCheckBackend):
14
+ @deprecated(
15
+ "`MigrationsHealthCheck` is deprecated and removed: Django's system check framework covers migrations. Action: remove this check and rely on Django's check framework or add an alternative check to `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md)."
16
+ )
17
+ class MigrationsHealthCheck(HealthCheck):
14
18
  def get_migration_plan(self, executor):
15
19
  return executor.migration_plan(executor.loader.graph.leaf_nodes())
16
20
 
@@ -1,3 +1,5 @@
1
+ import warnings
2
+
1
3
  from django.apps import AppConfig
2
4
  from django.conf import settings
3
5
 
@@ -10,6 +12,11 @@ class HealthCheckConfig(AppConfig):
10
12
  def ready(self):
11
13
  from .backends import DiskUsage, MemoryUsage
12
14
 
15
+ warnings.warn(
16
+ "The `health_check.contrib.psutil` app is deprecated: checks are now configured via `HealthCheckView` and explicit `checks` lists. Action: remove this sub-app from `INSTALLED_APPS` and add `health_check.Disk` and `health_check.Memory` to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
17
+ DeprecationWarning,
18
+ )
19
+
13
20
  # Ensure checks haven't been explicitly disabled before registering
14
21
  if (
15
22
  hasattr(settings, "HEALTH_CHECK")
@@ -0,0 +1,63 @@
1
+ import dataclasses
2
+ import os
3
+ import pathlib
4
+ import socket
5
+
6
+ import psutil
7
+
8
+ from health_check.backends import HealthCheck
9
+ from health_check.conf import HEALTH_CHECK
10
+ from health_check.exceptions import ServiceReturnedUnexpectedResult, ServiceWarning
11
+
12
+
13
+ @dataclasses.dataclass()
14
+ class DiskUsage(HealthCheck):
15
+ """
16
+ Check system disk usage.
17
+
18
+ Args:
19
+ path: Path to check disk usage for.
20
+ max_disk_usage_percent: Maximum disk usage in percent or None to disable the check.
21
+
22
+ """
23
+
24
+ path: pathlib.Path | str = dataclasses.field(default=os.getcwd())
25
+ max_disk_usage_percent: float | None = dataclasses.field(default=HEALTH_CHECK["DISK_USAGE_MAX"], repr=False)
26
+ hostname: str = dataclasses.field(default_factory=socket.gethostname, init=False)
27
+
28
+ def check_status(self):
29
+ try:
30
+ du = psutil.disk_usage(str(self.path))
31
+ if self.max_disk_usage_percent and du.percent >= self.max_disk_usage_percent:
32
+ raise ServiceWarning(f"{du.percent}\u202f% disk usage")
33
+ except ValueError as e:
34
+ self.add_error(ServiceReturnedUnexpectedResult("ValueError"), e)
35
+
36
+
37
+ @dataclasses.dataclass()
38
+ class MemoryUsage(HealthCheck):
39
+ """
40
+ Check system memory usage.
41
+
42
+ Args:
43
+ min_gibibytes_available: Minimum available memory in gibibytes or None to disable the check.
44
+ max_memory_usage_percent: Maximum memory usage in percent or None to disable the check.
45
+
46
+ """
47
+
48
+ min_gibibytes_available: float | None = dataclasses.field(default=None, repr=False)
49
+ max_memory_usage_percent: float | None = dataclasses.field(default=90.0, repr=False)
50
+ hostname: str = dataclasses.field(default_factory=socket.gethostname, init=False)
51
+
52
+ def check_status(self):
53
+ try:
54
+ memory = psutil.virtual_memory()
55
+ available_gibi = memory.available / (1024**3)
56
+ total_gibi = memory.total / (1024**3)
57
+ msg = f"RAM {available_gibi:.1f}/{total_gibi:.1f}GiB ({memory.percent}\u202f%)"
58
+ if self.min_gibibytes_available and available_gibi < self.min_gibibytes_available:
59
+ raise ServiceWarning(msg)
60
+ if self.max_memory_usage_percent and memory.percent >= self.max_memory_usage_percent:
61
+ raise ServiceWarning(msg)
62
+ except ValueError as e:
63
+ self.add_error(ServiceReturnedUnexpectedResult("ValueError"), e)
@@ -0,0 +1,3 @@
1
+ from .backends import RabbitMQHealthCheck as RabbitMQ
2
+
3
+ __all__ = ["RabbitMQ"]
@@ -0,0 +1,19 @@
1
+ import warnings
2
+
3
+ from django.apps import AppConfig
4
+
5
+ from health_check.plugins import plugin_dir
6
+
7
+
8
+ class HealthCheckConfig(AppConfig):
9
+ name = "health_check.contrib.rabbitmq"
10
+
11
+ def ready(self):
12
+ from .backends import RabbitMQHealthCheck as RabbitMQ
13
+
14
+ warnings.warn(
15
+ "The `health_check.contrib.rabbitmq` app is deprecated: checks are now configured via `HealthCheckView`. Action: remove this sub-app from `INSTALLED_APPS` and add `health_check.contrib.rabbitmq.RabbitMQ` to your `HealthCheckView.checks`. See migration guide: https://codingjoe.dev/django-health-check/migrate-to-v4/ (docs/migrate-to-v4.md).",
16
+ DeprecationWarning,
17
+ )
18
+
19
+ plugin_dir.register(RabbitMQ)
@@ -1,22 +1,29 @@
1
+ import dataclasses
1
2
  import logging
2
3
 
3
4
  from amqp.exceptions import AccessRefused
4
5
  from django.conf import settings
5
6
  from kombu import Connection
6
7
 
7
- from health_check.backends import BaseHealthCheckBackend
8
+ from health_check.backends import HealthCheck
8
9
  from health_check.exceptions import ServiceUnavailable
9
10
 
10
11
  logger = logging.getLogger(__name__)
11
12
 
12
13
 
13
- class RabbitMQHealthCheck(BaseHealthCheckBackend):
14
- """Health check for RabbitMQ."""
14
+ @dataclasses.dataclass
15
+ class RabbitMQHealthCheck(HealthCheck):
16
+ """
17
+ Check RabbitMQ service by opening and closing a broker channel.
15
18
 
16
- namespace = None
19
+ Args:
20
+ namespace: Optional namespace for the broker URL setting.
21
+
22
+ """
23
+
24
+ namespace: str = None
17
25
 
18
26
  def check_status(self):
19
- """Check RabbitMQ service by opening and closing a broker channel."""
20
27
  logger.debug("Checking for a broker_url on django settings...")
21
28
 
22
29
  broker_url_setting_key = f"{self.namespace}_BROKER_URL" if self.namespace else "BROKER_URL"
@@ -0,0 +1,3 @@
1
+ from .backends import RedisHealthCheck as Redis
2
+
3
+ __all__ = ["Redis"]