Внешний мониторинг исключений, создание отчетов и расположение кода сжатия js

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

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

1. Внешний аномальный метод мониторинга

Обработка исключений Window.onerror

window.onerror Onerror перехватывает ошибки времени выполнения независимо от того, являются ли они асинхронными или неасинхронными.

window.onerror = function (msg, url, row, col, error) {
    console.log('我知道错误了');
    console.log({
        msg,  url,  row, col, error
    })
    return true;
};

Уведомление:

  • 1) Только когда функция window.onerror возвращает true, исключение не будет выброшено вверх, иначе консоль выдаст Uncaught Error: xxxxx, даже если ей известно о возникновении исключения.
  • 2) window.onerror — ошибка, которая не может отлавливать сетевые исключения. Поскольку исключения сетевых запросов не всплывают, они должны быть перехвачены на этапе захвата.Однако, хотя этот метод может перехватывать исключения сетевых запросов, невозможно определить, является ли статус HTTP 404 или другим, например 500. Также необходимо сотрудничать с журналом сервера для устранения неполадок и анализа.
window.addEventListener('error', (msg, url, row, col, error) => {
    console.log('我知道错误了');
    console.log(
        msg, url, row, col, error
    );
    return true;
}, true);

2. Ошибка обещания

Если экземпляр Promise выдает исключение, а вы не перехватываете его с помощью catch, то onerror или try-catch не могут ничего сделать, чтобы перехватить ошибку. Если вы используете много экземпляров промисов, особенно вы должны быть осторожны с некоторыми асинхронными библиотеками на основе промисов, такими как axios, потому что вы не знаете, когда эти асинхронные запросы вызовут исключение, и вы не обрабатываете его, поэтому вы лучше добавить необработанное отклонение события захвата глобального исключения A Promise.

window.addEventListener("unhandledrejection", function(e){
    e.preventDefault()
    console.log('我知道 promise 的错误了');
    console.log(e.reason);
    return true;
});

3. ошибка фрейма

Родительское окно напрямую использует window.onerror Его нельзя захватить напрямую.Если вы хотите захватить исключение iframe, есть несколько ситуаций.

1) Если ваша страница iframe и ваш основной сайт имеют одно и то же доменное имя, вы можете напрямую добавить событие onerror в iframe.

<iframe src="./iframe.html" frameborder="0"></iframe>
<script>
  window.frames[0].onerror = function (msg, url, row, col, error) {
    console.log('我知道 iframe 的错误了,也知道错误信息');
    console.log({
      msg,  url,  row, col, error
    })
    return true;
  };
</script>

2) Если встраиваемая вами страница iframe не принадлежит к тому же доменному имени, что и ваш основной сайт, но содержимое iframe не принадлежит третьей стороне

Информация об исключении может быть отправлена ​​на ведущую станцию ​​для получения путем связи с iframe. Существует множество способов взаимодействия с фреймами, например:postMessage, поле хэша или имени между доменами и т. д.

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

Во-вторых, отчет о мониторинге

После мониторинга и получения информации об ошибке следующим шагом будет отправка собранной информации об ошибке на платформу сбора информации.Существуют две часто используемые формы отправки:

  • Отправка данных через Ajax
  • Динамически создавать форму тега img
function error(msg,url,line){
   var REPORT_URL = "xxxx/cgi"; // 收集上报数据的信息
   var m =[msg, url, line, navigator.userAgent, +new Date];// 收集错误信息,发生错误的脚本文件网络地址,用户代理信息,时间
   var url = REPORT_URL + m.join('||');// 组装错误上报信息内容URL
   var img = new Image;
   img.onload = img.onerror = function(){
      img = null;
   };
   img.src = url;// 发送数据到后台cgi
}
// 监听错误上报
window.onerror = function(msg,url,line){
   error(msg,url,line);
}

3. Как найти код JS после сжатия

Первоисточник этой части: https://github.com/joeyguo/blog/issues/14.

Пример:

1. Исходный код (с ошибками)

function test() {
    noerror // <- 报错
}

test();

2. После упаковки и сжатия Webpack генерируется следующий код

!function(n){function r(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return n[e].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var t={};r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=0)}([function(n,r){function t(){noerror}t()}]);

3. Код сообщает об ошибках по расписанию и сообщает соответствующую информацию.

{ msg: 'Uncaught ReferenceError: noerror is not defined',
  url: 'http://127.0.0.1:8077/main.min.js',
  row: '1',
  col: '515' }

На данный момент количество строк и столбцов в сообщении об ошибке равно 1 и 515. В сочетании со сжатым кодом трудно обнаружить конкретные проблемы невооруженным глазом.

Вариант 1. Измените точку с запятой в сжатом коде на новую строку

uglifyjs имеет параметр конфигурации, называемый точками с запятой.Если установлено значение false, он заменит точку с запятой в сжатом коде новой строкой, чтобы улучшить читаемость кода, например

!function(n){function r(e){if(t[e])return t[e].exports
var o=t[e]={i:e,l:!1,exports:{}}
return n[e].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var t={}
r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e})},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n}
return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=0)}([function(n,r){function t(){noerror}t()}])

На данный момент количество строк и столбцов в сообщении об ошибке составляет 5 и 137, что гораздо проще найти, чем при обычном сжатии. Но в одной строке по-прежнему много кода, который нелегко найти.

Вариант 2: частичное сжатие кода js · Сохранение пробелов и разрывов строк

Когда для другого параметра конфигурации beautify uglifyjs установлено значение true, окончательный код будет отформатирован после сжатия (с сохранением пробелов и новых строк), например

!function(n) {
    // ...
    // ...
}([ function(n, r) {
    function t() {
        noerror;
    }
    t();
} ]);

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

Вариант 3: Быстрое позиционирование SourceMap

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

Поле sourcesContent в файле SourceMap соответствует содержимому исходного кода.Мы не хотим публиковать файл SourceMap во внешней сети, а храним его на платформе обработки ошибок сценариев, которая используется только для обработки ошибок сценариев. Конкретную информацию об ошибке исходного файла можно получить через файл SourceMap, а содержимое исходного файла в sourcesContent можно визуально отобразить, чтобы информацию об ошибке можно было увидеть с первого взгляда!

sourceMap

Вариант 4: часовое решение с открытым исходным кодом

sentryЖурнал ошибок представляет собой платформу отслеживания и агрегации в режиме реального времени, включая вышеуказанные программы исходной карты, и поддерживает дополнительные функции, такие как: неправильный стек вызовов, информация журнала, управление проблемами, многопроектный, многопользовательский, многоязычный клиент, и т. д., конкретное введение можно просмотреть getentry / sentry, sentry.io, временно развернутые здесь.

sentry

Справочная статья:

  1. Междоменный, все, что вам нужно знать, здесь
  2. Ошибки скриптов оптимизированы до предела — сделайте ошибки скрипта понятными с первого взгляда
  3. Практика мониторинга исключений во внешнем коде