Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Где сохраняется логирование в браузере и на сервере?
Логирование — это очень важная тема для отладки приложений. Рассмотрим все места, где сохраняются логи в фронтенде и бэкенде.
Фронтенд (браузер)
1. Browser Console (консоль браузера)
Самое очевидное место — вкладка Console в DevTools:
// Все эти сообщения идут в консоль браузера
console.log('Information');
console.warn('Warning');
console.error('Error');
console.info('Info');
console.debug('Debug');
Как открыть:
- Chrome/Firefox: F12 или Ctrl+Shift+J
- Safari: Cmd+Option+I
ВАЖНО: эти логи удаляются при закрытии страницы!
console.log('This message is temporary');
// Перезагрузи страницу — логи исчезнут
2. localStorage (постоянное хранилище в браузере)
Можно сохранить логи в localStorage для последующего просмотра:
function logToStorage(message, level = 'info') {
const logs = JSON.parse(localStorage.getItem('app_logs') || '[]');
logs.push({
timestamp: new Date().toISOString(),
level,
message
});
localStorage.setItem('app_logs', JSON.stringify(logs));
}
// Использование
logToStorage('User logged in', 'info');
logToStorage('Payment failed', 'error');
// Просмотр
const logs = JSON.parse(localStorage.getItem('app_logs'));
console.table(logs);
// Очистка
localStorage.removeItem('app_logs');
Ограничения localStorage:
- Хранит только 5-10 MB
- Хранит только текст (JSON)
- Очищается при очистке кэша браузера
3. IndexedDB (объёмное хранилище)
Для большого количества логов используй IndexedDB:
const dbRequest = indexedDB.open('AppLogs', 1);
dbRequest.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains('logs')) {
db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
}
};
dbRequest.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction('logs', 'readwrite');
const store = transaction.objectStore('logs');
// Добавить лог
store.add({
timestamp: new Date(),
level: 'error',
message: 'Something went wrong'
});
};
Преимущества IndexedDB:
- Хранит до 50 MB+ (зависит от браузера)
- Асинхронный API
- Хорошо структурирован
4. sessionStorage
Времение жизни = время открытия вкладки:
// Сохраняется только во время сессии
sessionStorage.setItem('session_logs', JSON.stringify([
{ message: 'User action 1', time: Date.now() },
{ message: 'User action 2', time: Date.now() }
]));
// При закрытии вкладки — всё удалится
5. Network вкладка (Network tab)
Network вкладка в DevTools сохраняет логи всех HTTP запросов:
// Все эти запросы видны в Network tab
fetch('/api/users');
fetch('/api/posts', { method: 'POST', body: '...' });
Сохранение логов Network:
- Chrome: Gear icon → "Log XMLHttpRequest"
- Можно экспортировать как HAR файл
6. Performance вкладка
Performance вкладка логирует:
- Время загрузки
- Время рендера
- Длительность функций (если добавить performance markers)
// Добавить маркер производительности
performance.mark('api-start');
await fetch('/api/data');
performance.mark('api-end');
performance.measure('api-call', 'api-start', 'api-end');
// Просмотр в Performance tab (F12 -> Performance)
Отправка логов на сервер
1. Beacon API (асинхронно)
Отправляет логи без блокирования:
window.addEventListener('beforeunload', () => {
const logs = JSON.stringify({
page: window.location.href,
errors: window.errorLogs || []
});
navigator.sendBeacon('/api/logs', logs);
});
2. Fetch API
Обычный способ отправить логи:
async function sendLogsToServer(logs) {
try {
await fetch('/api/logs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(logs)
});
} catch (error) {
console.error('Failed to send logs:', error);
}
}
// Использование
window.addEventListener('error', (event) => {
sendLogsToServer([{
type: 'error',
message: event.message,
stack: event.error?.stack
}]);
});
3. Библиотеки логирования
Sentry (самая популярная):
import * as Sentry from '@sentry/react';
Sentry.init({
dsn: 'https://YOUR-KEY@sentry.io/PROJECT-ID',
environment: 'production'
});
// Все ошибки отправляются на Sentry
try {
riskyOperation();
} catch (error) {
Sentry.captureException(error);
}
Pino.js (для Node.js):
const logger = require('pino')({
transport: {
target: 'pino-http'
}
});
logger.info({ user: 'John' }, 'User logged in');
Бэкенд (сервер)
1. Файлы логов
На Linux/Mac сервере логи обычно хранятся в:
# Node.js приложения
/var/log/app.log # Обычные логи
/var/log/app-error.log # Только ошибки
/var/log/app-access.log # HTTP запросы
# Python приложения
/var/log/flask_app.log
/var/log/django.log
# Системные логи
/var/log/syslog
/var/log/messages
2. Express.js пример
const fs = require('fs');
const path = require('path');
const logDir = path.join(__dirname, 'logs');
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir);
}
function logError(error) {
const logFile = path.join(logDir, `${new Date().toISOString().split('T')[0]}.log`);
const message = `[${new Date().toISOString()}] ${error.message}\n${error.stack}\n\n`;
fs.appendFileSync(logFile, message);
}
app.use((error, req, res, next) => {
logError(error);
res.status(500).json({ error: error.message });
});
3. Docker/Контейнеры
Логи контейнера доступны через:
# Просмотр логов контейнера
docker logs my-container
# Последние 100 строк
docker logs --tail 100 my-container
# В реальном времени
docker logs -f my-container
4. Системы логирования
ELK Stack (Elasticsearch, Logstash, Kibana):
const elasticsearch = require('@elastic/elasticsearch');
const client = new elasticsearch.Client({ node: 'http://localhost:9200' });
app.use((req, res, next) => {
// Логирование HTTP запросов
client.index({
index: 'logs',
body: {
timestamp: new Date(),
method: req.method,
url: req.url,
status: res.statusCode
}
});
next();
});
Datadog/New Relic (облачные системы мониторинга):
const datadog = require('dd-trace').init();
const logger = require('pino')();
logger.info({ user: 'John' }, 'User action');
// Автоматически отправляется в Datadog
Структура логирования
Хорошее логирование:
{
"timestamp": "2024-01-15T10:30:45.123Z",
"level": "error",
"service": "auth-service",
"userId": "user_123",
"message": "Failed to authenticate user",
"error": {
"type": "AuthenticationError",
"message": "Invalid credentials",
"stack": "...."
},
"metadata": {
"ip": "192.168.1.1",
"userAgent": "Mozilla/5.0...",
"duration": 1234
}
}
Уровни логирования
console.debug('Debug info'); // 0 - самый детальный
console.info('Information'); // 1
console.warn('Warning'); // 2
console.error('Error'); // 3 - только критичные
Таблица: где хранятся логи
| Место | Постоянное? | Объём | Доступ | Примеры |
|---|---|---|---|---|
| Console | Нет | Малое | DevTools | log, warn, error |
| localStorage | Да | 5-10 MB | JS, DevTools | Пользовательские логи |
| IndexedDB | Да | 50 MB+ | JS | История действий |
| sessionStorage | Нет* | 5-10 MB | JS | Временные логи |
| Network tab | Нет* | Все запросы | DevTools | HTTP логи |
| Файлы сервера | Да | Неограниченно | SSH, Logs | /var/log/*.log |
| ELK/Datadog | Да | Неограниченно | Web UI | Облачное хранилище |
| Docker logs | Зависит | Зависит | docker logs | Логи контейнера |
*Удаляются при закрытии вкладки/браузера
Best practices
- Использование уровней логирования:
logger.error('Critical error'); // Отправляй на сервер
logger.warn('Warning'); // Отправляй на сервер
logger.info('Info'); // Сохраняй локально
logger.debug('Debug'); // Только при разработке
- Не логируй чувствительные данные:
// ПЛОХО
logger.info(`User ${user.password} logged in`);
// ХОРОШО
logger.info(`User ${user.id} logged in`, {
userId: user.id,
email: user.email // без пароля!
});
- Включай контекст:
logger.error('Request failed', {
url: request.url,
method: request.method,
status: response.status,
duration: response.time
});
- Ротация файлов логов (на сервере):
const rfs = require('rotating-file-stream');
const accessLogStream = rfs.createStream('access.log', {
interval: '1d', // Ротация каждый день
maxSize: '100M' // Или максимум 100MB
});