Skip to content

Справочник

Структура записи лога

Каждое захваченное событие, независимо от типа транспорта, сохраняется как 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