Мониторинг¶
Настройка журналирования¶
Настройка библиотеки производится через переменные окружения. Переменные окружения имеют префикс LOG_. Переменные окружения для включения-выключения функций имеют значение 1 или 0. На данный момент доступны следующие настройки:
Переменная окружения | Назначение | Значение по умолчанию |
---|---|---|
LOG_MESSAGE_FORMAT | Формат логирования пользовательских записей | {time} {level} {message} |
LOG_RESPONSE_FORMAT | Формат логирования http ответа | {time} {http_code} {local_request_id} {level} {url} {data} {message} |
LOG_REQUEST_FORMAT | Формат логирования http запроса | {time} {local_request_id} {level} {user_uuid} {method} {url} {data} {message} |
LOG_REMOVE_COOKIES | Удаление куки из лога | 1 |
LOG_SKIP_LOGGING_ENDPOINTS | Список эндпоинтов, которые не нужно логировать, через запятую | [] |
LOG_SKIP_LOGGING_CONTENT_TYPES | Список типов контента, которые не нужно логировать, через запятую | [] |
LOG_RESPONSE_BODY | Логирование тела ответа | 0 |
LOG_REQUEST_BODY | Логирование тела запроса | 1 |
LOG_REQUEST_USER | Логирование пользователя (только Django) | 1 |
LOG_REQUEST_METHOD | Логирование метода запроса | 1 |
LOG_RESPONSE_STATUS_CODE | Логирование кода ответа | 1 |
LOG_RESPONSE_HEADERS | Логирование заголовков ответа | 1 |
LOG_REQUEST_HEADERS | Логирование заголовков запроса | 1 |
LOG_REQUEST_URL_PATH | Логирование URL-адреса запроса (PATH) | 1 |
LOG_SQL_LOGGING | Логирование SQL-запросов. Работает только совместно с DEBUG=True | 0 |
LOG_JSON_LOGGING | JSON-формат логов | 0 |
Формат журналирования запроса и ответа
Форма сообщений HTTP-запроса и ответа задается переменными окружения LOG_REQUEST_FORMAT и LOG_RESPONSE_FORMAT соответственно.
Пример:
LOG_REQUEST_FORMAT='{time} {local_request_id} {level} {user_uuid} {method} {url} {data} {message}' LOG_RESPONSE_FORMAT='{time} {http_code} {local_request_id} {level} {url} {data} {message}'
Общие для LOG_REQUEST_FORMAT и LOG_RESPONSE_FORMAT
Ключ | Описание |
---|---|
elapsed | Примерное время выполнения запроса |
file | Имя файла, из которого пишется сообщение |
function | Имя функции, из которой пишется сообщение |
level | Уровень логирования |
line | Номер строки, из которой пишется сообщение |
message | Сообщение |
module | Модуль, из которого пишется сообщение |
name | Ключ name модуля, из которого пишется сообщение |
process | Процесс |
thread | Поток |
time | Временная метка |
local_request_id | Локальный идентификатор запроса и ответа |
headers | Заголовки HTTP-пакета |
url | URL-ардес запроса |
data | Полезная нагрузка HTTP-пакета |
Специфичные для LOG_REQUEST_FORMAT
Ключ | Описание |
---|---|
user_uuid | Идентификатор пользователя |
method | HTTP-метод (GET/POST/PUT/и т.д.) |
Специфичные для LOG_RESPONSE_FORMAT
Ключ | Описание |
---|---|
http_code | HTTP-код ответа |
Примеры логов¶
Стандартный, при значениях переменных окружения¶
LOG_REQUEST_FORMAT='{time} {local_request_id} {level} {user_uuid} {method} {url} {data} {message}'
LOG_RESPONSE_FORMAT='{time} {http_code} {local_request_id} {level} {url} {data} {message}'
Пример:
2023-10-11 12:11:34.557 2023-10-11T09:11:34.556661+0000 200 4b5d1c29-6fb0-495b-a8e3-7e92440f4752 INFO /api/comments/internal/comment/count/newsentry/ RESPONSE
2023-10-11 12:11:34.548|2023-10-11T09:11:34.547514+0000 4b5d1c29-6fb0-495b-a8e3-7e92440f4752 INFO None GET /api/comments/internal/comment/count/newsentry/ REQUEST
2023-10-11 12:11:34.218|2023-10-11T09:11:34.218558+0000 200 f9577935-2e3c-46d1-b5b1-f585efa2562e INFO /api/comments/internal/comment/count/entry/ RESPONSE
2023-10-11 12:11:34.206|2023-10-11T09:11:34.205082+0000 f9577935-2e3c-46d1-b5b1-f585efa2562e INFO None GET /api/comments/internal/comment/count/entry/ REQUEST
JSON-формата при установленной переменной окружения LOG_JSON_LOGGING=1¶
{
"time": "2023-10-11 12:14:57.788005+03:00",
"elapsed": "0:00:10.732528",
"level": "INFO",
"message": {
"request_id": "0263e10e-2a7e-4392-a7f7-819a93eea353",
"request_url": "\/",
"http_headers": {
"host": "127.0.0.1:8000",
"sec-fetch-site": "none",
"connection": "keep-alive",
"upgrade-insecure-requests": "1",
"sec-fetch-mode": "navigate",
"accept": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8",
"user-agent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit\/605.1.15 (KHTML, like Gecko) Version\/17.0 Safari\/605.1.15",
"accept-language": "ru",
"sec-fetch-dest": "document",
"accept-encoding": "gzip, deflate",
"x_request_id": "0263e10e-2a7e-4392-a7f7-819a93eea353"
},
"http_body": "",
"method": "GET",
"user": {
"id": "41757af9-2c40-4e26-90fb-03a40d90ce3b",
"is_superuser": true,
"username": "None"
}
},
"file": "ph_logging.models:97"
}{
"time": "2023-10-11 12:14:57.788982+03:00",
"elapsed": "0:00:10.733505",
"level": "INFO",
"message": {
"request_id": "0263e10e-2a7e-4392-a7f7-819a93eea353",
"request_url": "\/",
"http_headers": {
"content-length": "22",
"content-type": "application\/json"
},
"http_body": "{\"detail\":\"Not Found\"}",
"http_code": 404
},
"file": "ph_logging.models:138"
}
{
"time": "2023-10-11 12:14:57.837834+03:00",
"elapsed": "0:00:10.782357",
"level": "INFO",
"message": {
"request_id": "e455f0c3-2d44-4dc6-8f96-e850f25dfc75",
"request_url": "\/favicon.ico",
"http_headers": {
"host": "127.0.0.1:8000",
"sec-fetch-site": "same-origin",
"accept-encoding": "gzip, deflate",
"connection": "keep-alive",
"sec-fetch-mode": "no-cors",
"accept": "*\/*",
"user-agent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit\/605.1.15 (KHTML, like Gecko) Version\/17.0 Safari\/605.1.15",
"referer": "http:\/\/127.0.0.1:8000\/",
"sec-fetch-dest": "image",
"accept-language": "ru",
"x_request_id": "e455f0c3-2d44-4dc6-8f96-e850f25dfc75"
},
"http_body": "",
"method": "GET",
"user": {
"id": "88c7c226-3d05-4b93-a878-87c3c61d081e",
"is_superuser": true,
"username": "None"
}
},
"file": "ph_logging.models:97"
}{
"time": "2023-10-11 12:14:57.838680+03:00",
"elapsed": "0:00:10.783203",
"level": "INFO",
"message": {
"request_id": "e455f0c3-2d44-4dc6-8f96-e850f25dfc75",
"request_url": "\/favicon.ico",
"http_headers": {
"content-length": "22",
"content-type": "application\/json"
},
"http_body": "{\"detail\":\"Not Found\"}",
"http_code": 404
},
"file": "ph_logging.models:138"
}
Установка¶
Django¶
Добаьте middleware:
MIDDLEWARE = [
...
'ph_logging.middlewares.django_middleware.DjangoLoggingMiddleware',
...
]
from ph_logging import logging_config
LOGGING = None
logging_config.configure_loguru_logger(echo_settings=True) # для вывода текущих настроек
logging_config.add_skip_endpoints([
STATIC_URL,
f"/{API_BASE_URL}swagger/",
f"/{API_BASE_URL}admin/",
f"/{API_BASE_URL}media/",
f"/{API_BASE_URL}redoc/",
f"/{API_BASE_URL}internal/prometheus/metrics",
f"/{API_BASE_URL}diagnostic/",
])
Для логирования SQL-запросов добавьте в настройки:
DATABASES = {
'default': {
'ENGINE': 'ph_logging.django_db_engine.postgres',
...
}
}
FastAPI¶
Добавьте middleware:
from ph_logging.middlewares.fastapi_middleware import FastApiLoggingMiddleware
app.add_middleware(FastApiLoggingMiddleware)
Настройте логирование SQL-запросов:
from ph_logging.logging_config import LoguruHandler, LOG_SQL_LOGGING
import logging
logging.getLogger('sqlalchemy.engine').addHandler(LoguruHandler())
engine = create_async_engine(
...
echo=LOG_SQL_LOGGING,
)
Информация для разработчика¶
Свойство headers для Django response добавили только в версии Django 3.2. Для совместимости с более ранними версиями пришлось сооружать такую конструкцию.
Запуск тестов¶
- Установите переменные окружения:
export DJANGO_SETTINGS_MODULE=tests.django_settings; export LOG_SKIP_LOGGING_CONTENT_TYPES=application/xml,image/jpeg; export LOG_SKIP_LOGGING_ENDPOINTS=/skip_url/,/skip_url2/; export LOG_RESPONSE_BODY=1
- Выполните команду:
python3 -m pytest -v -s tests/
Наблюдение за состоянием сервисов¶
Наблюдение за состоянием сервисов доступно на портале пользователю с правами Администратор системы (superuser).
Список зависимостей (dependencies) каждого сервиса может меняться в зависимости от инфраструктуры компании. У каждого сервиса обязательно будут указаны следующие параметры — URL, host, name и is available.
Параметр is available показывает доступен ли данный сервис в данный момент времени. При недоступности сервиса — он помечен соответствующей пометкой в разделе Панель администратора → Состояние портала.
Если при наблюдении за состоянием сервиса какой-либо из них оказывается недоступным, необходимо обращаться в техподдержку или инженеру по внедрению продукта.
Ниже указан список сервисов продукта, наблюдение за состоянием которых доступно пользователю с правами Администратор системы (superuser):
- Сервис asyncblogs.
- Сервис blogs.
- Сервис calendar.
- Сервис CMS.
- Сервис comments.
- Сервис events.
- Сервис gamifications.
- Сервис groups.
- Сервис meetings.
- Сервис news.
- Сервис polls.
- Сервис profile.
- Сервис settings.
- Сервис tasks.
- Сервис pages.
- Сервис notifications.
- Сервис filestorage.
- Сервис dictionaries.