Мониторинг Python приложений с помощью Proto Observability Platform

Подключение трейсинга и сбора метрик для Python приложений.

На этой странице:

Введение

Общий процесс подключения Python приложения на мониторинг:

  1. Установка ProtoOBP Агента
  2. Установка трейсера

Установка Python трейсера

  1. Установите библиотеку pobptrace выполнив:

    pip install pobptrace --user --index-url "https://<token_name>:<token_key>@git.proto.group/api/v4/projects/125/packages/pypi/simple"
    

    Пример для Dockerfile и .gitlab-ci.yml:

    • в настройках проекта в Gitlab добавьте две переменные окружения (Проект -> Settings -> CI/CD -> Variables):

      • имя: PROTOOBP_INSTALL_TOKEN_NAME, значение = ваши данные из лицензионного сертификата (token или логин)
      • имя: PROTOOBP_INSTALL_TOKEN_KEY, значение = ваши данные из лицензионного сертификата (пароль)

    Имя и значение токена находятся в вашем лицензионном сертификате Proto Observability Platform.

    • .gitlab-ci.yml – необходимо передать значения переменных от Gitlab CI к docker build через --build-arg:

        script:
          - docker build --build-arg PROTOOBP_INSTALL_TOKEN_NAME=${PROTOOBP_INSTALL_TOKEN_NAME} --build-arg PROTOOBP_INSTALL_TOKEN_KEY=${PROTOOBP_INSTALL_TOKEN_KEY} .
      
    • Dockerfile – необходимо добавить переменные окружения через ARG и передать их в pip install --index-url:

      FROM python:latest
      ARG PROTOOBP_INSTALL_TOKEN_NAME
      ARG PROTOOBP_INSTALL_TOKEN_KEY
      RUN pip install pobptrace --user --index-url "https://${PROTOOBP_INSTALL_TOKEN_NAME}:${PROTOOBP_INSTALL_TOKEN_KEY}@git.proto.group/api/v4/projects/125/packages/pypi/simple"
      
  2. Добавьте pobptrace-run команду как entrypoint вашего приложения. Например:

    pobptrace-run python app.py
    
    • Пример для типового Python приложения:

      CMD ["pobptrace-run", "python", "app.py"]
      
    • Пример для uwsgi и Dockerfile:

      CMD ["pobptrace-run", "uwsgi", "--ini", "app.ini"]
      
  3. Добавьте следующие переменные окружения:

    • POBP_SERVICE=<service_name> - имя сервиса, как он будет отображаться в интерфейсе Proto Observability Platform
    • POBP_TRACE_TELEMETRY_ENABLED="false" - обязательно

Если приложение запускается в Docker контейнере

Выполните пункты указанные выше и добавьте следующую переменную окружения:

ENV POBP_AGENT_HOST="protoobp-agent" 

Укажите IP адрес хоста, где запущен ProtoOBP агент, доступные из сети Docker контейнера. В случае если агент запускается в виде Docker контейнера, то достаточно указать имя контейнера с агентом.

Пример полного Dockerfile:

FROM python:latest

WORKDIR /
COPY requirements.txt .

ARG PROTOOBP_INSTALL_TOKEN_NAME
ARG PROTOOBP_INSTALL_TOKEN_KEY

RUN pip install pobptrace --user --index-url "https://${PROTOOBP_INSTALL_TOKEN_NAME}:${PROTOOBP_INSTALL_TOKEN_KEY}@git.proto.group/api/v4/projects/125/packages/pypi/simple"
RUN pip install -r requirements.txt --user

ENV POBP_SERVICE="hello-world"
ENV POBP_AGENT_HOST="protoobp-agent" 
ENV POBP_TRACE_TELEMETRY_ENABLED="false"

CMD ["pobptrace-run", "python", "app.py"]

Если приложение работает в Kubernetes

Убедитесь, что у вас успешно установлен и настроен ProtoOBP Агент для Kubernetes.

Без использования автоматического подключения трейсера

Дополнительно необходимо передать поду переменную окружения POBP_AGENT_HOST со значением IP адреса воркер-ноды, а также переменные окружения для связи трейсов с инфраструктурой (имя k8s кластера нужно задать вручную).

apiVersion: apps/v1
kind: Deployment
#(...)
    spec:
      containers:
      - name: "<CONTAINER_NAME>"
        image: "<CONTAINER_IMAGE>/<TAG>"
        env:
          - name: POBP_SERVICE
            value: dispatch			
          - name: POBP_AGENT_HOST
            valueFrom:
              fieldRef:
                fieldPath: status.hostIP
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POBP_TAGS
            value: "pod_name:$(POD_NAME),node:$(NODE_NAME),kube_namespace:$(POD_NAMESPACE),kube_cluster_name:<my_cluster_name>"            
            

С использованием автоматического подключения трейсера

Агент ProtoOBP в K8s кластере по умолчанию инструментирует Python приложения с лейблом: admission.proto.group/enabled: "true"

  1. В спецификации пода приложения добавьте анотацию и лейбл с версией Python трейсинг агента:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
     labels:
     ...
    ...
    template:
       metadata:
         annotations:
           admission.proto.group/python-lib.version: "2.3.0" #Если Версия Python < 3.7, тогда необходимо указать версию "v1"
         creationTimestamp: null
         labels:
           admission.proto.group/enabled: "true" # Включение автоматической инструментации
           tags.proto.group/service: "my_service" #Укажите имя сервиса
           service: my_service
    
  2. В спецификации пода добавьте imagePullSecrets для доступа к Docker репозиторию ProtoOBP. Подробнее о добавление Secret указано в документации Установка агента в Kubernetes

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
      ...
    ...
     template:
        metadata:
          annotations:
            admission.proto.group/python-lib.version: "2.3.0" #Если Версия Python < 3.7, тогда необходимо указать версию "v1"
          creationTimestamp: null
          labels:
            admission.proto.group/enabled: "true" # Включение автоматической инструментации
           service: my_service
       spec:
          containers:
             ...
          ...
          imagePullSecrets:
          - name: protoobp-registry
    

Автоматическое подключение трейсера без использования лейблов

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

Поддерживаемые технологии трейсером

Версии Python

Поддерживает CPython версий 2.7, 3.5-3.10.

Автоматическая инструментация библиотек и фреймворков

Фреймворк Версии Автоматически подключается
asgi >= 2.0 нет
aiohttp (клиент) >= 2.0 да
aiohttp (сервер) >= 2.0 нет
Bottle >= 0.11 нет
CherryPy >= 11.2.0 нет
Django >= 1.8 да
djangorestframework >= 3.4 да
Falcon >= 1.0 нет
Flask >= 0.10 да
FastAPI >= 0.51 да
Molten >= 0.7.0 да
Pylons >= 0.9.6 нет
Pyramid >= 1.7 нет
pytest >= 3.0 нет
Sanic >= 19.6.0 да
Starlette >= 0.13.0 да
Tornado >= 4.0 нет

Хранилища данных

Хранилище Версии Автоматически подключается
algoliasearch >= 1.20.0 да
asyncpg >= 0.18.0 да
Cassandra >= 3.5 да
Elasticsearch >= 1.6 да
Flask Cache >= 0.12 нет
Mariadb >= 1.0.0 да
Memcached pylibmc >= 1.4 да
Memcached pymemcache >= 1.3 да
MongoDB Mongoengine >= 0.11 да
MongoDB Pymongo >= 3.0 да
MySQL MySQL-Python >= 1.2.3 да
MySQL mysqlclient >= 1.3 да
MySQL mysql-connector >= 2.1 да
Postgres aiopg >= 0.12.0, <= 0.16 да
Postgres psycopg >= 2.4 да
PyMySQL >= 0.7 да
PynamoDB >= 4.0 да
PyODBC >= 4.0 да
Redis >= 2.6 да
Redis redis-py-cluster >= 1.3.5 да
SQLAlchemy >= 1.0 нет
SQLite3 все да
Vertica >= 0.6 да

Библиотеки

Библиотека Версии Автоматически подключается
aiobotocore >= 0.2.3 нет
asyncio все > Python 3.7 да
Botocore >= 1.4.51 да
Boto2 >= 2.29.0 да
Celery >= 3.1 да
Consul >= 0.7 да
Futures все да
gevent >= 1.0 нет
Grpc >= 1.8.0 да
httplib все нет
Jinja2 >= 2.7 да
Kombu >= 4.0 нет
Mako >= 0.1.0 да
Requests >= 2.08 да
urllib3 >= 1.22 нет
graphql-core >= 2.0 да

Дополнительная инструментация вызовов

Дополнительную инструментацию можно использовать, если в перечене автоматически инструментированных библиотек и фреймворков нет необходимых.

Для примера будет использоваться следующий код приложения:

def make_sandwich_request(request):
    ingredients = get_ingredients()
    sandwich = assemble_sandwich(ingredients)
@tracer.wrap(service="my-sandwich-making-svc", resource="resource_name")
def get_ingredients():
    # сходить в кладовку
    # сходить к холодильнику
    # может быть сходить в магазин
    return

# можно добавить больше данных для кастомизации спана
@tracer.wrap("assemble_sandwich", service="my-sandwich-making-svc", resource="resource_name")
def assemble_sandwich(ingredients):
    return
from pobptrace import tracer

def make_sandwich_request(request):
    # запишем обе операции в спаны
    with tracer.trace("sandwich.make"):
        ingredients = get_ingredients()
        sandwich = assemble_sandwich(ingredients)

def make_sandwich_request(request):
    # запишем обе операции в спаны
    with tracer.trace("sandwich.create", resource="resource_name") as outer_span:

        with tracer.trace("get_ingredients", resource="resource_name") as span:
            ingredients = get_ingredients()

        with tracer.trace("assemble_sandwich", resource="resource_name") as span:
            sandwich = assemble_sandwich(ingredients)
from pobptrace import tracer
def make_sandwich_request(request):
    span = tracer.trace("sandwich.create", resource="resource_name")
    ingredients = get_ingredients()
    sandwich = assemble_sandwich(ingredients)
    span.finish()  # не забудьте закрыть спан

Кастомные метрики Python приложений

Кастомные, например, бизнес-метрики, можно генерировать напрямую из приложения и отсылать на Агента.

  1. Подключите библиотеку protoobp выполнив:

    pip install protoobp --user --index-url "https://<token_name>:<token_key>@git.proto.group/api/v4/projects/125/packages/pypi/simple"
    

    имя и значение токена находятся в вашем лицензионном сертификате Proto Observability Platform.

    Пример для Dockerfile и .gitlab-ci.yml:

    • в настройках проекта в Gitlab добавьте две переменные окружения (Проект -> Settings -> CI/CD -> Variables):

      • имя: PROTOOBP_INSTALL_TOKEN_NAME, значение = ваши данные из лицензионного сертификата (token или логин)
      • имя: PROTOOBP_INSTALL_TOKEN_KEY, значение = ваши данные из лицензионного сертификата (пароль)
    • .gitlab-ci.yml – необходимо передать значения переменных от Gitlab CI к docker build через --build-arg:

        script:
          - docker build --build-arg PROTOOBP_INSTALL_TOKEN_NAME=${PROTOOBP_INSTALL_TOKEN_NAME} --build-arg PROTOOBP_INSTALL_TOKEN_KEY=${PROTOOBP_INSTALL_TOKEN_KEY} .
      
    • Dockerrfile – необходимо добавить переменные окружения через ARG и передать их в pip install --index-url:

      FROM python:latest
      ARG PROTOOBP_INSTALL_TOKEN_NAME
      ARG PROTOOBP_INSTALL_TOKEN_KEY
      RUN pip install protoobp --user --index-url "https://${PROTOOBP_INSTALL_TOKEN_NAME}:${PROTOOBP_INSTALL_TOKEN_KEY}@git.proto.group/api/v4/projects/125/packages/pypi/simple"
      
  2. Инициализируйте StatsD клиента, используя UDP в коде приложения:

    from protoobp import initialize, statsd
    
    options = {
        "statsd_host": "127.0.0.1",
        "statsd_port": 8125,
    }
    
    initialize(**options)
    
  3. Теперь можно добавлять собственные метрики, пример использования:

    from protoobp import initialize, statsd
    import time
    
    options = {
        'statsd_host':'127.0.0.1',
        'statsd_port':8125
    }
    
    initialize(**options)
    
    while(1):
      statsd.increment('example_metric.increment', tags=["environment:dev"])
      statsd.decrement('example_metric.decrement', tags=["environment:dev"])
      time.sleep(10)
    

Типы кастомных метрик

После установки библиотеки для отправки метрик в Protoobp будут доступны следующие функции в зависимости от типа метрик. Функции имеют следующие общие параметры:

Параметр Тип Обязательно
<METRIC_NAME> String Да Имя метрики
<METRIC_VALUE> Double Да Значение метрики
<SAMPLE_RATE> Double Нет Рейт сэмплирования. Значение между 0 (все сэмплируется, то есть ничего не отправляется) и 1 (нет сэмплирования).
<TAGS> List of strings Нет Список тегов для метрики
  1. COUNT

    • increment(<METRIC_NAME>, <SAMPLE_RATE>, <TAGS>)
      Используется для увеличения значения метрики типа COUNT.

    • decrement(<METRIC_NAME>, <SAMPLE_RATE>, <TAGS>)
      Используется для уменьшения значения метрики типа COUNT.

    Пример:

    from protoobp import initialize, statsd
    import time
    
    options = {
        'statsd_host':'127.0.0.1',
        'statsd_port':8125
    }
    
    initialize(**options)
    
    while(1):
      statsd.increment('example_metric.increment', tags=["environment:dev"])
      statsd.decrement('example_metric.decrement', tags=["environment:dev"])
      time.sleep(10)
    
  2. GAUGE

    • gauge(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>)

    Пример:

    from protoobp import initialize, statsd
    import time
    
    options = {
        'statsd_host':'127.0.0.1',
        'statsd_port':8125
    }
    
    initialize(**options)
    
    i = 0
    
    while(1):
      i += 1
      statsd.gauge('example_metric.gauge', i, tags=["environment:dev"])
      time.sleep(10)
    
  3. HISTOGRAM

    • histogram(<METRIC_NAME>, <METRIC_VALUE>, <SAMPLE_RATE>, <TAGS>)
      Отправляются агрегаты max, median, avg и count.
      Отправляется 95-й перцентиль.

    Пример:

    from protoobp import initialize, statsd
    import time
    import random
    
    options = {
        'statsd_host':'127.0.0.1',
        'statsd_port':8125
    }
    
    initialize(**options)
    
    while(1):
      statsd.histogram('example_metric.histogram', random.randint(0, 20), tags=["environment:dev"])
      time.sleep(2)   
    

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

    Метрика Описание
    example_metric_histogram_count Количество раз сбора метрики
    example_metric_histogram_avg Среднее из собранных значений
    example_metric_histogram_median Медианное значение собранных значений
    example_metric_histogram_max Максимум среди собранных значений
    example_metric_histogram_95percentile 95-й перцентиль собранных значений