Руководство по связыванию сущностей кода CPG с внешними системами (Git, трекеры задач, APM).
Содержание¶
- Обзор
- Архитектура
- Быстрая настройка
- Установка зависимостей
- Настройка переменных окружения
- Первоначальная синхронизация
- Интеграция с Git
- GitSyncService
- Доступные теги Git
- SQL-запросы для Git
- Интеграция с трекерами задач
- IssueSyncService
- Поддерживаемые поставщики
- Доступные теги задач
- Создание задач
- Интеграция с APM/Sentry
- SentrySyncService
- Доступные теги Sentry
- Использование оркестратора
- Python API
- Интерфейс командной строки
- Вспомогательные функции
- Справочник серверного API
- Перечисления
- Основные классы данных
- Классы данных Git
- Классы данных задач
- Классы данных Sentry
- ExternalContextBase
- OrchestratorResult
- Устранение неполадок
- Теги не создаются
- Проблемы с синхронизацией Git
- Ограничение частоты запросов GitHub
- Ошибки API Sentry
- Теги есть, но ребра отсутствуют
- Дальнейшие шаги
Обзор¶
Интеграция внешнего контекста позволяет связывать сущности кода (методы, функции, классы) в графе свойств кода (CPG) с метаданными из внешних систем:
- Git: информация об авторах, история коммитов, частота изменений, данные blame
- Трекеры задач: Jira, GitHub Issues, GitLab Issues
- APM/отслеживание ошибок: данные об ошибках Sentry, категории частоты, критичность
Это позволяет выполнять запросы вида: - “Кто написал этот код?” - “Какие задачи связаны с этой функцией?” - “Какие методы вызывают больше всего ошибок в продакшене?” - “Какой код изменяется чаще всего?”
Архитектура¶
+-----------------------------------------------------------------+
| Внешние системы |
+---------------+---------------------+---------------------------+
| Git | Трекеры задач | Sentry |
| (коммиты) | (Jira/GitHub/GL) | (ошибки) |
+-------+-------+----------+----------+-----------+---------------+
| | |
v v v
+-----------------------------------------------------------------+
| ExternalContextOrchestrator |
| +---------------+ +-----------------+ +---------------------+ |
| |GitSyncService | |IssueSyncService | |SentrySyncService | |
| +---------------+ +-----------------+ +---------------------+ |
+-----------------------------------------------------------------+
| |
v v
+--------------------+ +------------------------+
| PostgreSQL | | DuckDB CPG |
| (необработанные | | (nodes_tag_v2, |
| метаданные) | | edges_tagged_by, |
| - external_context | | nodes_method) |
| - file_commit_hist | +------------------------+
| - git_authors |
| - runtime_metrics |
+--------------------+
Данные поступают из внешних систем через сервисы синхронизации в два хранилища:
- PostgreSQL (необязательно): хранит необработанные метаданные в таблицах
external_context,file_commit_history,git_authors,runtime_metrics - DuckDB CPG: хранит теги в
nodes_tag_v2и связывает их с методами черезedges_tagged_by
Все теги хранятся в nodes_tag_v2 (не nodes_tag). Связи методов с тегами проходят через edges_tagged_by.
Быстрая настройка¶
1. Установка зависимостей¶
pip install -r requirements.txt
2. Настройка переменных окружения¶
# Git (дополнительная настройка не требуется — используется локальный git)
# GitHub Issues
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
# GitLab Issues
export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"
# Jira
export JIRA_TOKEN="your_jira_api_token"
# Sentry
export SENTRY_AUTH_TOKEN="your_sentry_token"
3. Первоначальная синхронизация¶
from src.services.external_context import ExternalContextOrchestrator
# Инициализация оркестратора
orchestrator = ExternalContextOrchestrator(
duckdb_conn=your_duckdb_connection,
pg_conn=your_postgres_connection, # необязательно
repo_path="/path/to/your/repo"
)
# Синхронизация всех источников
result = orchestrator.sync_all(
git_config={"since_days": 90, "use_blame": True},
issue_config={
"provider": "github",
"repo": "owner/repo",
"token": os.getenv("GITHUB_TOKEN"),
},
sentry_config={
"org_slug": "my-org",
"project_slug": "my-project",
"token": os.getenv("SENTRY_AUTH_TOKEN"),
},
)
print(f"Всего синхронизировано: {result.total_items_synced}, тегов: {result.total_tags_created}")
Интеграция с Git¶
GitSyncService¶
Синхронизирует метаданные истории Git в теги CPG.
from src.services.external_context import GitSyncService
service = GitSyncService(
duckdb_conn=conn,
pg_conn=pg_conn, # необязательно, для хранения необработанных данных
repo_path="/path/to/repo",
max_commits=1000, # по умолчанию
since_days=90 # по умолчанию
)
# Синхронизация с анализом blame
result = service.sync(use_blame=True)
print(f"Синхронизировано {result.items_synced} коммитов, создано {result.tags_created} тегов")
# Синхронизация только определенных файлов, без blame
result = service.sync(files=["src/main.py", "src/auth.py"], use_blame=False)
Параметры конструктора:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
duckdb_conn |
connection | обязательный | Подключение к DuckDB |
pg_conn |
connection | None |
Подключение к PostgreSQL (необязательно) |
repo_path |
str | "." |
Путь к репозиторию Git |
max_commits |
int | 1000 |
Максимальное число коммитов |
since_days |
int | 90 |
Глубина истории в днях |
Параметры синхронизации:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
files |
List[str] | None |
Ограничить синхронизацию конкретными файлами |
use_blame |
bool | True |
Выполнять анализ git blame |
Доступные теги Git¶
| Имя тега | Описание | Пример значения |
|---|---|---|
git-author |
Электронная почта автора последнего изменения | dev@company.com |
git-commit |
SHA последнего коммита, изменившего метод | a1b2c3d4... |
git-branch |
Ветка происхождения кода | feature/PROJ-123 |
git-blame-count |
Количество уникальных авторов | 3 |
git-churn |
Количество изменений | 15 |
git-last-modified |
Временная метка последнего изменения | 2025-01-09T10:30:00Z |
SQL-запросы для Git¶
Все запросы используют nodes_tag_v2 (актуальная таблица тегов).
-- Найти все методы, измененные конкретным автором
SELECT m.full_name, m.filename, t.value AS author
FROM nodes_method m
JOIN edges_tagged_by e ON m.id = e.src
JOIN nodes_tag_v2 t ON e.dst = t.id
WHERE t.name = 'git-author' AND t.value = 'developer@example.com';
-- Найти код с высокой частотой изменений (методы, измененные > 10 раз)
SELECT m.full_name, CAST(t.value AS INT) AS churn_count
FROM nodes_method m
JOIN edges_tagged_by e ON m.id = e.src
JOIN nodes_tag_v2 t ON e.dst = t.id
WHERE t.name = 'git-churn' AND CAST(t.value AS INT) > 10
ORDER BY churn_count DESC;
-- Найти кандидатов на bus factor (методы с единственным автором)
SELECT m.full_name, t_author.value AS sole_author
FROM nodes_method m
JOIN edges_tagged_by e1 ON m.id = e1.src
JOIN nodes_tag_v2 t_blame ON e1.dst = t_blame.id
JOIN edges_tagged_by e2 ON m.id = e2.src
JOIN nodes_tag_v2 t_author ON e2.dst = t_author.id
WHERE t_blame.name = 'git-blame-count' AND t_blame.value = '1'
AND t_author.name = 'git-author';
-- Найти недавно измененные методы (за последние 7 дней)
SELECT m.full_name, m.filename, t.value AS last_modified
FROM nodes_method m
JOIN edges_tagged_by e ON m.id = e.src
JOIN nodes_tag_v2 t ON e.dst = t.id
WHERE t.name = 'git-last-modified'
AND CAST(t.value AS TIMESTAMP) > NOW() - INTERVAL '7 days'
ORDER BY t.value DESC;
Интеграция с трекерами задач¶
IssueSyncService¶
Связывает задачи с кодом через ссылки в сообщениях коммитов.
from src.services.external_context import IssueSyncService
# GitHub
service = IssueSyncService(
duckdb_conn=conn,
pg_conn=pg_conn,
provider="github",
repo="owner/repo",
token=os.getenv("GITHUB_TOKEN"),
max_issues=500 # по умолчанию
)
# GitLab
service = IssueSyncService(
duckdb_conn=conn,
provider="gitlab",
repo="owner/repo",
base_url="https://gitlab.company.com",
token=os.getenv("GITLAB_TOKEN")
)
# Jira
service = IssueSyncService(
duckdb_conn=conn,
provider="jira",
project_key="PROJ",
base_url="https://company.atlassian.net",
token=os.getenv("JIRA_TOKEN")
)
result = service.sync(since_days=90, link_via_commits=True)
Параметры конструктора:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
duckdb_conn |
connection | обязательный | Подключение к DuckDB |
pg_conn |
connection | None |
Подключение к PostgreSQL (необязательно) |
provider |
str | "github" |
Поставщик: github, gitlab, jira |
repo |
str | None |
Репозиторий (GitHub/GitLab: owner/repo) |
base_url |
str | None |
Базовый URL для self-hosted экземпляров |
project_key |
str | None |
Ключ проекта Jira (например, PROJ) |
token |
str | None |
Токен аутентификации API |
max_issues |
int | 500 |
Максимальное число задач |
Параметры синхронизации:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
since_days |
int | 90 |
Глубина истории в днях |
link_via_commits |
bool | True |
Связывать задачи с кодом через ссылки в коммитах |
Поддерживаемые поставщики¶
| Поставщик | Настройка | Шаблон ссылки на задачу |
|---|---|---|
| GitHub | provider="github", repo="owner/repo" |
#123, GH-123 |
| GitLab | provider="gitlab", repo="owner/repo" |
#123, !123 (MR) |
| Jira | provider="jira", project_key="PROJ" |
PROJ-123 |
Примечание: для Jira используйте параметр project_key (не repo).
Доступные теги задач¶
| Имя тега | Описание | Пример значения |
|---|---|---|
issue-id |
Идентификатор задачи | PROJ-123, #456 |
issue-type |
Тип задачи | bug, feature, refactor |
issue-status |
Текущий статус | open, closed, in_progress |
issue-priority |
Приоритет задачи | critical, high, medium, low |
issue-label |
Метки задачи | critical, tech-debt |
Создание задач¶
IssueSyncService позволяет программно создавать задачи в Jira:
service = IssueSyncService(
duckdb_conn=conn,
provider="jira",
project_key="PROJ",
base_url="https://company.atlassian.net",
token=os.getenv("JIRA_TOKEN")
)
issue_key = service.create_jira_issue(
summary="Fix NullPointerException in AuthService",
description="Method authenticate() throws NPE when token is expired",
issue_type="Bug", # по умолчанию
priority="Medium", # по умолчанию
labels=["codegraph", "auto-detected"],
components=["auth"]
)
# Возвращает "PROJ-456" или None в случае ошибки
Интеграция с APM/Sentry¶
SentrySyncService¶
Синхронизирует данные об ошибках из Sentry для выявления нестабильного кода.
from src.services.external_context import SentrySyncService
service = SentrySyncService(
duckdb_conn=conn,
pg_conn=pg_conn,
org_slug="my-organization",
project_slug="my-project",
token=os.getenv("SENTRY_AUTH_TOKEN"),
base_url="https://sentry.io", # по умолчанию; переопределите для self-hosted
max_issues=200 # по умолчанию
)
result = service.sync(since_days=30, min_events=1)
Параметры конструктора:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
duckdb_conn |
connection | обязательный | Подключение к DuckDB |
pg_conn |
connection | None |
Подключение к PostgreSQL (необязательно) |
org_slug |
str | None |
Идентификатор организации Sentry |
project_slug |
str | None |
Идентификатор проекта Sentry |
token |
str | None |
Токен аутентификации Sentry |
base_url |
str | "https://sentry.io" |
Базовый URL (переопределите для self-hosted) |
max_issues |
int | 200 |
Максимальное число задач |
Параметры синхронизации:
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
since_days |
int | 30 |
Глубина истории в днях |
min_events |
int | 1 |
Минимальное число событий для включения |
Доступные теги Sentry¶
| Имя тега | Описание | Пример значения |
|---|---|---|
sentry-issue |
Идентификатор задачи Sentry | SENTRY-12345 |
error-frequency |
Категория частоты по числу событий | critical, high, medium, low, rare |
error-type |
Тип исключения | NullPointerException |
error-level |
Уровень критичности | error, fatal, warning |
sentry-first-seen |
Дата первого появления ошибки | 2025-06-15T08:30:00Z |
Тег error-frequency использует категории на основе общего числа событий:
| Категория | Число событий |
|---|---|
critical |
>= 10000 |
high |
>= 1000 |
medium |
>= 100 |
low |
>= 10 |
rare |
< 10 |
-- Найти методы с критической частотой ошибок
SELECT m.full_name, m.filename, t.value AS frequency
FROM nodes_method m
JOIN edges_tagged_by e ON m.id = e.src
JOIN nodes_tag_v2 t ON e.dst = t.id
WHERE t.name = 'error-frequency' AND t.value = 'critical';
-- Найти методы по типу ошибки
SELECT m.full_name, t.value AS error_type
FROM nodes_method m
JOIN edges_tagged_by e ON m.id = e.src
JOIN nodes_tag_v2 t ON e.dst = t.id
WHERE t.name = 'error-type' AND t.value LIKE '%NullPointer%';
-- Комбинация: методы с высокой+ частотой И уровнем fatal
SELECT DISTINCT m.full_name, m.filename
FROM nodes_method m
JOIN edges_tagged_by e1 ON m.id = e1.src
JOIN nodes_tag_v2 t_freq ON e1.dst = t_freq.id
JOIN edges_tagged_by e2 ON m.id = e2.src
JOIN nodes_tag_v2 t_level ON e2.dst = t_level.id
WHERE t_freq.name = 'error-frequency' AND t_freq.value IN ('critical', 'high')
AND t_level.name = 'error-level' AND t_level.value = 'fatal';
Использование оркестратора¶
Python API¶
ExternalContextOrchestrator координирует все сервисы синхронизации.
from src.services.external_context import ExternalContextOrchestrator
orchestrator = ExternalContextOrchestrator(
duckdb_conn=conn,
pg_conn=pg_conn, # необязательно
repo_path=".",
vector_store=None # необязательно, для семантического индексирования
)
# Синхронизация всех источников одновременно
result = orchestrator.sync_all(
git_config={"since_days": 30, "use_blame": True},
issue_config={
"provider": "github",
"repo": "owner/repo",
"token": token,
},
sentry_config={
"org_slug": "org",
"project_slug": "proj",
"token": sentry_token,
},
parallel=True # запуск синхронизаций параллельно
)
print(f"Успешно: {result.success}")
print(f"Элементов синхронизировано: {result.total_items_synced}")
print(f"Тегов создано: {result.total_tags_created}")
print(f"Ребер создано: {result.total_edges_created}")
print(f"Длительность: {result.duration_seconds:.1f}s")
# Доступ к результатам по источникам
for source, src_result in result.source_results.items():
print(f" {source}: {src_result.items_synced} элементов, {src_result.tags_created} тегов")
# Синхронизация отдельных источников
git_result = orchestrator.sync_git(since_days=30, use_blame=True)
issue_result = orchestrator.sync_issues(
provider="github", repo="owner/repo", token=token
)
sentry_result = orchestrator.sync_sentry(
org_slug="org", project_slug="proj", token=token
)
# Получение статистики синхронизации
stats = orchestrator.get_sync_stats()
Интерфейс командной строки¶
# Синхронизация истории Git
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--repo-path /path/to/repo \
--sync-git --git-since-days 30
# Синхронизация Git без анализа blame
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-git --no-blame
# Синхронизация Git с ограничением числа коммитов
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-git --git-max-commits 2000
# Синхронизация задач GitHub
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-issues --issue-provider github --issue-repo owner/repo \
--issue-token "$GITHUB_TOKEN"
# Синхронизация задач GitLab (self-hosted)
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-issues --issue-provider gitlab --issue-repo owner/repo \
--issue-url https://gitlab.company.com \
--issue-token "$GITLAB_TOKEN"
# Синхронизация задач Jira
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-issues --issue-provider jira --issue-project PROJ \
--issue-url https://company.atlassian.net \
--issue-token "$JIRA_TOKEN"
# Синхронизация ошибок Sentry
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-sentry --sentry-org my-org --sentry-project my-project \
--sentry-token "$SENTRY_AUTH_TOKEN"
# Синхронизация Sentry (self-hosted)
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-sentry --sentry-org my-org --sentry-project my-project \
--sentry-token "$SENTRY_AUTH_TOKEN" --sentry-url https://sentry.company.com
# Синхронизация всех источников
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--repo-path /path/to/repo \
--sync-all
# Просмотр статистики синхронизации
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb --stats
# Подробный вывод
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb --sync-git --verbose
Полный перечень флагов командной строки:
| Флаг | Описание | По умолчанию |
|---|---|---|
--duckdb |
Путь к базе данных DuckDB | обязательный |
--pg-url |
URL подключения к PostgreSQL | None |
--repo-path |
Путь к репозиторию Git | . |
--sync-all |
Синхронизация всех источников | - |
--sync-git |
Синхронизация только Git | - |
--sync-issues |
Синхронизация только задач | - |
--sync-sentry |
Синхронизация только Sentry | - |
--git-since-days |
Глубина истории Git в днях | 90 |
--git-max-commits |
Максимальное число коммитов Git | 1000 |
--no-blame |
Пропуск анализа git blame | - |
--issue-provider |
Поставщик задач (github, gitlab, jira) |
- |
--issue-repo |
Репозиторий для GitHub/GitLab | - |
--issue-project |
Ключ проекта для Jira | - |
--issue-url |
Базовый URL для self-hosted экземпляров | - |
--issue-token |
Токен доступа к трекеру задач | - |
--sentry-org |
Идентификатор организации Sentry | - |
--sentry-project |
Идентификатор проекта Sentry | - |
--sentry-token |
Токен аутентификации Sentry | - |
--sentry-url |
Базовый URL Sentry (self-hosted) | - |
--stats |
Вывод статистики синхронизации | - |
--verbose |
Подробный вывод | - |
Вспомогательные функции¶
Пакет src.services.external_context экспортирует три вспомогательные функции для быстрой разовой синхронизации:
from src.services.external_context import (
sync_git_to_cpg,
sync_issues_to_cpg,
sync_sentry_to_cpg,
)
# Синхронизация метаданных Git
result = sync_git_to_cpg(
duckdb_conn=conn,
pg_conn=pg_conn, # необязательно
repo_path=".",
since_days=30,
use_blame=True
)
# Синхронизация задач
result = sync_issues_to_cpg(
duckdb_conn=conn,
pg_conn=pg_conn,
provider="github",
repo="owner/repo",
token=os.getenv("GITHUB_TOKEN")
)
# Синхронизация ошибок Sentry
result = sync_sentry_to_cpg(
duckdb_conn=conn,
pg_conn=pg_conn,
org_slug="my-org",
project_slug="my-project",
token=os.getenv("SENTRY_AUTH_TOKEN")
)
Все три функции возвращают SyncResult.
Справочник серверного API¶
Перечисления¶
ExternalSource – определяет внешнюю систему:
| Значение | Описание |
|---|---|
GIT |
Репозиторий Git |
JIRA |
Трекер задач Jira |
GITHUB |
GitHub |
GITLAB |
GitLab |
SENTRY |
Отслеживание ошибок Sentry |
SONARQUBE |
Качество кода SonarQube |
ContextType – тип внешнего контекста:
| Значение | Описание |
|---|---|
COMMIT |
Коммит Git |
ISSUE |
Задача |
ERROR |
Ошибка/исключение |
METRIC |
Метрика производительности |
REVIEW |
Ревью кода |
Основные классы данных¶
SyncResult – результат операции синхронизации:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
source |
ExternalSource |
обязательное | Система-источник |
context_type |
ContextType |
обязательное | Тип контекста |
success |
bool |
обязательное | Успешность синхронизации |
items_synced |
int |
0 |
Количество синхронизированных элементов |
items_failed |
int |
0 |
Количество элементов с ошибками |
tags_created |
int |
0 |
Количество созданных тегов |
edges_created |
int |
0 |
Количество созданных ребер |
duration_seconds |
float |
0.0 |
Длительность синхронизации |
errors |
List[str] |
field(default_factory=list) |
Сообщения об ошибках |
metadata |
Dict[str, Any] |
field(default_factory=dict) |
Дополнительные метаданные |
ExternalTag – тег для присоединения к узлу CPG:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
name |
str |
обязательное | Имя тега (например, git-author) |
value |
str |
обязательное | Значение тега |
external_source |
ExternalSource |
обязательное | Система-источник |
external_id |
str |
обязательное | Идентификатор во внешней системе |
external_url |
Optional[str] |
None |
URL во внешней системе |
confidence |
float |
1.0 |
Уверенность привязки |
metadata |
Dict[str, Any] |
field(default_factory=dict) |
Дополнительные метаданные |
MethodTagLink – связывает метод с тегом:
| Поле | Тип | Описание |
|---|---|---|
method_id |
int |
Идентификатор узла метода в CPG |
method_full_name |
str |
Полное имя метода |
filename |
str |
Путь к исходному файлу |
line_start |
int |
Начальная строка метода |
line_end |
int |
Конечная строка метода |
tag |
ExternalTag |
Присоединяемый тег |
Классы данных Git¶
GitCommit:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
sha |
str |
обязательное | SHA коммита |
author_email |
str |
обязательное | Электронная почта автора |
author_name |
str |
обязательное | Имя автора |
timestamp |
datetime |
обязательное | Временная метка коммита |
message |
str |
обязательное | Сообщение коммита |
files |
List[str] |
обязательное | Измененные файлы |
lines_added |
int |
0 |
Добавленные строки |
lines_deleted |
int |
0 |
Удаленные строки |
branch |
Optional[str] |
None |
Имя ветки |
issue_refs |
List[str] |
None |
Ссылки на задачи |
GitBlameEntry:
| Поле | Тип | Описание |
|---|---|---|
commit_sha |
str |
SHA коммита |
author_email |
str |
Электронная почта автора |
author_name |
str |
Имя автора |
timestamp |
datetime |
Временная метка коммита |
line_number |
int |
Номер строки |
line_content |
str |
Содержимое строки |
Классы данных задач¶
Issue:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
id |
str |
обязательное | Идентификатор задачи |
title |
str |
обязательное | Заголовок задачи |
description |
Optional[str] |
обязательное | Описание задачи |
issue_type |
str |
обязательное | Тип (bug, feature и т.д.) |
status |
str |
обязательное | Текущий статус |
priority |
Optional[str] |
обязательное | Приоритет |
assignee |
Optional[str] |
обязательное | Исполнитель |
reporter |
Optional[str] |
обязательное | Автор задачи |
labels |
List[str] |
обязательное | Метки |
created_at |
Optional[datetime] |
обязательное | Дата создания |
updated_at |
Optional[datetime] |
обязательное | Дата обновления |
url |
Optional[str] |
обязательное | URL задачи |
linked_commits |
List[str] |
обязательное | Связанные SHA коммитов |
linked_files |
List[str] |
обязательное | Связанные файлы |
Классы данных Sentry¶
SentryIssue:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
id |
str |
обязательное | Идентификатор задачи Sentry |
short_id |
str |
обязательное | Краткий идентификатор (например, PROJ-ABC) |
title |
str |
обязательное | Заголовок задачи |
culprit |
str |
обязательное | Виновный метод/файл |
level |
str |
обязательное | Уровень критичности |
status |
str |
обязательное | Статус задачи |
count |
int |
обязательное | Общее число событий |
user_count |
int |
обязательное | Число затронутых пользователей |
first_seen |
datetime |
обязательное | Первое появление |
last_seen |
datetime |
обязательное | Последнее появление |
url |
Optional[str] |
None |
URL задачи в Sentry |
stacktrace_frames |
List[Dict] |
обязательное | Кадры трассировки стека |
tags |
Dict[str, str] |
обязательное | Теги Sentry |
StackFrame:
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
filename |
str |
обязательное | Исходный файл |
function |
str |
обязательное | Имя функции |
lineno |
int |
обязательное | Номер строки |
context_line |
Optional[str] |
None |
Строка исходного кода |
in_app |
bool |
True |
Принадлежит ли кадр коду приложения |
ExternalContextBase¶
Абстрактный базовый класс для всех сервисов синхронизации. Расположен в src/services/external_context/base.py.
class ExternalContextBase(ABC):
def __init__(self, duckdb_conn, pg_conn=None, source: ExternalSource = None):
...
Конкретные методы:
| Метод | Параметры | Возвращает | Описание |
|---|---|---|---|
create_tag |
tag: ExternalTag |
int |
Создает тег в nodes_tag_v2, возвращает идентификатор тега |
create_tag_edge |
method_id: int, tag_id: int |
bool |
Создает ребро в edges_tagged_by |
find_methods_by_file_lines |
filename: str, line_start: int, line_end: int |
List[Dict] |
Находит методы, пересекающиеся с указанным диапазоном строк |
store_external_context |
external_id, context_type, raw_data, linked_files=None, linked_cpg_nodes=None, external_url=None |
bool |
Сохраняет необработанный контекст в PostgreSQL |
get_existing_tags |
tag_name: str |
Dict[str, int] |
Возвращает существующие теги по имени как словарь {value: id} |
Абстрактные методы (должны быть реализованы в подклассах):
| Метод | Возвращает | Описание |
|---|---|---|
sync(**kwargs) |
SyncResult |
Выполняет операцию синхронизации |
get_supported_tag_categories() |
List[str] |
Возвращает список категорий тегов, создаваемых сервисом |
OrchestratorResult¶
Результат оркестрированной синхронизации нескольких источников.
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
success |
bool |
True |
Общий статус |
total_items_synced |
int |
0 |
Общее число элементов по всем источникам |
total_tags_created |
int |
0 |
Общее число созданных тегов |
total_edges_created |
int |
0 |
Общее число созданных ребер |
duration_seconds |
float |
0.0 |
Общая длительность |
source_results |
Dict[str, SyncResult] |
field(default_factory=dict) |
Результаты по источникам |
errors |
List[str] |
field(default_factory=list) |
Собранные ошибки |
Метод: add_result(source: str, result: SyncResult) – добавляет результат источника и обновляет итоги.
Устранение неполадок¶
Теги не создаются¶
- Убедитесь, что в базе данных CPG есть методы в
nodes_method:sql SELECT COUNT(*) FROM nodes_method; - Проверьте, что пути к файлам в CPG совпадают со структурой репозитория. Несовпадение путей (например, абсолютные и относительные) не позволит связать методы с коммитами.
- Запустите синхронизацию с
use_blame=True(значение по умолчанию) для Git – blame обеспечивает точность до строки.
Проблемы с синхронизацией Git¶
# Проверка доступности истории Git
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-git --git-since-days 7 --verbose
# Пропуск blame при работе с большими репозиториями
python -m src.services.external_context.orchestrator \
--duckdb /path/to/cpg.duckdb \
--sync-git --no-blame
Ограничение частоты запросов GitHub¶
Используйте токен аутентификации для повышения лимитов:
service = IssueSyncService(
duckdb_conn=conn,
provider="github",
repo="owner/repo",
token=os.getenv("GITHUB_TOKEN")
)
Ошибки API Sentry¶
- Проверьте правильность
org_slugиproject_slug(сверьте с URL панели управления Sentry) - Убедитесь, что токен имеет права
project:readиevent:read - Попробуйте меньший период с
--git-since-days 7для проверки подключения - Для self-hosted Sentry укажите
--sentry-urlс URL вашего экземпляра
Теги есть, но ребра отсутствуют¶
Если теги присутствуют в nodes_tag_v2, но ребра в edges_tagged_by отсутствуют, это обычно означает, что пути файлов в CPG не совпадают с путями, возвращаемыми Git/Sentry. Проверьте:
-- Просмотр значений тегов
SELECT name, value, COUNT(*) FROM nodes_tag_v2 GROUP BY name, value LIMIT 20;
-- Проверка количества ребер
SELECT COUNT(*) FROM edges_tagged_by;
Дальнейшие шаги¶
- SQL Query Cookbook – дополнительные примеры SQL-запросов для CPG
- Сценарий онбординга – использование внешнего контекста в запросах на естественном языке
- Архитектура – общая архитектура системы