Danro/Assets/Scripts/Utilities/README_LOGGING.md
Danil Iarosh 98d5285b46 feat(logging): add advanced logging example with file output
- Created AdvancedLoggingExample class demonstrating composite and file loggers
- Implemented multi-file logging setup with separate error and full logs
- Added game event and performance logging methods
- Included key input handling for log operations (flush, clear)
- Setup proper resource disposal on application quit
2025-11-07 14:12:50 +03:00

285 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Система логирования для Unity
## Обзор
Система состоит из трёх компонентов:
1. **CompositeLogger** - композитный логгер, пересылающий сообщения на несколько логгеров
2. **FileLogger** - логгер для записи в файл
3. **LoggerInitializer** - компонент для автоматической инициализации
## Быстрый старт
### Вариант 1: Использование через LoggerInitializer (рекомендуется)
1. Создайте пустой GameObject на сцене
2. Прикрепите компонент `LoggerInitializer`
3. Настройте параметры в инспекторе:
- **Enable File Logging** - включить запись в файл
- **Custom Log Path** - путь к файлу (оставьте пустым для автоматического)
- **Append To Existing Log** - добавлять к существующему файлу
- **Clear Log On Start** - очищать файл при запуске
4. Запустите игру - все логи будут автоматически писаться в файл!
### Вариант 2: Ручная настройка в коде
```csharp
using UnityEngine;
public class MyGameManager : MonoBehaviour
{
private CompositeLogger compositeLogger;
private FileLogger fileLogger;
void Awake()
{
// Инициализация композитного логгера
compositeLogger = new CompositeLogger();
compositeLogger.Initialize();
// Создание файлового логгера
fileLogger = new FileLogger(); // Использует путь по умолчанию
// или
// fileLogger = new FileLogger("D:/MyGame/logs/game.log", append: true);
// Добавление файлового логгера в композитный
compositeLogger.AddLogger(fileLogger);
// Теперь все логи через compositeLogger будут идти и в консоль, и в файл
compositeLogger.Log("Игра запущена!");
compositeLogger.LogWarning("Test", "Тестовое предупреждение");
}
void OnApplicationQuit()
{
fileLogger?.Dispose();
}
}
```
## Где находится файл лога?
По умолчанию файл сохраняется в `Application.persistentDataPath/game.log`:
- **Windows**: `C:/Users/<Username>/AppData/LocalLow/<CompanyName>/<ProductName>/game.log`
- **macOS**: `~/Library/Application Support/<CompanyName>/<ProductName>/game.log`
- **Linux**: `~/.config/unity3d/<CompanyName>/<ProductName>/game.log`
- **Android**: `/storage/emulated/0/Android/data/<PackageName>/files/game.log`
Узнать точный путь можно через:
```csharp
Debug.Log(Application.persistentDataPath);
```
## Примеры использования
### Базовое логирование
```csharp
// Через композитный логгер
compositeLogger.Log("Простое сообщение");
compositeLogger.LogWarning("Tag", "Предупреждение");
compositeLogger.LogError("Tag", "Ошибка");
// Через стандартный Debug (если вы заменили Debug.unityLogger)
Debug.Log("Это тоже пойдёт в файл");
```
### Логирование с контекстом
```csharp
compositeLogger.Log(LogType.Log, "Игрок спавнится", playerGameObject);
compositeLogger.LogWarning("AI", "Путь не найден", enemyGameObject);
```
### Логирование исключений
```csharp
try
{
// Опасный код
}
catch (Exception ex)
{
compositeLogger.LogException(ex);
}
```
### Форматированное логирование
```csharp
compositeLogger.LogFormat(LogType.Log, "Игрок {0} имеет {1} очков здоровья", playerName, health);
```
### Добавление нескольких логгеров
```csharp
var fileLogger1 = new FileLogger("logs/debug.log");
var fileLogger2 = new FileLogger("logs/errors.log");
fileLogger2.filterLogType = LogType.Error; // Только ошибки
compositeLogger.AddLoggers(fileLogger1, fileLogger2);
```
## Настройка фильтрации
### На уровне FileLogger
```csharp
fileLogger.filterLogType = LogType.Warning; // Логировать только Warning, Error, Exception
fileLogger.logEnabled = false; // Временно отключить
```
### Очистка файла лога
```csharp
fileLogger.Clear(); // Очистить файл и записать новый заголовок
```
### Принудительная запись на диск
```csharp
fileLogger.Flush(); // Сбросить буфер на диск
```
## Формат записи в файле
```
================================================================================
Новая сессия логирования начата: 2025-11-07 14:30:15
Unity версия: 2022.3.5f1
Платформа: WindowsEditor
Путь к логу: C:/Users/User/AppData/LocalLow/DefaultCompany/MyGame/game.log
================================================================================
[14:30:15.123] [INFO] Игра запущена!
[14:30:16.456] [WARNING] [AI] Путь не найден
[14:30:17.789] [ERROR] [Network] Соединение потеряно
[14:30:18.012] [EXCEPTION] NullReferenceException: Object reference not set to an instance of an object
StackTrace:
at MyScript.MyMethod () [0x00000] in <filename>:0
```
## Важные замечания
### Потокобезопасность
FileLogger потокобезопасен - использует `lock` для синхронизации записи.
### Производительность
- `AutoFlush = true` гарантирует сохранность данных при крашах, но снижает производительность
- Если нужна максимальная производительность, установите `AutoFlush = false` и вызывайте `Flush()` вручную
### Освобождение ресурсов
**ВАЖНО:** Всегда вызывайте `Dispose()` при завершении работы:
```csharp
void OnApplicationQuit()
{
fileLogger?.Dispose();
}
```
### Ротация логов
Для больших проектов можно реализовать ротацию:
```csharp
string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
string logPath = $"logs/game_{timestamp}.log";
var fileLogger = new FileLogger(logPath, append: false);
```
## Расширенные сценарии
### Отдельные логи для разных систем
```csharp
// Общий лог
var mainLogger = new FileLogger("logs/game.log");
// Лог только для сетевой подсистемы
var networkLogger = new FileLogger("logs/network.log");
networkLogger.filterLogType = LogType.Log;
// Лог только для ошибок
var errorLogger = new FileLogger("logs/errors.log");
errorLogger.filterLogType = LogType.Error;
compositeLogger.AddLoggers(mainLogger, networkLogger, errorLogger);
```
### Условное логирование
```csharp
#if UNITY_EDITOR
// В редакторе не пишем в файл, только в консоль
#else
compositeLogger.AddLogger(new FileLogger());
#endif
```
### Логирование с метками времени
```csharp
public class TimestampLogger
{
private CompositeLogger logger;
public void LogWithTimestamp(string message)
{
logger.Log($"[{Time.time:F2}s] {message}");
}
}
```
## Troubleshooting
### Файл не создаётся
- Проверьте права доступа к папке
- Проверьте путь через `Debug.Log(Application.persistentDataPath)`
- Убедитесь, что вызвали `Initialize()` на CompositeLogger
### Логи не пишутся в файл
- Убедитесь, что `logEnabled = true`
- Проверьте `filterLogType` - возможно фильтр слишком строгий
- Проверьте, что логгер добавлен через `AddLogger()`
### Файл заблокирован
- Убедитесь, что вызвали `Dispose()` перед закрытием приложения
- Закройте все программы, которые могут держать файл открытым
### Производительность низкая
- Установите `AutoFlush = false` в конструкторе FileLogger
- Вызывайте `Flush()` периодически (например, раз в секунду)
- Используйте более строгий `filterLogType`
## API Reference
### FileLogger
#### Конструктор
```csharp
FileLogger(string filePath = null, bool append = true)
```
#### Свойства
- `bool logEnabled` - включено ли логирование
- `LogType filterLogType` - минимальный уровень логирования
- `ILogHandler logHandler` - обработчик логов (для совместимости)
#### Методы
- `void Flush()` - принудительно сбросить буфер на диск
- `void Clear()` - очистить файл лога
- `void Dispose()` - закрыть файл и освободить ресурсы
- `bool IsLogTypeAllowed(LogType)` - проверка фильтра
### CompositeLogger
#### Методы управления
- `void Initialize(ILogger additiveLogger = null)` - инициализация
- `void AddLogger(ILogger)` - добавить логгер
- `void AddLoggers(params ILogger[])` - добавить несколько логгеров
- `void RemoveLogger(ILogger)` - удалить логгер
- `void RemoveLoggers(params ILogger[])` - удалить несколько логгеров
## Лицензия
Свободное использование в ваших проектах.