# logosFor1c

> Подсистема сквозного логирования для 1С: клиент и сервер, различные приемники, настройки без хранения в переменной.

- GitHub: https://github.com/cpr1c/logosFor1c
- Gitsell page: https://gitsell.ru/cpr1c/logosFor1c
- Visibility: public/free
- GitHub stars: 29
- Gitsell views: 47
- Gitsell downloads: 0

## 1C Configurations

Not specified.

## Pricing

Free or price is not specified.

## README

# logosFor1c

Подсистема сквозного логирования на клиенте и сервере в разные приемники.
За основу взята обработка https://github.com/codenull/log1c.

Позволяет задать несколько настроек логирования и использовать изолированно друг от друга. Притом настройки не нужно хранить в переменной

В перспективе есть мысли сделать переопределяемый программный интерфейс для добавления своих способов логирования

Распространяется в виде расширения. Ограничений по видам приложений и операционным системам нет

# Использование

# Пример использования

```bsl
//Контекст - Клиент

лЛог.НовыйЛог();
лЛог.ДобавитьСпособЛогированияБаза();

лЛог.Инф_("Мой первый лог"); //Логируется только в базу

лЛог.ДобавитьСпособЛогированияФайл("D:\МойЛог.txt");

лЛог.Инф_("Мой второй лог"); //Логируется в базу и в файл

лЛог.ДобавитьСпособЛогированияФайл("D:\ЛогТолькоНаКлиенте.txt",,"Сервер");

лЛог.Инф_("Мой третий лог лог"); //Логируется в базу и в первый файл

//Контекст - Сервер
лЛог.Инф_("Мой четвертый лог лог"); //Логируется в базу и в оба файла


//Контекст - Клиент
лЛог.Отключить(); //Логирование прекращается

лЛог.Инф_("Мой пятый лог"); //ничего не залогируется

лЛог.Включить(); //Заново включаем

лЛог.Инф_("Мой шестой лог"); //Логируется в базу и в первый файл

лЛог.ЗавершитьЛогирование(); //Прекращаем логировать в лог по умолчанию.
```

## Инициализация

1. Инициализация с настройками по умолчанию

```bsl
лЛог.НовыйЛог();
```

2. Инициализация по наименованию настройки

```bsl
лЛог.НовыйЛог(Наименование);
```

Далее все логирование должно идти с указанием имени лога

## Особенности изменения настроек лога на сервере
Ввиду технологических ограничений (невозможности использовать параметров сеанса в расширении), пришлось реализовать отдельные хранилища для клиента и сервера.
При создании/настройке лога на клиенте, настройки автоматически обновляются на сервере.

При инициализации лога или изменении его настроек на сервере, после заверешение серверного вызова нужно на клиенте вызвать метод

```bsl
лЛог.ОбновитьЛогиНаКлиентеПоДаннымСервера();
```



## Уровни логирования и основные методы
В подсистеме используется следующие (по возрастанию приоритета):
1. НЕТ - Логирование не происходит
1. ОТЛАДКА
1. ИНФОРМАЦИЯ
2. ПРЕДУПРЕЖДЕНИЕ
3. ОШИБКА
4. КРИТИЧЕСКАЯОШИБКА

По умолчанию используется уровень логирования ИНФОРМАЦИЯ. При установке какого-либо уровня, в лог будут выводиться только сообщения этого уровня и уровней с большим приоритетом. Например, если установлен уровень ПРЕДУПРЕЖДЕНИЕ то будут выводиться сообщения следующих уровней: ПРЕДУПРЕЖДЕНИЕ, ОШИБКА, КРИТИЧЕСКАЯОШИБКА.

Уровень логирования можно изменить с помощью метода *УстановитьУровеньЛогирования()*:

```bsl
лЛог. УстановитьУровеньЛогирования("Ошибка");
лЛог. УстановитьУровеньЛогирования("Ошибка", "НеОсновнойЛог");
```
# Шаблон сообщения
Для лога можно задать свой шаблон сообщения. В шаблонах поддерживаются следующие псевдонимы:
* **%УРОВЕНЬ%** - уровень лога которым было сформировано сообщение (например: ИНФОРМАЦИЯ).
* **%СОБЫТИЕ%**   - указанное событие логирования (имя лога).
* **%СООБЩЕНИЕ%** - текст выводимого сообщения.
* **%ДАТА%** - дата и время в формате yyyy.MM.dd HH:mm:ss (например: 2020.09.16 23:52:49).
* **%ДАТАМС%** - количество миллисекунд текущей даты.
* **%УНИВЕРСАЛЬНАЯДАТАМС%** - универсальная дата полученная с помощью функции ТекущаяУниверсальнаяДатаВМиллисекундах().

По-умолчанию используется шаблон **%ДАТА% - %УРОВЕНЬ% - %СООБЩЕНИЕ%**

**ВАЖНО:** псевдонимы регистрозависмые и допускается их указание только в верхнем регистре.

Пример шаблона:
```bsl
лЛог.УстановитьШаблонСообщения("%ДАТА%.%ДАТАМС%/ %УНИВЕРСАЛЬНАЯДАТАМС% /%СООБЩЕНИЕ% | %СОБЫТИЕ% | %УРОВЕНЬ% |");
лЛог.Пред_("Привет. Это первый лог в базе");
```
```
2021.11.01 18:35:32.830/ 63771377732830 /Привет. Это первый лог в базе | Логирование | ПРЕДУПРЕЖДЕНИЕ |
```

## Вывод сообщений в лог

Каждому уровню логирования соответствует свой метод вывода информации:

```bsl
лЛог.Отл_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Пред_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Инф_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Ош_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Крит_("Отладочное сообщение", ИмяЛога = Неопределено);
```

Так же есть длинные варианты тех же методов

```bsl
лЛог.Отладка_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Информация_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Предупреждение_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.Ошибка_("Отладочное сообщение", ИмяЛога = Неопределено);
лЛог.КритическаяОшибка_("Отладочное сообщение", ИмяЛога = Неопределено);
```

Имя события логирования записывается как "Логирование.<ИмяЛога>"

## Способы логирования
Поддерживаются следующие способы:
* Консоль -  вывод в стандартные сообщения
* ЖурналРегистрации
* Память - работает только в конексте клиента
* База - запись в специальный регистр сведений
* Файл - Логирование производится в указанный файл
* КаталогФайлов - для логирования указывается каталог и шаблон имени файла. Файлы в данном случае генерятся автоматически


```bsl
лЛог.ДобавитьСпособЛогирования(Способ, Параметры, ЛогИлиИмяЛога = Неопределено, Контекст = "");
```

Параметры способа логирования можно получить методом:
```bsl
лЛог.ПараметрыСпособаЛогирования(Способ);
```

Для типовых способов логирования предусмотрены специфичные методы добавления в лог


```bsl
лЛог.ДобавитьСпособЛогированияКонсоль(ЛогИлиИмяЛога = Неопределено, Контекст = "");
лЛог.ДобавитьСпособЛогированияБаза(ЛогИлиИмяЛога = Неопределено, Контекст = "");
лЛог.ДобавитьСпособЛогированияЖурналРегистрации(ЛогИлиИмяЛога = Неопределено, Контекст = "");
лЛог.ДобавитьСпособЛогированияПамять(ЛогИлиИмяЛога = Неопределено, Контекст = "");
лЛог.ДобавитьСпособЛогированияФайл(ИмяФайла, ЛогИлиИмяЛога = Неопределено, Контекст = "");
лЛог.ДобавитьСпособЛогированияКаталогФайлов(Каталог, ШаблонИмениФайла = "", ЛогИлиИмяЛога = Неопределено, Контекст = "");
```

## Добавление своих способов логирования

Есть возможность определять свои способы логирования. Для этого предоставляются два варианта. Использование добавленных способов идет по общей схеме.

```bsl
	ПараметрыСпособа = лЛог.ПараметрыСпособаЛогирования("Мой");
	ПараметрыСпособа.Суффикс = "Привет";
	
	лЛог.ДобавитьСпособЛогирования("Мой", ПараметрыСпособа);
```

### Добавление способа логирования через переопределяемый модуль

Нужно в общем модуле **лЛогПереопределяемый** доработать методы 

* *ПриОпределенииСпособовЛогирования* - для добавления вашего способа в список
Например, 
```bsl
	МойСпособ = лЛогСлужебный.НовыйСпособЛогирования("Мой");
	
	Способы.Вставить(МойСпособ.Имя, МойСпособ);
```

* *ПриОпределенииПараметровСпособаЛогирования* - для определения параметров, необходимых вашему способу(Необязательно)
Например,
```bsl
	Если ИмяСпособа = "Мой" Тогда
		ПараметрыСпособа = Новый Структура;
		ПараметрыСпособа.Вставить("Суффикс", "");
	КонецЕсли;
```

*  *ПриВыводеСообщенияВЛогПоСпособу* - здесь нужно добавить алгоритм записи лога по вашему способу

Например, 
```bsl
	Если ИмяСпособа = "Мой" Тогда
		Сообщить(Сообщение+Параметры.Суффикс);
	КонецЕсли;
```

### Добавление способа логирования через новый общий модуль

Нужно добавить новый общий модуль в конфигурацию/расширение/новое расширение с префиксом **лЛогСпособЛогирования**. Пример добавления способа логирования через общий модуль приведен [тут](./src/лЛогСпособЛогирониваяОбщийМодуль)

Префикс можно переопределить в процедуре **ПриОпределенииПрефиксаОбщихМодулейОпределяющихСпособыЛогирования** общего модуля *лЛогПереопределяемый* 

Имя нового способа логирования получается из имени модуля путем отсечения префикса. Например, модуль с именем *лЛогСпособЛогированияОповещениеПользователя* добавляет способ логирования с именем *"ОповещениеПользователя"*. 
Также имя можно задать непосредственно в модуле определив функцию **Имя()**

В модуле должны быть определены следующие методы

```bsl

//необязательна. Показывает необхоодимость серверного контекста для выполнения записи. По умолчанию Ложь
Функция ЗаписьТолькоНаСервере() Экспорт
	Возврат Ложь;	
КонецФункции

//Необязательна. Указывает на невозможность добавления способа два раза в один лог. По умолчанию Истина
Функция ЗапретДублейУЛога() Экспорт
	Возврат Истина;
КонецФункции

//Необязательна. Позволяет переопределить имя, получаемое из имени модуля
Функция Имя() Экспорт
	Возврат "МоеИмя";
КонецФункции

//Необязательна. Определяет параметры, необходимые для способа логировнаия. По умолчанию Неопределено
Функция НовыйПараметрыСпособаЛогирования() Экспорт
	ПараметрыСпособа = Новый Структура;
	ПараметрыСпособа.Вставить("Префикс","");
	Возврат ПараметрыСпособа;	
КонецФункции

//Обязательна. Выполняет запись лога по вашему алгоритму
Процедура ЗаписатьСообщениеВЛог(Сообщение, Лог, УровеньЛогирования, Параметры) Экспорт
	СообщениеДляЗаписи = Параметры.Префикс  + Сообщение;
	лЛогСлужебныйСервер.ЗаписатьСообщениеЛогаВБазу(Лог, СообщениеДляЗаписи, УровеньЛогирования);
КонецПроцедуры
```

## Шаблон наименования файла для логирования в каталог

По умолчанию равен **[ИМЯЛОГА].txt**.

Поддерживаются следующие параметры:
* **[ИМЯЛОГА]** - Имя текущего лога
* **[ДАТА]** - Текущая дата в формате dd.MM.yyyy
* **[ДЕНЬ]** - номер текущего дня месяца
* **[ДЕНЬНЕДЕЛИ]** - Номер текущего дня недели
* **[МЕСЯЦ]** - Номер текущего месяца
* **[ГОД]** - Текущий год
* **[НОМЕРСЕАНСА]** - Номер текущего сеанса пользователя
* **[ПОЛЬЗОВАТЕЛЬ]** - Имя текущего пользователя системы

## Контекст для способа логирования
Для каждого способа логирования можно указать контекст в котором данный способ срабатывать.
Сейчас доступно:
* Клиент - Логирование для способа происходит только на клиенте
* Сервер - Логирование для способа происходит только на сервере
* КлиентСервер или пустой контекст - фильтр по контексту не применяется

Например,
```bsl
лЛог.ДобавитьСпособЛогированияКонсоль(, "Клиент"); //ЛОгирование для лога по умолчанию в консоль будет выполняться только на клиенте
лЛог.ДобавитьСпособЛогированияБаза(, "Сервер"); //Логирование для лога по умолчанию в базу будет только на сервере
```
## Управление логированием

* Отключение логирования для лога. В этом логирование по данному логу прекращается, но все настройки сохраняются
```bsl
лЛог.Отключить(ЛогИлиИмяЛога = Неопределено);
```

* Включение логирования для лога после отключения.
```bsl
лЛог.Включить(ЛогИлиИмяЛога = Неопределено);
```

Это может быть удобным, если требуется отключить логи на определенном участке кода.

* Завершение логирования для лога. Удаление настройки лога из актуальных

```bsl
лЛог.ЗавершитьЛогирование(ЛогИлиИмяЛога = Неопределено);
```

* Получения текущих настроек логов
  
```bsl
лЛог.АктивныеЛоги();
```

* Удаление всех настроек логов. Остановка всего логирования 

```bsl
лЛог.ОчиститьСписокЛогов();
```

* Получение данных лога для способа логирования Память

```bsl
лЛог.ДанныеЛога(ЛогИлиИмяЛога = Неопределено);
```

# Особенности

1. Что будет если лог не проинициализирован и по нему происходит настройка и дальнейшее логирование?

    **Логирование не будет произведено. Ошибок не выдасться**

2. Что будет если два раза добавить способ логирования База с разными контекстами?

   **Логирование будет просходить по самому первому заданному контексту**

# Интеграция в ваше решение

Есть возможность простой интеграции в ваше решение с переименованием модулей и объектов подсистемы. 
Для этого нужно:
1. Перенести объекты подсистемы в ваше решение
2. Переименовать объекты подсистемы на ваши имена
3. В модулях найти область с именем **ПереопределениеМодулейПодсистемы** и во вложенных процедурах указать новые имена модулей и объектов
4. В модулях приложения, внешнего соединения и сеанса изменить вызов общих модулей на ваши.
5. Можно пользоваться

# Сборка в бинарные файлы

Зависимости сборки теперь находятся в файле **packagedef**, для установки зависимостей необходимо выполнить команду
`opm install`  находясь в корне проекта

В корне репозитория вызвать файл сценария 

* **build.sh** - для Linux
* **build.bat** - для Windows

Доступные параметры сборки:
  * **--platformSource**  - Каталог установки платформы для выполнения сборки
  * **--versionEDT** - Версия EDT для выполнения конвертации. Для запуска через утилиту ring. Необходимо указывать, если в системе установлено более одной версии 1C:EDT
  * **--cfe** - Формировать сборку в формате Расширения
  * **--cf** - Формировать сборку в виде конфигурации
   
Пример 
`./build.sh ----platformSource=/opt/1cv8/x86_64/8.3.12.1924 --versionEDT=edt@2020.6.0`

# Другие решения

* Обработка для логирования из одного объекта (обработки): https://github.com/codenull/log1c
* Модуль logos из OneScript: https://github.com/oscript-library/logos
* Подсистема логирования на базе модуля logos: https://github.com/1823244/logos-1c
* 1C_logger. Подсистема логирования - https://infostart.ru/public/671835/  https://gitlab.com/shmalevoz/1C_logger https://gitlab.com/shmalevoz/logger_ext