Мониторинг Python приложений с помощью Proto Observability Platform
На этой странице:
- Введение
- Установка Python трейсера
- Поддерживаемые технологии трейсером
- Дополнительная инструментация вызовов
- Кастомные метрики Python приложений
Введение
Общий процесс подключения Python приложения на мониторинг:
- Установка ProtoOBP Агента
- Установка трейсера
Установка Python трейсера
- 
Установите библиотеку 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"
 
- 
- 
Добавьте pobptrace-runкоманду какentrypointвашего приложения. Например:pobptrace-run python app.py- 
Пример для типового Python приложения: CMD ["pobptrace-run", "python", "app.py"]
- 
Пример для uwsgiиDockerfile:CMD ["pobptrace-run", "uwsgi", "--ini", "app.ini"]
 
- 
- 
Добавьте следующие переменные окружения: - POBP_AGENT_HOST– адрес Агента, на который будет отсылать данные трейсер
- POBP_SERVICE=<service_name>– имя сервиса, как он будет отображаться в интерфейсе Proto Observability Platform
- POBP_TRACE_TELEMETRY_ENABLED="false"– обязательно
 
Если приложение запускается в Docker контейнере
Выполните пункты указанные выше и добавьте следующие переменные окружения:
- POBP_AGENT_HOST– адрес Агента, на который будет отсылать данные трейсер:- если Агент запущен в Docker контейнере, укажите имя Docker контейнера Агента:
Убедитесь, что контейнер Агента и контейнер приложения находятся в одной Docker сети. Адрес агента должен быть доступен из Docker контейнера приложения.ENV POBP_AGENT_HOST="protoobp-agent"
- если Агент запущен на хосте как сервис (не в контейнере):
Убедитесь что в конфигурации Агента разрешен прием APM данных от контейнеров:ENV POBP_AGENT_HOST="host.docker.internal"apm_config: apm_non_local_traffic: true
 
- если Агент запущен в Docker контейнере, укажите имя Docker контейнера Агента:
- POBP_SERVICE– имя сервиса, которое будет отображаться в интерфейсе Proto OBP:- ENV POBP_SERVICE="my_service_name"
- POBP_TRACE_TELEMETRY_ENABLED– установите в- false- ENV POBP_TRACE_TELEMETRY_ENABLED="false"
Пример полного 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"
- 
В спецификации пода приложения добавьте анотацию и лейбл с версией 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
- 
В спецификации пода добавьте imagePullSecretsдля доступа к Docker репозиторию ProtoOBP. Подробнее о добавление Secret указано в документации Установка агента в KubernetesapiVersion: 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 приложений
Кастомные, например, бизнес-метрики, можно генерировать напрямую из приложения и отсылать на Агента.
Обратите внимание
Агент должен быть установлен и запущен на том хосте, на котором запускаются Python приложения.- 
Подключите библиотеку 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"
 
- 
- 
Инициализируйте StatsD клиента, используя UDP в коде приложения: from protoobp import initialize, statsd options = { "statsd_host": "127.0.0.1", "statsd_port": 8125, } initialize(**options)
- 
Теперь можно добавлять собственные метрики, пример использования: 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 | Нет | Список тегов для метрики | 
- 
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)Обратите вниманиеНе забудьте сделатьflush/closeклиента, когда он уже более не нужен.
- 
- 
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)Обратите вниманиеНе забудьте сделатьflush/closeклиента, когда он уже более не нужен.
- 
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)Обратите вниманиеНе забудьте сделатьflush/closeклиента, когда он уже более не нужен.Пример выше создаст следующие метрики: Метрика Описание example_metric_histogram_countКоличество раз сбора метрики example_metric_histogram_avgСреднее из собранных значений example_metric_histogram_medianМедианное значение собранных значений example_metric_histogram_maxМаксимум среди собранных значений example_metric_histogram_95percentile95-й перцентиль собранных значений