Giter VIP home page Giter VIP logo

django-health-check's Introduction

django-health-check

version pyversion djversion license

This project checks for various conditions and provides reports when anomalous behavior is detected.

The following health checks are bundled with this project:

  • cache
  • database
  • storage
  • disk and memory utilization (via psutil)
  • AWS S3 storage
  • Celery task queue
  • Celery ping
  • RabbitMQ
  • Migrations

Writing your own custom health checks is also very quick and easy.

We also like contributions, so don't be afraid to make a pull request.

Use Cases

The primary intended use case is to monitor conditions via HTTP(S), with responses available in HTML and JSON formats. When you get back a response that includes one or more problems, you can then decide the appropriate course of action, which could include generating notifications and/or automating the replacement of a failing node with a new one. If you are monitoring health in a high-availability environment with a load balancer that returns responses from multiple nodes, please note that certain checks (e.g., disk and memory usage) will return responses specific to the node selected by the load balancer.

Supported Versions

We officially only support the latest version of Python as well as the latest version of Django and the latest Django LTS version.

Installation

First, install the django-health-check package:

$ pip install django-health-check

Add the health checker to a URL you want to use:

    urlpatterns = [
        # ...
        path(r'ht/', include('health_check.urls')),
    ]

Add the health_check applications to your INSTALLED_APPS:

    INSTALLED_APPS = [
        # ...
        'health_check',                             # required
        'health_check.db',                          # stock Django health checkers
        'health_check.cache',
        'health_check.storage',
        'health_check.contrib.migrations',
        'health_check.contrib.celery',              # requires celery
        'health_check.contrib.celery_ping',         # requires celery
        'health_check.contrib.psutil',              # disk and memory utilization; requires psutil
        'health_check.contrib.s3boto3_storage',     # requires boto3 and S3BotoStorage backend
        'health_check.contrib.rabbitmq',            # requires RabbitMQ broker
        'health_check.contrib.redis',               # requires Redis broker
    ]

Note: If using boto 2.x.x use health_check.contrib.s3boto_storage

(Optional) If using the psutil app, you can configure disk and memory threshold settings; otherwise below defaults are assumed. If you want to disable one of these checks, set its value to None.

    HEALTH_CHECK = {
        'DISK_USAGE_MAX': 90,  # percent
        'MEMORY_MIN': 100,    # in MB
    }

To use Health Check Subsets, Specify a subset name and associate it with the relevant health check services to utilize Health Check Subsets.

    HEALTH_CHECK = {
        # .....
        "SUBSETS": {
            "startup-probe": ["MigrationsHealthCheck", "DatabaseBackend"],
            "liveness-probe": ["DatabaseBackend"],
            "<SUBSET_NAME>": ["<Health_Check_Service_Name>"]
        },
        # .....
    }

To only execute specific subset of health check

curl -X GET -H "Accept: application/json" http://www.example.com/ht/startup-probe/

If using the DB check, run migrations:

$ django-admin migrate

To use the RabbitMQ healthcheck, please make sure that there is a variable named BROKER_URL on django.conf.settings with the required format to connect to your rabbit server. For example:

    BROKER_URL = "amqp://myuser:mypassword@localhost:5672/myvhost"

To use the Redis healthcheck, please make sure that there is a variable named REDIS_URL on django.conf.settings with the required format to connect to your redis server. For example:

    REDIS_URL = "redis://localhost:6370"

The cache healthcheck tries to write and read a specific key within the cache backend. It can be customized by setting HEALTHCHECK_CACHE_KEY to another value:

    HEALTHCHECK_CACHE_KEY = "custom_healthcheck_key"

Setting up monitoring

You can use tools like Pingdom, StatusCake or other uptime robots to monitor service status. The /ht/ endpoint will respond with an HTTP 200 if all checks passed and with an HTTP 500 if any of the tests failed. Getting machine-readable JSON reports

If you want machine-readable status reports you can request the /ht/ endpoint with the Accept HTTP header set to application/json or pass format=json as a query parameter.

The backend will return a JSON response:

    $ curl -v -X GET -H "Accept: application/json" http://www.example.com/ht/

    > GET /ht/ HTTP/1.1
    > Host: www.example.com
    > Accept: application/json
    >
    < HTTP/1.1 200 OK
    < Content-Type: application/json

    {
        "CacheBackend": "working",
        "DatabaseBackend": "working",
        "S3BotoStorageHealthCheck": "working"
    }

    $ curl -v -X GET http://www.example.com/ht/?format=json

    > GET /ht/?format=json HTTP/1.1
    > Host: www.example.com
    >
    < HTTP/1.1 200 OK
    < Content-Type: application/json

    {
        "CacheBackend": "working",
        "DatabaseBackend": "working",
        "S3BotoStorageHealthCheck": "working"
    }

Writing a custom health check

Writing a health check is quick and easy:

    from health_check.backends import BaseHealthCheckBackend

    class MyHealthCheckBackend(BaseHealthCheckBackend):
        #: The status endpoints will respond with a 200 status code
        #: even if the check errors.
        critical_service = False

        def check_status(self):
            # The test code goes here.
            # You can use `self.add_error` or
            # raise a `HealthCheckException`,
            # similar to Django's form validation.
            pass

        def identifier(self):
            return self.__class__.__name__  # Display name on the endpoint.

After writing a custom checker, register it in your app configuration:

    from django.apps import AppConfig

    from health_check.plugins import plugin_dir

    class MyAppConfig(AppConfig):
        name = 'my_app'

        def ready(self):
            from .backends import MyHealthCheckBackend
            plugin_dir.register(MyHealthCheckBackend)

Make sure the application you write the checker into is registered in your INSTALLED_APPS.

Customizing output

You can customize HTML or JSON rendering by inheriting from MainView in health_check.views and customizing the template_name, get, render_to_response and render_to_response_json properties:

    # views.py
    from health_check.views import MainView

    class HealthCheckCustomView(MainView):
        template_name = 'myapp/health_check_dashboard.html'  # customize the used templates

        def get(self, request, *args, **kwargs):
            plugins = []
            status = 200 # needs to be filled status you need
            # ...
            if 'application/json' in request.META.get('HTTP_ACCEPT', ''):
                return self.render_to_response_json(plugins, status)
            return self.render_to_response(plugins, status)

        def render_to_response(self, plugins, status):       # customize HTML output
            return HttpResponse('COOL' if status == 200 else 'SWEATY', status=status)

        def render_to_response_json(self, plugins, status):  # customize JSON output
            return JsonResponse(
                {str(p.identifier()): 'COOL' if status == 200 else 'SWEATY' for p in plugins},
                status=status
            )

    # urls.py
    import views

    urlpatterns = [
        # ...
        path(r'ht/', views.HealthCheckCustomView.as_view(), name='health_check_custom'),
    ]

Django command

You can run the Django command health_check to perform your health checks via the command line, or periodically with a cron, as follow:

    django-admin health_check

This should yield the following output:

    DatabaseHealthCheck      ... working
    CustomHealthCheck        ... unavailable: Something went wrong!

Similar to the http version, a critical error will cause the command to quit with the exit code 1.

Other resources

  • django-watchman is a package that does some of the same things in a slightly different way.

django-health-check's People

Contributors

aleksihakli avatar anushbmx avatar ashokdelphia avatar astraluma avatar codingjoe avatar courcelm avatar czpython avatar dependabot[bot] avatar dyve avatar ehmkah avatar flauschbaellchen avatar frankwiles avatar frankyjquintero avatar gableroux avatar hramezani avatar jairhenrique avatar jayh5 avatar jefftriplett avatar justinmayer avatar kristianoellegaard avatar maszaa avatar mnitchie avatar ojii avatar panteparak avatar pyup-bot avatar realorangeone avatar skarzi avatar sobolevn avatar stefanfoulis avatar toopy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-health-check's Issues

cannot import name autodiscover_modules

A legacy project with Django 1.6.3.

There is no such module in django.utils.module_loading?

Django Version: 1.6.3
Exception Type: ImportError
Exception Value:
cannot import name autodiscover_modules
Exception Location: /Users/tristanguo/workspace/python_envs/xxx/lib/python2.7/site-packages/health_check/init.py in autodiscover, line 20

Add ChangeLog to repo please

Going from 2.4.0 to 3.3.0 we have no clue what is changed. Please add a CHANGELOG.md to document changes between releases.

Celery backend

I'm getting the following error with the celery backend:

[2017-03-03 11:12:08,194: INFO/MainProcess] Discarding revoked task: health_check.contrib.celery.tasks.add[ac03c91f-c578-43d4-bf64-23f8ecdc0872]

Exception print: expired

Timeout for waiting Self.Chanel

Hi Kristian,

I am having this issue in the code below:
in the MainView get method:

            for plugin_class, options in plugin_dir._registry:
                plugin = plugin_class(**copy.deepcopy(options))
                try:
                    plugin.run_check()
                    plugins.append(plugin)
                    errors += plugin.errors
                except Exception as ex1:
                    return {}

In the for loop, when the plugin_class is the health_check.contrib.celery.backends.CeleryHealthCheck, I get the timeout exception in the messaging.py file line 187:

        channel = self.channel

It just occurs only when tthe plugin_class is the health_check.contrib.celery.backends.CeleryHealthCheck.

I have config celery==4.1.0.

Could you please take a look on it?

Thanks,
Thanh

Development status and assorted properties not defined in the PyPI page

Project PyPI page does not have a Development Status defined:

https://pypi.python.org/pypi/django-health-check

And it shows status as unknown in Django Packages:

https://djangopackages.org/packages/p/django-health-check/

I think the following trove classifiers could be added for the project to make it easier to find:

Development Status :: 5 - Production/Stable
Framework :: Django

Some of the following classifiers could also be useful:

Framework :: Django :: 1.8
Framework :: Django :: 1.9
Framework :: Django :: 1.10

Intended Audience :: Developers

License :: OSI Approved :: MIT License
License :: Public Domain

Operating System :: OS Independent

Topic :: System :: Logging
Topic :: System :: Monitoring
Topic :: Software Development :: Quality Assurance

DB migrations fail when upgrading to v1.2.0

Tested with

  • django 1.8.15
  • django-health-check 1.1.4 migrated to 1.2.0

Steps to reproduce

Install django 1.8.15 and django-health-check 1.1.4
Configure django-health-check
Migrate the database
Upgrade to django-health-check 1.2.0
Migrate the database and see that the migration fails

Work arounds

Fake the database migration

Install django 1.8.15 and django-health-check 1.1.4

$ mktmpenv     
$ pip install django==1.8.15 django-health-check==1.1.4 
$ pip freeze
Django==1.8.15
django-health-check==1.1.4

Configure django-health-check

$ django-admin startproject myproject                  
$ vim ./myproject/myproject/settings.py 
# Add 'health_check_*' to INSTALLED_APPS
$ vim ./myproject/myproject/urls.py
# Add '/healthcheck/' URLs.

Migrate the database

$ ./myproject/manage.py migrate
Operations to perform:
  Synchronize unmigrated apps: health_check, staticfiles, messages, health_check_storage, health_check_db, health_check_cache
  Apply all migrations: admin, contenttypes, auth, sessions
Synchronizing apps without migrations:
  Creating tables...
    Creating table health_check_db_testmodel
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying sessions.0001_initial... OK

Upgrade to django-health-check 1.2.0

$ pip install django==1.8.15 django-health-check==1.2.0

Migrate the database and see that the migration fails

$ ./myproject/manage.py migrate                        
Operations to perform:
  Synchronize unmigrated apps: staticfiles, health_check, messages, health_check_storage, health_check_cache
  Apply all migrations: admin, contenttypes, health_check_db, auth, sessions
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying health_check_db.0001_initial...Traceback (most recent call last):
  File "./myproject/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute_from_command_line
    utility.execute()
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 346, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/core/management/base.py", line 394, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/core/management/base.py", line 445, in execute
    output = self.handle(*args, **options)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 222, in handle
    executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 110, in migrate
    self.apply_migration(states[migration], migration, fake=fake, fake_initial=fake_initial)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 148, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/migrations/migration.py", line 115, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/migrations/operations/models.py", line 59, in database_forwards
    schema_editor.create_model(model)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 286, in create_model
    self.execute(sql, params or None)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 111, in execute
    cursor.execute(sql, params)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/utils.py", line 98, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 62, in execute
    return self.cursor.execute(sql)
  File "/home/christopherd/.virtualenvs/tmp-1bfff73823f1c428/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 316, in execute
    return Database.Cursor.execute(self, query)
django.db.utils.OperationalError: table "health_check_db_testmodel" already exists

Fake the database migration

$ ./myproject/manage.py migrate --list
admin
 [X] 0001_initial
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
health_check_db
 [ ] 0001_initial
sessions
 [X] 0001_initial
$ ./myproject/manage.py migrate health_check_db 0001 --fake
Operations to perform:
  Target specific migration: 0001_initial, from health_check_db
Running migrations:
  Rendering model states... DONE
  Applying health_check_db.0001_initial... FAKED
$ ./myproject/manage.py runserver  
Performing system checks...

System check identified no issues (0 silenced).
November 21, 2016 - 15:37:25
Django version 1.8.15, using settings 'myproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[21/Nov/2016 15:37:26] "GET /healthcheck HTTP/1.1" 301 0
[21/Nov/2016 15:37:26] "GET /healthcheck/ HTTP/1.1" 200 1516

GCP & 3.3.0 error

I'm quite confused regarding this bug, so it's difficult to report it.

When using django-health-check v3.0.0, I have no problem querying my docker container, whether locally (docker-compose) or on GCP kubernetes.

When upgrading django-health-check v3.3.0, I can still query /healthz locally (docker-compose & runserver), but my GCP environment breaks, returning 502 Bad gateway errors (kubectl & gunicorn/wsgi).

Django==2.0.1

Python==3.4.2 on kubernetes, 3.6.3 in local

Will try upgrading python on GCP to see whether this fixes the issue

Not compatible with explicit AppConfig

If an [exact AppConfig reference](https://docs.djangoproject.com/en/1.10/ref/applications/#for-application-users) is given in INSTALLED_APPS(instead of a package name),django-health-check` fails with:

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\management\__init__.py", line 367, in execute_from_command_line
    utility.execute()
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\management\__init__.py", line 359, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\management\base.py", line 294, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\management\base.py", line 342, in execute
    self.check()
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\management\base.py", line 374, in check
    include_deployment_checks=include_deployment_checks,
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\management\base.py", line 361, in _run_checks
    return checks.run_checks(**kwargs)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\checks\registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver
    for pattern in resolver.url_patterns:
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\utils\functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\urls\resolvers.py", line 313, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\utils\functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\urls\resolvers.py", line 306, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:\Users\James\AppData\Local\Programs\Python\Python35\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "C:\Users\James\code\innocence-envs\innocence\urls.py", line 24, in <module>
    url(r'^health/', include('health_check.urls')),
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\django\conf\urls\__init__.py", line 50, in include
    urlconf_module = import_module(urlconf_module)
  File "C:\Users\James\AppData\Local\Programs\Python\Python35\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\health_check\urls.py", line 6, in <module>
    health_check.autodiscover()
  File "C:\Users\James\.virtualenvs\innocence-envs\lib\site-packages\health_check\__init__.py", line 25, in autodiscover
    mod = import_module(app)
  File "C:\Users\James\AppData\Local\Programs\Python\Python35\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 953, in _find_and_load_unlocked
ImportError: No module named 'django.contrib.admin.apps.SimpleAdminConfig'; 'django.contrib.admin.apps' is not a package

Project updates

Hi,

I was planning on contributing the following updates to the project:

  • Rewrite the bundled storage backend to internally provide and use check_save and check_delete methods that could be overridden per storage backend instead of overriding the whole check_status backend. This would not be a breaking change and would
  • Add a bundled S3 storage backend checker for AWS health checking compatibility, for example health_check_storage_s3, which utilizes the S3BotoStorage interface from the django-storages. This is a very widely used package in AWS and Heroku which would be nice to support here as well. It is officially recommended by Heroku;
  • Upgrade README from Markdown to reStructuredText for PyPI documentation compatibility (this is the preferred format for Python packages and is supported by GitHub and many other VCS services out-of-the-box.

I thought to ask about the plan before starting the work as to avoid unnecessary changes that could be rejected in PRs.

No Migrations

No migrations are packaged with django-health-check. This renders health_check_db useless under modern Django.

Please run manage.py makemigrations.

Problems with Django 1.6

This line completely breaks compatibiliy with Django 1.6 (yes, we are still using it in some of our projects). I know it is easy to fix, but it is up to you decide whether you want to main compatibility.
But even after manually replacing that JsonResponse with a proper HttpResponse in source code, all json-requests to ^ht/ always return {} (used the same settings described in README). And actually that's my main concern.
Btw the older version 1.3 also doesn't work with Django 1.6 due to the line from django.utils.module_loading import autodiscover_modules (though Django 1.4+ was stated in Dependencies).

Add timer and elapsed time to checks

We are adopting django-health-check as our base health check helper and one thing we had in our custom health checks was showing the elapsed time. For example:

from contexttimer import Timer
from api.models import City

def health_check_view(request):
    with Timer() as timer_db:
        City.objects.first()
    response = "ok; db: {}".format(timer_db.elapsed)
    return HttpResponse(response)

I am planning to put this in django-health-check but you do not have any package dependency. Will you accept the feature even if it forces a dependency?
https://pypi.python.org/pypi/contexttimer/0.3.3

Tests?

Given the critical nature of this sort of application, it would be really nice if there were tests that this actually works, which are run in a CI server (see #23).

Green indicators are not working

So, I just noticed that in my template working checks result as status_True instead of status_1.

Unavailable checks result as status_0 as they should.

Is this just me or is anyone else experiencing the same issue?

log exceptions

To make actually debugging an error easier, it would be nice if the error could be logged using standard logging. This would be an alternative approach to #10 .
The "status" could also include the very short version of the exception (or just the Exception class) as information instead of just "unavailable".

Django system check warning on URL route entry

The current README suggests the following urls.py entry:

url(r'^ht/$', include('health_check.urls')),

However, running django-admin check then yields:

System check identified some issues:

WARNINGS:
?: (urls.W001) Your URL pattern '^ht/$' uses include with a regex ending with a '$'. Remove the dollar from the regex to avoid problems including URLs.

Removing the dollar sign caused the warning to go away, with no apparent ill effects regarding django-health-check app functionality.

Installation steps

My django project may be nonstandard hence my troubles.

I have made the following changes

# projectName/core/foo/internal/views.py
+import health_check.backends.base

fooViewSet(projectName.common.internal.views.ModelViewSet):
             instance.fail()
             instance.save()
         return self.instance_to_json(request, instance)
+
+class CustomTest(health_check.backends.base.BaseHealthCheckBackend):
+    def check_status(self):
+        try:
+            my_model = projectName.core.foo.models.Foo.objects.create(
+                source=projectName.core.foo.models.Foo.CONST,
+            )
+            my_model.save()
+            my_model.delete()
+            return True
+        except IntegrityError:
+            raise ServiceReturnedUnexpectedResult("Integrity Error")
+        except DatabaseError:
+            raise ServiceUnavailable("Database error")
+
+django.contrib.admin.site.register(CustomTest)
# projectName/core/urls.py
 import django.conf.urls
 
+import health_check

...

 internal_urls = [
+    django.conf.urls.url(r'^ht/', django.conf.urls.include(health_check.urls)),
 ]

urlpatterns = [
    django.conf.urls.url(r'^internal/', django.conf.urls.include(internal_urls, namespace='core_internal')),
]
# /config/settings/__default__.py b/config/settings/__default__.py
INSTALLED_APPS = [
+    'health_check',
+    'health_check_celery3',
+    'health_check_db',
+    'health_check_cache',
+    'health_check_storage',
]
# requirements.txt
+django-health-check==1.3.0

I get the error

Traceback (most recent call last):
          File "manage.py", line 17, in <module>
              execute_from_command_line(sys.argv)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
              utility.execute()
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/management/__init__.py", line 345, in execute
              self.fetch_command(subcommand).run_from_argv(self.argv)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/management/base.py", line 348, in run_from_argv
              self.execute(*args, **cmd_options)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/management/base.py", line 398, in execute
              self.check()
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/management/base.py", line 426, in check
              include_deployment_checks=include_deployment_checks,
                File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/checks/registry.py", line 75, in run_checks
              new_errors = check(app_configs=app_configs)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/checks/urls.py", line 13, in check_url_config
              return check_resolver(resolver)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/checks/urls.py", line 23, in check_resolver
              for pattern in resolver.url_patterns:
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/utils/functional.py", line 33, in __get__
              res = instance.__dict__[self.name] = self.func(instance)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/urlresolvers.py", line 417, in url_patterns
              patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/utils/functional.py", line 33, in __get__
              res = instance.__dict__[self.name] = self.func(instance)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/core/urlresolvers.py", line 410, in urlconf_module
              return import_module(self.urlconf_name)
            File "/opt/foo/.pyenv/versions/2.7.11/lib/python2.7/importlib/__init__.py", line 37, in import_module
              __import__(name)
            File "/Users/harry/programming/project/foo/urls.py", line 7, in <module>
              import foo.core.urls
            File "/Users/harry/programming/project/foo/core/urls.py", line 13, in <module>
              import foo.core.modelName.internal.views
            File "/Users/harry/programming/project/foo/core/modelName/internal/views.py", line 176, in <module>
              django.contrib.admin.site.register(HealthCheckModelLookup)
            File "/Users/harry/programming/project/env/project/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 86, in register
              for model in model_or_iterable:
          TypeError: 'type' object is not iterable

healthcheck db required write permission?

Hello,
I have RDS with only read permission and i am checking health-check db and i found my status was failed .so health-check db required the write permission?

Storage base check_status returns errors instead of raising them

In health_check_storage.base.check_status in two of the if statements, the code returns an error instead of raising it. Therefore if the file contents are not equal to what is read, or if it is improperly deleted, the status of the plugin will be set to ServiceUnavailable(msg), rather than its numbered error code. The error is then raised when pretty_status attempts to to translate the ServiceUnavailable error into one of the three default messages.

Replace 'return' with 'raise' and the problem should be fixed.

Getting exception

Hi,
I am implementing health check for my project and it work absolute fine until when i try to enable cache in my project.

I tried all possible way from my side but couldn't able to figure out.

Please help .

Urls :

urlpatterns = patterns(
url(r'^api/health/$', include('health_check.urls'))
)

Settings: config

INSTALLED_APPS =[
'health_check',  # required
    'health_check.db',  # stock Django health checkers
    'health_check.contrib.rmq',
    'health_check.cache'
]
HEALTH_CHECK_CONF = dict(rmq_host=BROKER_URL, sqs_queue_name='queue_name', region_name='eu-west-1',
                         aws_secret_access_key='mykey', aws_access_key_id='access_id',
                         soft_dependencies=[CACHES]
                         )

===========

 Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/neeraj/virtualenv/python2/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "/Users/neeraj/virtualenv/python2/lib/python2.7/site-packages/django/core/management/__init__.py", line 312, in execute
    django.setup()
  File "/Users/neeraj/virtualenv/python2/lib/python2.7/site-packages/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/Users/neeraj/virtualenv/python2/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate
    app_config = AppConfig.create(entry)
  File "/Users/neeraj/virtualenv/python2/lib/python2.7/site-packages/django/apps/config.py", line 119, in create
    import_module(entry)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
ImportError: No module named cacherest_framework

==========

Regards,
Neeraj

health_check.db in 3.3.0: FATAL: connection limit exceeded for non-superusers

The latest release (3.3.0) is having an issue for the health_check.db in 3.3.0. The database connections (Postgres in my case) are piling up every time the check is run. The issue is not found in 2.2.1 to 3.2.0.

I guess it is related to this new feature: "Use futures and parallel execution to improve performance"

Dependancy missing

Python 2.7, Django 1.11 and django-health-check 3.3.0 crash on a missing dependency:

File "/Users/dylan/.pyenv/versions/meetnetten/lib/python2.7/site-packages/health_check/views.py", line 2, in <module>
    from concurrent.futures import ThreadPoolExecutor
ImportError: No module named concurrent.futures

Reverting to 2.4.0 resolves this error for now.

Use get() instead of polling for celery health check

Hey
I'd like to refactor the celery health check to remove the self implemented polling of the result and instead use result.get(). This way we wouldn't be using polling for the rabbitmq,redis,memcached backends. Also we could use the timeout parameter of get() so we get the celery.exceptions.TimeoutError of celery.
Does anyone see a problem with this?

notify admin on 500

Would you accept a PR for implementing a custom setting (via a settings.py that reads from the project) to notify admins of 500s?
If True, and maybe some other fine-tuned details, the admin/people/endpoint will get notified of an error, and by default/False, they won't.

I realize monitoring and bot services can do this for us, but in the case of not using those services, it may be nice to have the option for a built-in version.

Hourly checks from 8:00 to 18:00

I am interested in your project.

I am looking for a django application that lets my specify things like:

  • do check foo monday to friday hourly between 8:00 and 18:00.

The times and checks need to be configurable via admin (storing the values in db is preferred).

Is this possible with django-health-check?

DefaultFileStorageHealthCheck fails if backend is Amazon S3

If the backend storage is Amazon S3, the health check fails when it tries to check existence of the deleted test file.

            storage.delete(file_name)
            if storage.exists(file_name):
                return ServiceUnavailable("File was not deleted")

https://github.com/KristianOellegaard/django-health-check/blob/master/health_check_storage/base.py#L50-L52

The issue is that it take moment for S3 to actually delete the file and therefore the health check fails because the file still exists. It gets to the exists() before S3 actually can delete the file because delete() on S3 is asynchronous (whereas the save() is synchronous because we wait for a file name).

I solved this was sub-classing and not checking if the file was deleted but this isn't an ideal solution. I'd submit a PR if you have a suggestion on how you'd like to fix it. I'd be fine with adding at setting:

HEALTH_CHECK_STORAGE_DISABLE_DELETE_EXISTS = True

Django 1.10 support

Hello - Django 1.10 is on beta now. I'd be happy to add support via a pull request if you would like. Right now we get these warnings in 1.9

/usr/local/lib/python3.5/site-packages/health_check/urls.py:8: RemovedInDjango110Warning: Support for string view arguments to url() is deprecated and will be removed in Django 1.10 (got health_check.views.home). Pass the callable instead.
  url(r'^$', 'health_check.views.home', name='health_check_home'),
/usr/local/lib/python3.5/site-packages/health_check/urls.py:8: RemovedInDjango110Warning: Support for string view arguments to url() is deprecated and will be removed in Django 1.10 (got health_check.views.home). Pass the callable instead.

Should be trivial to fix.

getting an exception error

seems like base.py in the file storage app is throwing an exception error that the health check module can't handle so i'm getting an error page instead of the status page.

see error message

Environment:

Request Method: GET

Django Version: 1.5.1
Python Version: 2.7.3
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'grappelli',
'django.contrib.admin',
'django.contrib.admindocs',
'south',
'project',
'django_nose',
'gravatar',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.github',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.twitter',
'django_mailgun',
'djcelery',
'json_field',
'health_check',
'health_check_celery',
'health_check_db',
'health_check_cache',
'health_check_storage')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')

Template error:
In template /home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/health_check/templates/health_check/dashboard.html, error at line 57
Unknown exception

57 : {{ plugin.pretty_status }}

Traceback:
File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response

  1.                     response = callback(request, _callback_args, *_callback_kwargs)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/health_check/views.py" in home
  2.     return HttpResponseServerError(loader.render_to_string("health_check/dashboard.html", {'plugins': plugins}))
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/loader.py" in render_to_string
  3.     return t.render(Context(dictionary))
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/base.py" in render
  4.         return self._render(context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/base.py" in _render
  5.     return self.nodelist.render(context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/base.py" in render
  6.             bit = self.render_node(node, context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/debug.py" in render_node
  7.         return node.render(context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  8.                     nodelist.append(node.render(context))
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/debug.py" in render
  9.         output = self.filter_expression.resolve(context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/base.py" in resolve
  10.             obj = self.var.resolve(context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/base.py" in resolve
  11.         value = self._resolve_lookup(context)
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/django/template/base.py" in _resolve_lookup
  12.                         current = current()
    
    File "/home/ubuntu/projects/simpletest/local/lib/python2.7/site-packages/health_check/backends/base.py" in pretty_status
  13.     return u"%s" % (HEALTH_CHECK_STATUS_TYPE_TRANSLATOR[self.status])
    

Exception Type: KeyError at /ht/
Exception Value: ServiceUnavailable('Unknown exception',)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.