kpi-dashboard/Impala_connection.md

182 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Подключение к Impala из Python
Инструкция описывает, как подключиться к корпоративному кластеру Impala через Python-библиотеку `impyla`. Используется в проекте `metrics_audit`.
---
## Параметры кластера
| Параметр | Значение |
|---|---|
| Основной хост | `bdas-worker-08.bdpak.telecom.kz` |
| Резервный хост | `bdas-utility-01.bdpak.telecom.kz` |
| Порт | `21050` |
| База данных | `drb` |
| Аутентификация | PLAIN (логин + пароль) |
| SSL | включён (`use_ssl=True`) |
| Доступ | только из внутренней сети или через VPN |
> **Username и password** хранятся в `config.yaml` и не коммитятся в git.
---
## Зависимости
`impyla` работает через протокол Thrift напрямую — Java-драйверы (JDBC `.zip`) **не нужны**, они только для DBeaver/Tableau.
```
# requirements.txt
impyla==0.19.0
thrift==0.16.0
thrift-sasl==0.4.3
pure-sasl>=0.6.2 # вместо sasl — не требует C++ компилятора на Windows
```
> **Важно:** пакет `sasl==0.3.1` на Windows не устанавливается без Microsoft C++ Build Tools.
> Используйте `pure-sasl` — он устанавливается автоматически как зависимость `thrift-sasl`.
Установка:
```bat
python -m venv venv
venv\Scripts\activate
pip install impyla==0.19.0 thrift==0.16.0 thrift-sasl==0.4.3 pandas
```
---
## Проблема с SSL и её решение
При подключении с `use_ssl=True` возникает ошибка:
```
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure
```
**Причина:** сервер Impala использует устаревшие cipher suites, которые Python 3.10+ отклоняет по умолчанию (security level 2).
**Решение:** monkey-patch SSL-контекста библиотеки `thrift` перед подключением:
```python
import ssl
import thrift.transport.TSSLSocket as _mod
def _patch_thrift_ssl():
_orig = _mod.TSSLSocket.__init__
def _patched(self, *a, **kw):
_orig(self, *a, **kw)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.set_ciphers("DEFAULT:@SECLEVEL=0")
self._context = ctx
_mod.TSSLSocket.__init__ = _patched
# Вызвать ДО impyla_connect:
_patch_thrift_ssl()
```
Это нужно вызвать один раз перед первым подключением. Патч снижает проверку сертификата и разрешает старые шифры — приемлемо для внутренней сети за VPN.
---
## Подключение
```python
from impala.dbapi import connect
conn = connect(
host="bdas-worker-08.bdpak.telecom.kz",
port=21050,
database="drb",
user="<username>", # из config.yaml
password="<password>", # из config.yaml
use_ssl=True,
auth_mechanism="PLAIN", # AuthMech=3 в JDBC-терминологии
timeout=60,
)
```
С резервным хостом — оберните в try/except и переключитесь на `bdas-utility-01.bdpak.telecom.kz` при ошибке.
---
## Выполнение запроса
```python
cursor = conn.cursor()
cursor.execute("SELECT event_type, entry_date, count(*) AS cnt FROM drb.drb_iliyas_amplitude_metrics_full GROUP BY 1, 2")
import pandas as pd
rows = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
df = pd.DataFrame(rows, columns=columns)
```
---
## Схема таблицы метрик
**`drb.drb_iliyas_amplitude_metrics_full`**
| Колонка | Тип | Описание |
|---|---|---|
| `metrics` | string | Платформа: `TelecomKz` или `Aitu` |
| `event_type` | string | Название метрики (событие Amplitude) |
| `entry_date` | string | Дата события (`YYYY-MM-DD`) |
| `event_time` | string | Полная метка времени |
| `event_properties` | string | JSON с параметрами события |
| `platform` | string | `android` / `iOS` / `Web` |
| ... | | прочие поля пользователя и устройства |
> **Внимание:** колонка `metrics` содержит **платформу** (`TelecomKz`/`Aitu`), а не название метрики.
> Название метрики — в колонке `event_type`.
**`external_sources.amplitude_loyalty_program_logs`**
| Колонка | Тип | Описание |
|---|---|---|
| `event_type` | string | Название метрики |
| `event_time` | string | Полная метка времени (дата берётся через `left(event_time, 10)`) |
| ... | | прочие поля |
---
## Агрегирующий запрос проекта
```sql
-- TelecomKz (все метрики) + Aitu (только whitelist)
SELECT metrics AS platform, event_type AS metrics, entry_date, count(*) AS cnt
FROM drb.drb_iliyas_amplitude_metrics_full
WHERE event_type IS NOT NULL AND event_type != ''
AND (
metrics = 'TelecomKz'
OR (metrics = 'Aitu' AND event_type IN ('miniapp_opened', 'main_tab_selected', ...))
)
GROUP BY 1, 2, 3
UNION ALL
-- Loyalty (без временных акционных метрик)
SELECT 'Loyalty' AS platform, event_type AS metrics,
left(event_time, 10) AS entry_date, count(*) AS cnt
FROM external_sources.amplitude_loyalty_program_logs
WHERE event_type IS NOT NULL AND event_type != ''
AND event_type NOT LIKE 'detail_promo_%'
AND event_type NOT LIKE 'company_promo_%'
GROUP BY 1, 2, 3
```
---
## Типичные ошибки
| Ошибка | Причина | Решение |
|---|---|---|
| `SSLV3_ALERT_HANDSHAKE_FAILURE` | Старые cipher suites на сервере | Применить `_patch_thrift_ssl()` (см. выше) |
| `ConnectionRefusedError` / `TSocket read 0 bytes` | VPN не подключён | Подключить VPN и повторить |
| `AuthenticationError` | Неверный логин/пароль | Проверить `config.yaml` |
| `sasl` не устанавливается | Нет C++ Build Tools | Использовать `pure-sasl` (устанавливается автоматически) |
| `ssl.PROTOCOL_TLS is deprecated` | Предупреждение thrift 0.16 | Некритично, патч перезаписывает контекст после |