Мониторинг¶
Настройка журналирования¶
Настройка библиотеки производится через переменные окружения. Переменные окружения имеют префикс LOG_. Переменные окружения для включения-выключения функций имеют значение 1 или 0.
На данный момент доступны следующие настройки:
Переменная окружения | Назначение | Значение по умолчанию |
---|---|---|
LOG_REQUEST_BODY | Логирование тела запроса | 0 |
LOG_REQUEST_HEADERS | Логирование заголовков запроса | 1 |
LOG_REQUEST_URL_PATH | Логирование URL-адреса запроса (PATH) | 1 |
LOG_REQUEST_METHOD | Логирование метода запроса | 1 |
LOG_REQUEST_USER | Логирование пользователя (только Django) | 1 |
LOG_RESPONSE_BODY | Логирование тела ответа | 0 |
LOG_RESPONSE_HEADERS | Логирование заголовков ответа | 1 |
LOG_RESPONSE_STATUS_CODE | Логирование кода ответа | 1 |
LOG_REMOVE_COOKIES | Удаление cookie из лога | 1 |
LOG_SKIP_LOGGING_ENDPOINTS | Список endpoint, которые не нужно логировать. Указать через запятую | api/base_url,api/base_url2 |
LOG_SKIP_LOGGING_CONTENT_TYPES | Список типов контента, которые не нужно логировать. Указать через запятую | [] |
LOG_SQL_LOGGING | Логирование SQL-запросов. Работает только совместно с DEBUG=True | 0 |
LOG_JSON_LOGGING | JSON-формат логов | 0 |
LOG_REQUEST_FORMAT | Формат логирования HTTP-запроса | {time} {local_request_id} {level} {user_uuid} {method} {url} {data} {message} |
LOG_RESPONSE_FORMAT | Формат логирования HTTP-ответа | {time} {http_code} {local_request_id} {level} {url} {data} {message} |
LOG_MESSAGE_FORMAT | Формат логирования пользовательских записей | {time} {level} {message} |
Формат журналирования запроса и ответа¶
Форма сообщений 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"
}
Логгер аудита¶
Список событий, которые обрабатывает логгер аудита:
- SOCIAL-LINK - учетная запись соединена с провайдером социальных сетей;
- REMOVE-SOCIAL-LINK - связь с аккаунтом социальных сетей удалена;
- UPDATE-PROFILE - профиль учетной записи изменился;
- PROFILE_REQUEST - запрос по public api в сервис профилей;
- GROUPS_REQUEST - запрос по public api в сервис оргструктуры;
- DICTIONARIES_REQUEST - запрос по public api в сервис справочникой.
Когда происходит бизнесовый сценарий, например, пользователь добавил в профиль новую ссылку на социальную сеть, дополнительно к обычным логам, запись дублируется в логгер аудита.
Также дополнительно логируются в логгер аудита запросы в public api.
Формат журналирования логгера аудита¶
Идентификатор логгера аудита - AUDIT.
LOG_FORMAT = '{audit_indicator} {time} {level} {user_uuid} {event_type}'
Пример:
AUDIT 2024-05-02T20:11:09.349092+0000 INFO 4f107436-ada9-4134-af4f-77b6e81921d7 UPDATE-PROFILE
AUDIT 2024-05-02T20:38:44.921232+0000 INFO 4f107436-ada9-4134-af4f-77b6e81921d7 PROFILE_REQUEST
Пример использования в коде логгера аудита¶
from ph_logging import audit_loger
...
# в нужную часть кода необходимо добавить логирование в лог аудита
audit_loger.info(AUDIT_EVENTS.SOCIAL_LINK, user_uuid=instance.user.id)
Установка¶
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,
)
Запуск тестов¶
- Установите переменные окружения:
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;
- сервис calendar;
- сервис cms;
- сервис comments;
- сервис dictionaries;
- сервис events;
- сервис filestorage;
- сервис gamification;
- сервис groups;
- сервис ideas;
- сервис meetings;
- сервис news;
- сервис notifications;
- сервис pages;
- сервис polls;
- сервис profile;
- сервис settings;
- сервис tasks;
- сервис timelines.