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