1 /**
2  * Модуль содержит функции для работы с логами в приложении
3  *
4  * Copyright: (c) 2015-2020, Milofon Project.
5  * License: Subject to the terms of the BSD 3-Clause License, as written in the included LICENSE.md file.
6  * Author: <m.galanin@milofon.pro> Maksim Galanin
7  * Date: 2020-04-11
8  */
9 
10 module dango.system.logging.core;
11 
12 public
13 {
14     import uniconf.core : UniConf;
15 }
16 
17 private
18 {
19     import std.uni : toUpper;
20     import std.functional : toDelegate;
21     import std.format : fmt = format;
22 
23     import vibe.core.log : Logger, LogLevel, FileLogger, setLogLevel;
24 
25     import dango.inject : DependencyContainer, ComponentFactory;
26     import dango.system.properties : getNameOrEnforce;
27 }
28 
29 
30 /**
31  * Интерфейс фабрики для создания объекта логгера
32  */
33 alias LoggerFactory = ComponentFactory!(shared(Logger), UniConf);
34 
35 
36 /**
37  * Преобразует строку в уровеь логирования
38  */
39 package LogLevel matchLogLevel(string level) @safe
40 {
41     switch (level.toUpper) with (LogLevel)
42     {
43         case "TRACE":
44             return trace;
45         case "DEBUGV":
46             return debugV;
47         case "DEBUG":
48             return debug_;
49         case "INFO":
50             return info;
51         case "WARN":
52             return warn;
53         case "ERROR":
54             return error;
55         case "FATAL":
56             return fatal;
57         default:
58             return info;
59     }
60 }
61 
62 
63 /**
64  * Преобразует строку в формат лога
65  */
66 package FileLogger.Format matchLogFormat(string logFormat)
67 {
68     switch (logFormat.toUpper) with (FileLogger.Format)
69     {
70         case "PLAIN":
71             return plain;
72         case "THREAD":
73             return thread;
74         case "THREADTIME":
75             return threadTime;
76         default:
77             return plain;
78     }
79 }
80 
81 
82 /**
83  * Инициализация логирования приложения
84  *
85  * В основе функционала логирования используется реализация из vibed.
86  * Значения по умолчанию: уровень логирования = warn, формат лога = plain
87  *
88  * Params:
89  *
90  * container = Контейнер DI
91  * config    = Объект свойств содержит настройки логгеров
92  * dg        = Функция для обработки логгера
93  */
94 void configureLogging(DependencyContainer container, UniConf config,
95         void function(shared(Logger)) nothrow dg) @trusted
96 {
97     configureLogging(container, config, toDelegate(dg));
98 }
99 
100 
101 /**
102  * Инициализация логирования приложения
103  *
104  * В основе функционала логирования используется реализация из vibed.
105  * Значения по умолчанию: уровень логирования = warn, формат лога = plain
106  *
107  * Params:
108  *
109  * container = Контейнер DI
110  * config    = Объект свойств содержит настройки логгеров
111  * dg        = Функция-делегат для обработки логгера
112  */
113 void configureLogging(DependencyContainer container, UniConf config,
114         void delegate(shared(Logger)) nothrow dg) @safe
115 {
116     if ("logger" !in config)
117         return;
118 
119     // отключаем логгер консоли по умолчанию
120     setLogLevel(LogLevel.none);
121 
122     UniConf logConfig = config.get!UniConf("logger");
123     if (logConfig.canMapping)
124         logConfig = UniConf([logConfig]);
125 
126     foreach (UniConf loggerConf; logConfig.getSequence())
127     {
128         auto appender = loggerConf.opt!UniConf("appender");
129         if (appender.empty)
130             throw new Exception(fmt!"В конфигурации логера не указан тип ('%s')"(loggerConf));
131 
132         string appenderName = appender.front.getNameOrEnforce(
133                 "Не указано наименование логгера").toUpper;
134 
135         auto factory = container.resolve!LoggerFactory(appenderName);
136         if (factory is null)
137             throw new Exception("Не зарегистрирован логгер с именем " ~ appenderName);
138 
139         shared(Logger) logger = factory.createComponent(loggerConf);
140         if (logger && dg)
141             () @trusted { dg(logger); }();
142     }
143 }
144