Pull to refresh

ELK Stack для хранения логов Django приложения

Reading time3 min
Views33K

Каждый из проектов, который перерастает этап прототипа, нуждается в организации логирования. Грамотное логирования решает уйму проблем и помогает понять состояние проекта. На начальном этапе логирование в файл меня устраивало пока проект не разросся и поиск по логам не начал отнимать время.


Решением было создание централизованного лог хранилища с агрегацией логов и поиском. Выбор пал на ELK стек. ELK — сочетание трех OpenSource проектов: ElasticSearch, Logstash и Kibana. ELK хранит логи, строит графики и есть поддержка полнотекстового поиска с фильтрами. В статье описывается процесс настройки ELK стека для хранения логов Django приложения.


Установка ELK


Для установки ELK стека будет использоваться Docker, за основу взят репозиторий docker-elk. Изменим настройку Logstash-а, добавим GROK паттерн для матчинга nginx логов и изменим output секцию, чтобы логи Django приложения и nginx логи сохранялись в разных индексах ElasticSearch-а. В итоге logstash.conf выглядит так:


input {  
  beats {
    port => 5000
    host => "0.0.0.0"
  }
}
filter {
   if [type] == "nginx" {
     grok {
        match => { "message" => "%{IPORHOST:remote_ip} - %{DATA:user_name} \[%{HTTPDATE:access_time}\] \"%{WORD:http_method} %{DATA:url} HTTP/%{NUMBER:http_version}\" %{NUMBER:response_code} %{NUMBER:body_sent_bytes} \"%{DATA:referrer}\" \"%{DATA:agent}\"" }
      }
   }
}
output {
    if [type] == "nginx" {
        elasticsearch {
            hosts     => "elasticsearch:9200"
            index    => "nginx-%{+YYYY.MM.dd}"
        }
    }
    else if [type] == "django" {
        elasticsearch {
            hosts     => "elasticsearch:9200"
            index    => "django-%{+YYYY.MM.dd}"
        }
    }
    else {
        elasticsearch {
            hosts     => "elasticsearch:9200"
            index    => "unknown_messages"
        }
    }
}

После внесения изменений запускаем стек:


docker-compose up

После запуска стек слушает следующее порты:


  • 5000: Logstash TCP input.
  • 9200: Elasticsearch HTTP
  • 9300: Elasticsearch TCP transport
  • 5601: Kibana

Архитектура логирования


Рассмотрим архитектуру логирования Django приложения.


image


Как видно из схемы, приложение состоит из сервисов: nginx, django application, celery worker. Каждый из сервисов отправлял логи в ELK стек. Рассмотрим настройку каждого сервиса по отдельности.


Запись Nginx логов в ELK


Для работы с nginx логами потребуется дополнительный сервис Filebeat. Процесс установки Filebeat детально описан на официальном сайте. Пример установки Filebeat сервиса на Ubuntu сервер:


curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-6.4.0-amd64.deb
sudo dpkg -i filebeat-6.4.0-amd64.deb

Filebeat будет читать логи из файла и отправлять в Logstash. Пример конфигурации:


filebeat.inputs:
- type: log
  enabled: true
  paths:
      - /var/log/nginx/access.log
  fields:
    type: nginx
  fields_under_root: true
  scan_frequency: 5s

output.logstash:
  hosts: ["logstash:5000"]

Запускаем наш Filebeat сервис и наблюдаем за появлением логов в Kibana.


Запись Django логов в ELK


Для взаимодействия Django с сервисом Logstash установите дополнительный пакет Python-logstash.


pip install python-logstash

Изменим настройки Django приложения, чтобы логи отправлялись в Logstash сервис.


LOGGING = {
  'version': 1,
  'disable_existing_loggers': False,
  'formatters': {
      'simple': {
            'format': 'velname)s %(message)s'
        },
  },
  'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'logstash': {
            'level': 'INFO',
            'class': 'logstash.TCPLogstashHandler',
            'host': 'logstash',
            'port': 5000, 
            'version': 1,
            'message_type': 'django',  # 'type' поле для logstash сообщения.
            'fqdn': False,
            'tags': ['django'], # список тег.
        },
  },
  'loggers': {
        'django.request': {
            'handlers': ['logstash'],
            'level': 'INFO',
            'propagate': True,
        },
        ...
    }
}

После этого приложение будет отправлять логи в Logstash. Пример использования:


import logging

logger = logging.getLogger(__name__)

def test_view(request, arg1, arg):
    ...
    if is_error:
        # Отправляем лог сообщение
        logger.error('Something went wrong!')

После этого настройте Kibana под себя, чтобы отображать необходимую информацию. Пример скриншотов собственной настройки:


image
image
image


Система собирает логи сервисов, позволяет по ним удобно искать, строить графики и визуализации, позволяя в кратчайшие сроки обнаружить и исправлять проблемы.

Tags:
Hubs:
Total votes 12: ↑12 and ↓0+12
Comments3

Articles