Skip to content

feat: RSS-SE-24 implement request analytics collection - #37

Merged
dilmun1101 merged 2 commits into
feature/historyAndAnaliticsfrom
story/RSS-SE-24_implementRequestAnalyticsCollection
Jul 13, 2026
Merged

dilmun1101 merged 2 commits into
feature/historyAndAnaliticsfrom
story/RSS-SE-24_implementRequestAnalyticsCollection

Conversation

@dilmun1101

@dilmun1101 dilmun1101 commented Jul 12, 2026 •

Copy link
Copy Markdown
Collaborator

📋 Trello Task ID

  • RSS-SE-24 (Task ID / Trello Card)
  • No ID (Global fix or chore)

⚡️ Summary

  • A request history page has been added that displays the HTTP method, status, URL, duration, and payload sizes for each request.
  • For failed requests, detailed error information is shown when available.
  • The history is sorted from newest to oldest.
  • When there are no records, an informative empty-state message is displayed.

🛠 Type of change

  • feat (New feature)
  • fix (Bug fix)
  • refactor (Code improvement / Refactoring without changing logic)
  • style (Formatting, CSS)
  • docs (Documentation)
  • chore (Configs, Build)
  • test (Testing)

Summary by CodeRabbit

  • Новые возможности

    • Добавлена страница истории запросов с отображением метода, статуса, URL, длительности и размеров данных.
    • Для ошибок отображаются подробности, если они доступны.
    • История сортируется от новых записей к старым.
    • При отсутствии записей показывается информативное сообщение.
  • Исправления

    • Неавторизованных посетителей автоматически перенаправляет на главную страницу.
    • Успешные и неуспешные прокси-запросы теперь сохраняются в истории.

@vercel

vercel Bot commented Jul 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swagger-editor-app Ready Ready Preview, Comment Jul 12, 2026 8:11pm

@coderabbitai

coderabbitai Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Добавлено сохранение успешных и ошибочных прокси-запросов в Supabase. Защищённая страница загружает историю текущего пользователя и отображает метаданные запросов, размеры ответов, длительность и детали ошибок.

Changes

История запросов

Layer / File(s) Summary
Сохранение истории прокси-запросов
app/api/proxy/route.ts
Прокси измеряет запросы, получает пользователя через Supabase, сохраняет успешные и ошибочные результаты в history и возвращает соответствующий ответ.
Контракт и загрузка истории
src/features/history/api/history.ts
Добавлены тип HistoryItem и серверная функция loadHistory с фильтрацией по пользователю и сортировкой по времени.
Отображение истории и маршрутизация
app/[locale]/history/page.tsx, src/pages/history-page/*
Страница перенаправляет неавторизованных пользователей, загружает историю и отображает карточки запросов либо пустое состояние.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Proxy
  participant Supabase
  participant HistoryPage
  Client->>Proxy: Выполняет прокси-запрос
  Proxy->>Supabase: Получает пользователя
  Proxy->>Supabase: Сохраняет запись history
  Proxy-->>Client: Возвращает результат
  HistoryPage->>Supabase: Загружает историю пользователя
  Supabase-->>HistoryPage: Возвращает записи
  HistoryPage-->>Client: Отображает историю
Loading

Possibly related PRs

  • FierceSloth/swagger-editor-app#21: добавляет auth/Supabase-инфраструктуру, используемую для получения текущего пользователя.

Suggested reviewers: lexarudak

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning Описание почти полное, но для UI-изменений отсутствует обязательный раздел со скриншотами/GIF. Добавьте раздел Screenshots / GIFs с изображениями или удалите его только если UI-изменений нет.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed Заголовок кратко и точно отражает основное изменение: сбор аналитики запросов и историю запросов.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch story/RSS-SE-24_implementRequestAnalyticsCollection

Comment @coderabbitai help to get the list of available commands.

@dilmun1101
dilmun1101 marked this pull request as draft July 12, 2026 20:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/api/proxy/route.ts`:
- Around line 45-47: Измените обработку ответа в маршруте прокси вокруг
response.arrayBuffer(): не буферизуйте тело целиком перед отправкой клиенту, а
возвращайте исходный response.body для сохранения потоковой передачи. Для
responseSize используйте валидный Content-Length либо null; если подсчёт байтов
через поток необходим, примените поток без нарушения передачи ответа клиенту и
сохраните расчёт duration.
- Around line 49-65: Move the history analytics block around
supabase.auth.getUser() and the history insert out of the proxy response’s
critical path by scheduling it with the framework’s after() or equivalent
best-effort task before returning. Preserve the existing analytics fields, and
catch and log errors from both getUser() and insert() so RLS or schema failures
are visible without delaying or failing the proxy response.

In `@src/features/history/api/history.ts`:
- Around line 19-23: Ограничьте запрос истории в функции API вокруг цепочки
Supabase для таблицы history фиксированным размером страницы и добавьте
курсорную пагинацию по timestamp (с id как стабильным tie-breaker). Принимайте
курсор и размер страницы из параметров запроса, применяйте соответствующий
фильтр до сортировки, запрашивайте на одну запись больше для определения
следующей страницы и возвращайте данные вместе с next cursor.

In `@src/pages/history-page/ui/history-page.tsx`:
- Around line 18-45: Update the history page component and its caller to receive
the active route locale, replace hardcoded labels with the existing translation
mechanism, and pass that locale to Date.toLocaleString for timestamp formatting.
Preserve the current empty-state, item rendering, and conditional error display
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5e9d6222-ca0c-4046-8de8-cc3acdea9572

📥 Commits

Reviewing files that changed from the base of the PR and between 7cdc9a7 and 794075e.

📒 Files selected for processing (5)
  • app/[locale]/history/page.tsx
  • app/api/proxy/route.ts
  • src/features/history/api/history.ts
  • src/pages/history-page/index.ts
  • src/pages/history-page/ui/history-page.tsx

Comment thread app/api/proxy/route.ts
Comment on lines +45 to +47
const responseBuffer = await response.arrayBuffer();
const duration = Date.now() - startedAt;
const responseSize = responseBuffer.byteLength;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Не буферизуйте весь ответ прокси.

response.arrayBuffer() удерживает в памяти весь ответ произвольного удалённого URL до начала передачи клиенту. Большие ответы отключат стриминг и могут исчерпать память обработчика. Считайте байты через поток либо сохраняйте валидный Content-Length/null, но возвращайте исходный поток ответа.

Also applies to: 68-72

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/api/proxy/route.ts` around lines 45 - 47, Измените обработку ответа в
маршруте прокси вокруг response.arrayBuffer(): не буферизуйте тело целиком перед
отправкой клиенту, а возвращайте исходный response.body для сохранения потоковой
передачи. Для responseSize используйте валидный Content-Length либо null; если
подсчёт байтов через поток необходим, примените поток без нарушения передачи
ответа клиенту и сохраните расчёт duration.

Comment thread app/api/proxy/route.ts
Comment on lines +49 to +65
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();

if (user) {
await supabase.from('history').insert({
user_id: user.id,
url: targetUrl,
method,
status: response.status,
duration,
request_size: requestSize,
response_size: responseSize,
timestamp: new Date().toISOString(),
error_details: response.ok ? null : `HTTP ${response.status}`,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 2 '"next"|`@supabase/supabase-js`' package.json 2>/dev/null || true
rg -n -C 4 "supabase\.auth\.getUser|\.from\('history'\)\.insert" app/api/proxy/route.ts

curl -fsSL https://nextjs.org/docs/app/api-reference/functions/after \
  | grep -i -m 3 'route handler'

curl -fsSL https://supabase.com/docs/reference/javascript/insert \
  | grep -i -m 3 'error'

Repository: FierceSloth/swagger-editor-app

Length of output: 50388


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n== app/api/proxy/route.ts ==\n'
wc -l app/api/proxy/route.ts
sed -n '1,220p' app/api/proxy/route.ts

printf '\n== поиски after / background / history insert ==\n'
rg -n "after\\(|supabase\\.auth\\.getUser\\(|from\\('history'\\)\\.insert|AbortController|timeout" app/api/proxy app -g '!**/node_modules/**' || true

Repository: FierceSloth/swagger-editor-app

Length of output: 4877


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n== Next.js after docs snippet ==\n'
python3 - <<'PY'
import urllib.request, re
url = 'https://nextjs.org/docs/app/api-reference/functions/after'
html = urllib.request.urlopen(url, timeout=20).read().decode('utf-8', 'ignore')
for pat in [
    r'Route Handlers',
    r'after\(',
    r'can be used in Route Handlers',
    r'cannot be used in Route Handlers',
]:
    m = re.search(pat, html, re.I)
    print(pat, '=>', bool(m))
PY

printf '\n== Supabase insert docs snippet ==\n'
python3 - <<'PY'
import urllib.request, re
url = 'https://supabase.com/docs/reference/javascript/insert'
html = urllib.request.urlopen(url, timeout=20).read().decode('utf-8', 'ignore')
for pat in [r'error', r'data', r'select\(', r'RLS', r'row level security']:
    m = re.search(pat, html, re.I)
    print(pat, '=>', bool(m))
PY

Repository: FierceSloth/swagger-editor-app

Length of output: 2796


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n== app/api/proxy/route.ts line numbers ==\n'
nl -ba app/api/proxy/route.ts | sed -n '1,180p'

printf '\n== package.json relevant deps ==\n'
nl -ba package.json | sed -n '1,90p'

printf '\n== search for after import/use in repo ==\n'
rg -n "from 'next/server'|from \"next/server\"|\\bafter\\b" app lib src . -g '!**/node_modules/**' || true

Repository: FierceSloth/swagger-editor-app

Length of output: 251


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import urllib.request, re
html = urllib.request.urlopen('https://nextjs.org/docs/app/api-reference/functions/after', timeout=20).read().decode('utf-8', 'ignore')
text = re.sub(r'<script\b.*?</script>|<style\b.*?</style>', ' ', html, flags=re.S|re.I)
text = re.sub(r'<[^>]+>', ' ', text)
text = re.sub(r'\s+', ' ', text)
for needle in [
    'Route Handlers',
    'can be used in Server Components, Server Actions, Route Handlers, and Middleware',
    'after is a function that allows you to schedule work to be done after a response has been sent',
    'after callback',
]:
    idx = text.lower().find(needle.lower())
    print(f'--- {needle} ---')
    print(text[idx-250:idx+600] if idx != -1 else 'NOT FOUND')
PY

Repository: FierceSloth/swagger-editor-app

Length of output: 2762


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import urllib.request, re
html = urllib.request.urlopen('https://supabase.com/docs/reference/javascript/insert', timeout=20).read().decode('utf-8', 'ignore')
text = re.sub(r'<script\b.*?</script>|<style\b.*?</style>', ' ', html, flags=re.S|re.I)
text = re.sub(r'<[^>]+>', ' ', text)
text = re.sub(r'\s+', ' ', text)
for needle in [
    'If you do not select',
    'errors',
    'RLS',
    'row level security',
    'returns',
]:
    idx = text.lower().find(needle.lower())
    print(f'--- {needle} ---')
    print(text[idx-250:idx+600] if idx != -1 else 'NOT FOUND')
PY

Repository: FierceSloth/swagger-editor-app

Length of output: 2762


Вынесите аналитику из критического пути прокси.
В обеих ветках getUser() и insert() выполняются до return, поэтому задержка Supabase тормозит ответ; текущий AbortController это не покрывает. Ошибки insert() тоже игнорируются, так что RLS/схема могут молча терять историю. Перенесите запись в after()/best-effort задачу и логируйте ошибки записи.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/api/proxy/route.ts` around lines 49 - 65, Move the history analytics
block around supabase.auth.getUser() and the history insert out of the proxy
response’s critical path by scheduling it with the framework’s after() or
equivalent best-effort task before returning. Preserve the existing analytics
fields, and catch and log errors from both getUser() and insert() so RLS or
schema failures are visible without delaying or failing the proxy response.

Comment on lines +19 to +23
const { data, error } = await supabase
.from('history')
.select('id, user_id, url, method, status, duration, timestamp, request_size, response_size, error_details')
.eq('user_id', userId)
.order('timestamp', { ascending: false });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift

Ограничьте и пагинируйте историю.

Запрос загружает все записи пользователя, а прокси создаёт запись для каждого успешного и ошибочного вызова. Со временем страница будет читать, сериализовать и рендерить неограниченный объём данных. Добавьте размер страницы и курсорную пагинацию.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/history/api/history.ts` around lines 19 - 23, Ограничьте запрос
истории в функции API вокруг цепочки Supabase для таблицы history фиксированным
размером страницы и добавьте курсорную пагинацию по timestamp (с id как
стабильным tie-breaker). Принимайте курсор и размер страницы из параметров
запроса, применяйте соответствующий фильтр до сортировки, запрашивайте на одну
запись больше для определения следующей страницы и возвращайте данные вместе с
next cursor.

Comment on lines +18 to +45
<h1>History</h1>
<p>You haven&apos;t executed any requests yet.</p>
</div>
);
}

return (
<div>
<h1>History</h1>

<div>
{items.map((item) => (
<div key={item.id}>
<div>
<span>{item.method}</span>
<span>Status: {item.status}</span>
</div>

<p>{item.url}</p>

<div>
<span>Duration: {item.duration} ms</span>
<span>Request size: {formatBytes(item.request_size)}</span>
<span>Response size: {formatBytes(item.response_size)}</span>
<span>{new Date(item.timestamp).toLocaleString()}</span>
</div>

{item.error_details && <p>Error: {item.error_details}</p>}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Верните локализацию текста и даты.

Маршрут использует [locale], но все новые подписи захардкожены на английском, а toLocaleString() использует локаль сервера, а не активную локаль маршрута. Передавайте локаль в компонент, используйте переводы и форматируйте дату через неё.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/history-page/ui/history-page.tsx` around lines 18 - 45, Update the
history page component and its caller to receive the active route locale,
replace hardcoded labels with the existing translation mechanism, and pass that
locale to Date.toLocaleString for timestamp formatting. Preserve the current
empty-state, item rendering, and conditional error display behavior.

@dilmun1101
dilmun1101 marked this pull request as ready for review July 13, 2026 09:25
@dilmun1101 dilmun1101 changed the title Story/rss se 24 implement request analytics collection feat: RSS-SE-24 implement request analytics collection Jul 13, 2026
@dilmun1101
dilmun1101 merged commit 1e8b6e0 into feature/historyAndAnalitics Jul 13, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview — 794075e8 Deployed Jul 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant