Справочник
Структура записи лога
Каждое захваченное событие, независимо от типа транспорта, сохраняется как UnifiedLogEntry:
typescript
interface UnifiedLogEntry {
id: string // Уникальный UUID-подобный идентификатор
type: 'http' | 'websocket' | 'sse'
// Тайминг
startTime: number // Unix-таймстамп начала запроса (мс)
endTime: number | null // Unix-таймстамп завершения
duration: number | null // endTime - startTime, миллисекунды
// Идентичность запроса
url: string
method: string // HTTP-глагол, или тип события WebSocket/SSE
// Специфично для HTTP (null для WebSocket / SSE)
http: {
status: number | null // например 200, 404, 500
statusText: string | null // например "OK", "Not Found"
protocol: string | null // например "HTTP/1.1", "HTTP/2"
} | null
// Специфично для WebSocket (null для HTTP / SSE)
websocket: {
readyState: number // 0 CONNECTING | 1 OPEN | 2 CLOSING | 3 CLOSED
eventType: 'connection' | 'open' | 'message' | 'error' | 'close'
direction: 'incoming' | 'outgoing' | null
code: number | null // Код закрытия (1000 = обычное, 1001 = уход со страницы, …)
reason: string | null
wasClean: boolean | null
} | null
// Специфично для SSE (null для HTTP / WebSocket)
sse: {
readyState: number // 0 CONNECTING | 1 OPEN | 2 CLOSED
eventType: string | null // Именованный тип события, или null для стандартного "message"
lastEventId: string | null
} | null
// Заголовки
requestHeaders: Record<string, string> // Санитизированные заголовки запроса
responseHeaders: Record<string, string> // Санитизированные заголовки ответа
// Тела
request: {
body: any | null // Разобранное тело (объект, строка, FormData и т. д.)
bodyRaw: string | null // Сырая сериализованная строка тела
bodySize: number | null // Размер в байтах
bodyType: string | null // MIME-тип, выведенный из Content-Type
}
response: {
body: any | null
bodyRaw: string | null
bodySize: number | null
bodyType: string | null
}
// Ошибки
error: {
occurred: boolean
message: string | null
name: string | null // например "TypeError", "NetworkError"
stack: string | null
}
// Метаданные
metadata: {
clientType: 'fetch' | 'xhr' | 'websocket' | 'eventsource'
redirected: boolean
retryCount: number
timestamp: string // Таймстамп ISO 8601 в момент создания лога
}
// Путь маршрута Vue Router в момент инициации запроса.
// Заполняется только когда в опциях плагина установлено `enrichWithRoute: true`.
route?: string
}Статистика
getStats() возвращает объект NetworkStats:
typescript
interface NetworkStats {
totalRequests: number
totalErrors: number
averageDuration: number // Среднее время ответа в мс
totalDataSent: number // Общий объём байт тела запроса
totalDataReceived: number // Общий объём байт тела ответа
requestsByMethod: Record<string, number> // { GET: 42, POST: 17, … }
requestsByStatus: Record<string, number> // { '200': 55, '404': 3, '500': 1, … }
slowestRequests: UnifiedLogEntry[] // Топ-10 по длительности (по убыванию)
largestRequests: UnifiedLogEntry[] // Топ-10 по общему размеру тела (по убыванию)
sseEventCount: number // Общее число захваченных событий SSE
}getStatsSummary() возвращает те же данные в виде отформатированной многострочной строки, полезной для логирования в консоль.
Архитектура
vue-network-dashboard/
├── src/
│ ├── core/
│ │ ├── NetworkDashboard.ts # Оркестратор — перехватчики, реестр моков, точки останова, жизненный цикл
│ │ ├── formatters.ts # HTTPFormatter, WebSocketFormatter, SSEFormatter
│ │ ├── openApiParser.ts # Парсит OpenAPI 3.x / Swagger 2.x JSON → MockRule[]
│ │ └── types.ts # UnifiedLogEntry, MockRule, BreakpointRule, NetworkStats, …
│ ├── interceptors/
│ │ ├── fetchInterceptor.ts # Патчит window.fetch (незавершённое состояние + поддержка моков)
│ │ ├── xhrInterceptor.ts # Патчит прототип XMLHttpRequest (WeakMap + поддержка моков)
│ │ ├── websocketInterceptor.ts # Заменяет window.WebSocket
│ │ └── sseInterceptor.ts # Заменяет window.EventSource
│ ├── store/
│ │ └── logStore.ts # Реактивное хранилище Vue — addLog, updateLog, экспорт HAR/JSON/CSV
│ ├── plugins/
│ │ └── vuePlugin.ts # Плагин Vue 3 + composable useNetworkDashboard + API моков
│ ├── adapters/
│ │ ├── sentry.ts # createSentryAdapter — breadcrumbs + события Sentry
│ │ └── opentelemetry.ts # createOpenTelemetryAdapter — OTel-спаны на каждый запрос
│ ├── utils/
│ │ ├── sanitizer.ts # Редактирование заголовков, удаление полей, маскирование PII
│ │ ├── helpers.ts # generateId, formatBytes, getContentType
│ │ └── sizeCalculator.ts # calculateSize, getDataType, safeStringify
│ ├── view/
│ │ ├── components/
│ │ │ ├── NetworkDebugger.vue # Основная перетаскиваемая панель (вкладки logs / stats / timeline / mocks)
│ │ │ ├── LogEntry.vue # Одна строка — незавершённое состояние, бейдж мока, выбор для диффа
│ │ │ ├── FilterBar.vue # Вкладки типа, фильтры URL, тела, метода, статуса, длительности
│ │ │ ├── StatsPanel.vue # Живая статистика со столбцами распределения
│ │ │ ├── MockPanel.vue # Редактор правил моков — группы, условия, transform, импорт OpenAPI
│ │ │ ├── BreakpointPanel.vue # Правила точек останова + карточки приостановленных запросов с редактируемыми полями
│ │ │ ├── ReplayModal.vue # Модальное окно Edit & Replay — URL, метод, заголовки, тело
│ │ │ ├── SessionComparePanel.vue # Просмотр диффа HAR — две сессии бок о бок
│ │ │ ├── NetworkTimeline.vue # Waterfall-диаграмма
│ │ │ └── DiffPanel.vue # Дифф заголовков и тела между двумя записями лога на основе LCS
│ │ ├── composables/
│ │ │ ├── useLogFilter.ts # Реактивное состояние фильтров (url, body, method, status, …)
│ │ │ └── useHotkey.ts # Хелпер привязки клавиатурного шортката
│ │ └── styles/
│ │ ├── variables.scss # Дизайн-токены (цвета, отступы, типографика)
│ │ └── debugger.scss # Все стили компонентов
│ ├── devtools.ts # setupDevtools() — инспектор Vue DevTools + слой таймлайна
│ ├── nuxt.ts # Модуль Nuxt 3 (defineNuxtModule)
│ └── runtime/
│ └── nuxt-plugin.ts # Клиентский плагин Nuxt — регистрируется автоматически через nuxt.ts
└── demo/ # Демо-приложение (Vite + Vue 3)Плагин не имеет runtime-зависимостей помимо Vue 3. Он полагается только на стандартные API браузера (window.fetch, XMLHttpRequest, WebSocket, EventSource).
Лицензия
MIT