Перейти к содержанию

Мониторинг

Настройка журналирования

Настройка библиотеки производится через переменные окружения. Переменные окружения имеют префикс 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

  1. Добаьте middleware:
MIDDLEWARE = [
    ...
    'ph_logging.middlewares.django_middleware.DjangoLoggingMiddleware',
    ...
]
  1. Настройте библиотеку:
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/",
])
  1. Для логирования SQL-запросов добавьте в настройки:
DATABASES = {
    'default': {
        'ENGINE': 'ph_logging.django_db_engine.postgres',
        ...
    }
}

FastAPI

  1. Добавьте middleware:
from ph_logging.middlewares.fastapi_middleware import FastApiLoggingMiddleware
app.add_middleware(FastApiLoggingMiddleware)
  1. Настройте логирование 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,
)

Запуск тестов

  1. Установите переменные окружения:
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
  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.