Логирование сообщений консоли и стека вызова функций в JavaScript с последующей передачей на сервер для отладки
При отладке javascript в реальных условиях нужно отслеживать не только сам факт ошибки, но и понять цепочку событий, которая к ней привела. Для понимания проблемы нужно знать стек вызова функций и хорошо бы получить сообщения, которые выводились вашим скриптом в консоль. Ниже приведен мой код, используемый в сайтах, который позволяет решить эти задачи и оперативно решать возникающие проблемы на моих сайтах и сайтах клиентов:
<script>
window.onerror = function (msg, url, line) {
try {
if (msg && url && typeof url != "undefined") if (url.indexOf(window.location.hostname) >= 0) {
var data = new FormData();
data.append('msg', msg);
data.append('url', url);
data.append('ref', document.location.href);
data.append('line', line);
//if(typeof console.trace ==="function") data.append('trace', console.trace());
data.append('logs', console.logs.slice(-10).join("\n"));
data.append('trace', getStackTrace().join('\n'));
if (typeof obj !== "undefined") data.append('obj', JSON.stringify(obj));
var xhr = new XMLHttpRequest();
xhr.open('POST', '/jserr.php');
xhr.send(data);
console.log('Отправил ошибку: ', msg);
return true;
}
console.log(msg, url, line);
} catch (e) {
console.error('Не отправил ошибку: ', e);
}
return true;
};
console.stdlog = console.log.bind(console);
console.stdwarn = console.warn.bind(console);
console.stderror = console.error.bind(console);
console.logs = [];
console.error = function () {
console.logs.push('error:' + objToString(arguments));
console.stderror.apply(console, arguments);
}
console.warn = function () {
console.logs.push('warn:' + objToString(arguments));
console.stdwarn.apply(console, arguments);
}
console.log = function () {
console.logs.push(objToString(arguments));
console.stdlog.apply(console, arguments);
}
function objToString(obj, ndeep) {
if (obj == null) {
return String(obj);
}
switch (typeof obj) {
case "string":
return '"' + obj + '"';
case "function":
return obj.name + '()' || obj.toString();
case "object":
if (ndeep > 3) {
return '...';
} // исключаю бесконечную рекурсию
if (//Array.isArray(obj) ||
obj.join !== undefined) {
return '[' + obj.join(',') + ']';
} else {
return '{' + Object.keys(obj).map(function (key) {
if (key === 'self') return 'self:..';
else if (ndeep > 1 && (key === 'window' || key === 'document' || key === 'location' || key === 'top')) return key + ':..';
else return key + ': ' + objToString(obj[key], (ndeep || 1) + 1);
}).join(',') + '}';
}
default:
return obj.toString();
}
}
function getStackTrace() {
let stack = new Error().stack || '';
stack = stack.split('\n').map(function (line) {
return line.trim();
});
return stack.splice(stack[0] == 'Error' ? 2 : 1);
}
</script>
// setTimeout('console.warn("TEST");document.getElementsByTagName("INPUT")[0].value.aa;adlhds();',1000);
И функция получения и сохранения данных на PHP jserr.php:
< ?php
define("AdminMail","МЫЛО@АДМИНА"); // период кеширования сутки 24*60*60=86400
if (
$_SERVER['REQUEST_METHOD'] !== 'POST' ||
(
empty($_SERVER['HTTP_REFERER']) ||
strpos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) === false
)
) exit;
if (
!isset($_POST['msg']) &&
!isset($_POST['url']) &&
!isset($_POST['line'])
) exit;
$key = md5($_POST['url'] . ':' . $_POST['line'].':'.$_POST['msg']);
$file = __DIR__ . '/log_error/js' . $key . '.log';
if(!is_file($file)){
$msg = var_export($_POST,!0)./*"Message: ".$_POST['msg']."\n"."\n".
"URL: ".$_POST['url']."\n".
"Ref: ".$_POST['ref']."\n".
"Line: ".$_POST['line']."\n".
(empty($_POST['trace'])?'':"trace: ".$_POST['trace']."\n").
(empty($_POST['trace'])?'':"trace: ".$_POST['trace']."\n").*/
"\n".
"Browser: ".$_SERVER['HTTP_USER_AGENT'];
file_put_contents($file, $msg, LOCK_EX);
mail(AdminMail, "Javascript error", $msg,
"From: <noreply@".preg_replace("/www\./i","",$_SERVER['HTTP_HOST']).">\nContent-Type: text/plain; charset=utf-8");
}
?>
.
Прокомментировать/Отблагодарить