Проект реального боя - предварительная проработка системы закопанных очков

внешний интерфейс JavaScript

предисловие

В последнее время было много разного.Редко бывает, что нужно время, чтобы наверстать предыдущую серию.Теперь начинает идти серия, которая должна тебе закопанную точку.

Зачем вам нужна система захороненных точек?

в кино

Фронтенд-разработка siege lion счастливое кодирование, очень горжусь тем, что занимаюсь раздельной разработкой бизнеса и пользовательского интерфейса, различные шаблоны проектирования, оптимизация алгоритмов по очереди, код написан идеально (код трудового капитала - первый в мире), без ошибок , программа идеальна, Совместимость №1, код может драться и сопротивляться высокому качеству. Легко зарегистрируйтесь после работы и идите домой, чтобы присмотреть за ребенком.

в реальности

На самом деле среда разработки — это не то же самое, что производственная среда, и каким бы совершенным ни был процесс тестирования, все равно будут пропущенные тесты. С учетом использования пользователемКлиентская среда, сетевая средаСуществует ряд неопределенных факторов.

Так что в процессе разработки надо помнить три принципа (я вру)

  1. Не бывает идеального кода, есть не обнаруженные ошибки
  2. Никогда не доверяйте тестовой среде, ни одна тестовая среда не охватывает все онлайн-ситуации
  3. Если нет отзывов в сети, не сомневайтесь, проблема должна быть спрятана глубоко-глубоко

Что такое система скрытых точек

Скрытая точка похожа на камеру в городе: с точки зрения продукта она может отслеживать поведение пользователей в наших продуктах, обеспечивая основу для итерации продукта и стабильности проекта.КТО, КОГДА, ГДЕ, КАК, ЧТО являются основными аспектами сбора данных.

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

Могилы можно условно разделить на три категории:

  1. Нет следов похороненных- Без разбора собирать всю информацию о странице, включая вход и выход на страницу, клики по событиям и т. д. Для получения полезной информации требуется сброс данных.
  2. Визуализируйте закопанные точки- Получите определенные баллы в соответствии с созданной структурой страницы и проанализируйте баллы отдельно
  3. Вручную похороните бизнес-код- В соответствии с конкретным и сложным бизнесом удалите два вышеуказанных места, которые не могут быть покрыты, и похороните бизнес-код.
код похоронен Визуализируйте закопанные точки Нет следов похороненных
Типичная сцена Бесследные закопанные точки не могут быть покрыты, например, требуются бизнес-данные Простая и каноничная сцена страницы Простая и стандартизированная сцена страницы,
Преимущество Очистить бизнес-данные Стоимость разработки низкая, и операторы могут напрямую настраивать соответствующие закопанные точки. Настройка не требуется, данные можно отследить
недостаточный Данные невозможно отследить, а стоимость разработки высока. Бизнес-данные не могут быть связаны, и данные нельзя отследить Объем данных велик и не может быть связан с бизнес-данными.

В большинстве случаев мы можем собрать все информационные данные через скрытую точку без следов, а затем сотрудничать с визуальной скрытой точкой, чтобы найти определенную точку, чтобы можно было соответствующим образом проанализировать большую часть информации о скрытой точке.

В особых случаях вы можете добавить больше бизнес-кодов, чтобы вручную закопать точки, чтобы иметь дело с особыми сценариями (в большинстве случаев сильный бизнес связан с обычными кликами, а события обновления не имеют ничего общего с информацией, о которой необходимо сообщать).

Скрытая разработка SDK

Сбор и анализ данных о захороненных точках

  • Основные данные события
    • время события
    • Моментальный снимок информации о странице, как это происходит
  • страница
    • Страница ПВ, УФ
    • Продолжительность пребывания на странице пользователя
    • событие перехода на страницу
    • Страница уходит в фон
    • Пользователь покидает страницу
  • Информация о пользователе
    • пользовательский идентификатор
    • Отпечаток пользовательского устройства
    • Информация об устройстве
    • ip
    • позиция
  • Поведение пользователя при работе
    • пользовательские клики
      • нажмите цель
  • AJAX-запрос страницы
    • запрос выполнен
    • Запрос не выполнен
    • Истекло время запроса
  • ошибка страницы
    • Ошибка загрузки ресурса
    • Ошибка запуска JS
  • Ресурс загружает новую производительность
  • картина
  • сценарий
  • Производительность нагрузки страницы

Вышеуказанные данные прошли3 измерениядля определения скрытых событий

  • ·LEVEL: описывает уровень журнала скрытых данных.
    • INFO: Обычные записи данных о некоторых пользовательских операциях, успешных запросах, загрузке ресурсов и т.д.
    • ERROR: ошибка JS, ошибка интерфейса и т. д. записи данных типа ошибки
    • DEBUG: зарезервировано разработчиками для возврата записей данных для устранения ошибок путем ручного вызова
    • WARN: зарезервировано для разработчиков, чтобы возвращать записи данных об аномальном поведении пользователей путем ручного вызова
  • CATEGORY: Опишите классификацию данных скрытых точек.
    • TRACK: Жизненный цикл встроенного объекта SDK управляет всеми встроенными данными.
      • WILL_MOUNT: объект sdk должен быть инициализирован и загружен, генерируется идентификатор по умолчанию, и все связанные события отслеживаются.
      • DID_MOUNTED: Инициализация объекта sdk завершена, и асинхронные операции, такие как получение отпечатков пальцев устройства, завершены.
    • AJAX: данные, связанные с AJAX
    • ERROR: данные, связанные с исключением, на странице.
    • PERFORMANCE: данные о производительности
    • OPERATION: Данные, связанные с операциями пользователя.
  • EVENT_NAME: конкретное название события

В соответствии с указанными выше размерами мы можем просто спроектировать следующую архитектуру

В соответствии с архитектурой на приведенном выше рисунке перейдите к следующей конкретной разработке кода.

прокси-запрос

В браузере в основном есть 2 метода запроса, один из нихXMLHttpRequest, одинFetch.

Прокси XMLHttpRequest

function NewXHR() {
  var realXHR: any = new OldXHR(); // 代理模式里面有提到过
  realXHR.id = guid()
  const oldSend = realXHR.send;

  realXHR.send = function (body) {
    oldSend.call(this, body)
    //记录埋点
  }
  realXHR.addEventListener('load', function () {
    //记录埋点
  }, false);
  realXHR.addEventListener('abort', function () {
    //记录埋点
  }, false);

  realXHR.addEventListener('error', function () {
    //记录埋点
  }, false);
  realXHR.addEventListener('timeout', function () {
    //记录埋点
  }, false);

  return realXHR;
}

Прокси-выборка

 const oldFetch = window.fetch;
  function newFetch(url, init) {
    const fetchObj = {
      url: url,
      method: method,
      body: body,
    }
    ajaxEventTrigger.call(fetchObj, AJAX_START);
    return oldFetch.apply(this, arguments).then(function (response) {
      if (response.ok) {
       //记录埋点
      } else {
       //上报错误
      }
      return response
    }).catch(function (error) {
      fetchObj.error = error
        //记录埋点      
        throw error
    })
  }

страница монитораPV,UV

При входе на страницу мы алгоритмически генерируем уникальныйsession idВ качестве глобального поведения похороненного идентификатора, отчетливый идентификатор пользователя, оборудование отпечатков пальцев, информация об устройстве. В случае, когда пользователь не вошел в систему, отпечаток пальцев рассчитывается по устройствуUV,пройти черезsession idрассчитатьPV.

ловушка исключения

Исключением является необычный инцидент, который мешает нормальному ходу программы.

RUNTIME ERROR

существуетJSсквозьwindow.onerrorа такжеwindow.addEventListener('error', callback)Перехват исключений во время выполнения, обычно используетсяwindow.onerror, это более совместимо.

window.onerror = function(message, url, lineno, columnNo, error) {
    const lowCashMessage = message.toLowerCase()
    if(lowCashMessage.indexOf('script error') > -1) {
      return
    }
    const detail = {
      url: url    
      filename: filename,
      columnNo: columnNo,
      lineno: lineno,
      stack: error.stack,
      message: message
    }
    //记录埋点
}

Script Error

Здесь мы фильтруемScript Error, основная причина этого заключается в том, что сторонний междоменный скрипт, загруженный на страницу, сообщает об ошибке, например, той, что размещена на стороннем CDN.jsсценарий. Такие проблемы труднее устранить. Решения:

  • ОткрытьCORS(Совместное использование ресурсов между источниками, совместное использование ресурсов между доменами), следующие шаги
    • <srcipt src="another domain/main.js" cossorigin="anonymous"></script>
    • ИсправлятьAccess-Control-Allow-Origin: * | 指定域名
  • использоватьtry catch
      <script scr="crgt.js"></script> //加载crgt脚本,window.crgt = {getUser: () => string}
      try{
          window.crgt.getUser();
      }catch(error) {
          throw error // 输出正确的错误堆栈
      }
    

Promise reject

jsНе удалось передать асинхронное исключениеonerrorЗахват метода, когда объект Promise отклоняется и не обрабатывается одновременно броситunhandledrejectionОшибка не будет поймана вышеописанным методом, поэтому вам нужно добавить отдельное событие обработки.

window.addEventListener("unhandledrejection", event => {
  throw event.reason
});

Исключение при загрузке ресурсов

В браузере можноwindow.addEventListener('error', callback)способ отслеживать исключения загрузки ресурсов, такие какjsилиcssФайл скрипта отсутствует.

window.addEventListener('error', (event) => {
  if (event.target instanceof HTMLElement) {
    const target = parseDom(event.target, ['src']);
    const detail = {
      target: target,
      path: parseXPath(target),
    }
    //  记录埋点
  }
}, true)

Следите за поведением пользователей

пройти черезaddEventListener clickмониторclickмероприятие

window.addEventListener('click', (event) => {
    //记录埋点
}, true)

здесь через компонентdisplaNameпозиционировать элемент,displaNameПредставляет каталог файлов компонента, напримерsrc/components/Form.jsКомпоненты, экспортированные в файлFormItemпройти черезbabel pluginдобавлять свойства автоматически@components/Form.FormItem, либо пользователь активно добавляет в компонентstaticАтрибутыdisplayName.

Изменения маршрутизации страницы

  • hashRouter

Мониторинг изменений хэша страницы и анализ хэша

window.addEventListener('hashchange', event => {
  const { oldURL, newURL } = event;
  const oldURLObj = url.parseUrl(oldURL);
  const newURLObj = url.parseUrl(newURL);
  const from = oldURLObj.hash && url.parseHash(oldURLObj.hash);
  const to = newURLObj.hash && url.parseHash(newURLObj.hash);
  if(!from && !to ) return;
  // 记录埋点
})

Следить за страницей, чтобы покинуть

пройти черезaddEventListener beforeunloadПрослушивание событий ухода со страницы

window.addEventListener('beforeunload', (event) => {
    //记录埋点
})

Архитектура SDK

class Observable {
    constructor(observer) {
        observer(this.emit)
    }
    emit = (data) => {
        this.listeners.forEach(listener => {
            listener(data)
        })
    }
    listeners = [];
    
    subscribe = (listener) => {
        this.listeners.push(listeners);
        return () => {
            const index = this.listeners.indexOf(listener);
            if(index === -1) {
                return false
            }
            
            this.listeners.splice(index, 1);
            return true;
        }
     }
}
const clickObservable = new Observable((emit) => {
    window.addEventListener('click', emit)
})

Однако, имея дело сajax, необходимо объединить несколько данных вместе, необходимо выполнить операцию слияния, это не так элегантно, и его трудно адаптировать к работе последующего сложного потока данных.

const ajaxErrorObservable = new Observable((emit) => {
    window.addEventListener(AJAX_ERROR, emit)
})

const ajaxSuccessObservable = new Observable((emit) => {
    window.addEventListener(AJAX_SUCCESS, emit)
})
const ajaxTimeoutObservable = new Observable((emit) => {
    window.addEventListener(AJAX_TIMEOUT, emit)
})

можешь выбратьRxJSоптимизировать код

export const ajaxError$ = fromEvent(window, 'AJAX_ERROR', true)
export const ajaxSuccess$ = fromEvent(window, 'AJAX_SUCCESS', true)
export const ajaxTimeout$ = fromEvent(window, 'AJAX_TIMEOUT', true)
ajaxError$.pipe(
    merge(ajaxSuccess$, ajaxTimeout$), 
    map(data=> (data) => ({category: 'ajax', data; data}))
    subscribe(data => console.log(data))

пройти черезmerge, mapДва оператора завершают объединение и обработку данных.

поток данных

Структура проекта

  • core
    • event$слияние потоков данных
    • snapshotПолучите снимок текущего устройства, например.url,userID,router
    • trackКласс захороненных точек, комбинированный поток данных и журнал.
  • logger
    • loggerКласс журнала
      • info
      • warn
      • debug
      • error
  • observable
    • ajax
    • beforeUpload
    • opeartion
    • routerChange
    • logger
    • track

Ссылаться на

конец

Самостоятельно построенная система скрытых точек — это вопрос, который требует сотрудничества между интерфейсом и сервером.Если рабочей силы недостаточно, рекомендуется использовать сторонние аналитические плагины, такие какSentryдостаточно для большинства повседневного использования

Тем не менее, все же рекомендуется узнать больше, и когда сторонние плагины не могут удовлетворить потребности бизнеса, вы можете использовать их.

Боевой сериал проекта

Боевой проект | Обработка кеша

Бой проекта|Базовая инкапсуляция запросов

Борьба с проектами | Реализация уровня бизнес-процессинга