1 /**
2 Copyright: Copyright (c) 2016-2017, Joakim Brännström. All rights reserved.
3 License: MPL-2
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 This Source Code Form is subject to the terms of the Mozilla Public License,
7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain
8 one at http://mozilla.org/MPL/2.0/.
9 */
10 module dextool.logger_conf;
11 
12 import std.algorithm : among;
13 import std.stdio : writeln, writefln, stderr, stdout;
14 
15 import logger = std.experimental.logger;
16 
17 class SimpleLogger : logger.Logger {
18     import std.conv;
19 
20     int line = -1;
21     string file = null;
22     string func = null;
23     string prettyFunc = null;
24     string msg = null;
25     logger.LogLevel lvl;
26 
27     this(const logger.LogLevel lv = logger.LogLevel.info) {
28         super(lv);
29     }
30 
31     override void writeLogMsg(ref LogEntry payload) @trusted {
32         this.line = payload.line;
33         this.file = payload.file;
34         this.func = payload.funcName;
35         this.prettyFunc = payload.prettyFuncName;
36         this.lvl = payload.logLevel;
37         this.msg = payload.msg;
38 
39         auto out_ = stderr;
40 
41         if (payload.logLevel.among(logger.LogLevel.info, logger.LogLevel.trace)) {
42             out_ = stdout;
43         }
44 
45         out_.writefln("%s: %s", text(this.lvl), this.msg);
46     }
47 }
48 
49 class DebugLogger : logger.Logger {
50     import std.conv;
51 
52     int line = -1;
53     string file = null;
54     string func = null;
55     string prettyFunc = null;
56     string msg = null;
57     logger.LogLevel lvl;
58 
59     this(const logger.LogLevel lv = logger.LogLevel.trace) {
60         super(lv);
61     }
62 
63     override void writeLogMsg(ref LogEntry payload) @trusted {
64         this.line = payload.line;
65         this.file = payload.file;
66         this.func = payload.funcName;
67         this.prettyFunc = payload.prettyFuncName;
68         this.lvl = payload.logLevel;
69         this.msg = payload.msg;
70 
71         auto out_ = stderr;
72 
73         if (payload.logLevel.among(logger.LogLevel.info, logger.LogLevel.trace)) {
74             out_ = stdout;
75         }
76 
77         if (this.line == -1) {
78             out_.writefln("%s: %s", text(this.lvl), this.msg);
79         } else {
80             // Example of standard: 2016-05-01T22:31:54.019:type.d:retrieveType:159 c:@S@Foo:struct Foo
81             out_.writefln("%s: %s [%s:%d]", text(this.lvl), this.msg, this.func, this.line);
82         }
83     }
84 }
85 
86 enum ConfigureLog {
87     default_,
88     info,
89     debug_,
90 }
91 
92 void confLogLevel(ConfigureLog conf) {
93     import std.exception;
94     import std.experimental.logger.core : sharedLog;
95 
96     try {
97         final switch (conf) {
98         case ConfigureLog.default_:
99             goto case;
100         case ConfigureLog.info:
101             logger.globalLogLevel(logger.LogLevel.info);
102             auto simple_logger = new SimpleLogger();
103             logger.sharedLog(simple_logger);
104             break;
105         case ConfigureLog.debug_:
106             logger.globalLogLevel(logger.LogLevel.all);
107             auto logger_ = new DebugLogger();
108             logger.sharedLog(logger_);
109             break;
110         }
111     }
112     catch (Exception ex) {
113         collectException(logger.error("Failed to configure logging level"));
114         throw ex;
115     }
116 }