1 module des.log.base;
2 
3 import std.conv : to;
4 import std.datetime : Clock;
5 import std.string : toUpper, format;
6 
7 import des.log.output;
8 import des.log.rule;
9 
10 ///
11 class LogException : Exception
12 { this( string msg ) pure @safe nothrow { super(msg); } }
13 
14 ///
15 enum LogLevel
16 {
17     OFF,   /// no output
18     FATAL, /// not recoverible error
19     ERROR, /// recoverible error (exceptions)
20     WARN,  /// warning (only if something wrong but not critical)
21     INFO,  /// info message (one-call functions messages)
22     DEBUG, /// debug message (detalied one-call functions messages)
23     TRACE  /// trace message (idle, foreach, etc)
24 };
25 
26 ///
27 struct LogMessage
28 {
29     string emitter; /// name of log message emmiter
30     ulong ts; /// timestamp
31 
32     /// log message level (without LogLevel.OFF)
33     enum Level : LogLevel 
34     {
35         FATAL = LogLevel.FATAL, ///
36         ERROR, ///
37         WARN, ///
38         INFO, ///
39         DEBUG, ///
40         TRACE ///
41     };
42 
43     Level level; /// log level
44     string message; ///
45 
46     ///
47     @disable this();
48 
49     ///
50     this( string emitter, ulong ts, Level level, string message ) pure nothrow @safe
51     {
52         this.emitter = emitter;
53         this.ts = ts;
54         this.level = level;
55         this.message = message;
56     }
57 }
58 
59 /++
60  nothrow format function, if first is string it try call string.format,
61  if it's failed return all args converted to string
62  +/
63 string ntFormat(Args...)( Args args ) nothrow
64 {
65     try
66     {
67         static if( is( Args[0] == string ) )
68         { try return format(args); catch{} }
69 
70         string res;
71         foreach( arg; args )
72             res ~= to!string(arg);
73         return res;
74     }
75     catch( Exception e )
76         return "[MESSAGE CTOR EXCEPTION]: " ~ e.msg;
77 }
78 
79 ///
80 LogLevel toLogLevel( string s ) { return to!LogLevel( s.toUpper ); }
81 
82 /++
83     Returns:
84     format( "[%016.9f][%5s][%s]: %s", lm.ts / 1e9f, lm.level, lm.emitter, lm.message );
85  +/
86 string defaultFormatLogMessage( in LogMessage lm )
87 {
88     return format( "[%016.9f][%5s][%s]: %s",
89                     lm.ts / 1e9f, lm.level, lm.emitter, lm.message );
90 }
91 
92 package:
93 
94 static shared OutputHandler g_output;
95 static shared Rule g_rule;
96 
97 ulong __ts() nothrow @property
98 {
99     try return Clock.currAppTick().length;
100     catch(Exception e) return 0;
101 }
102 
103 string fixReservedName( string name ) nothrow
104 {
105     if( name == "debug" ) return "Debug";
106     return name;
107 }