Difference between revisions of "Using string mixins for logging"
m (edit functions for readability) |
(updated version) |
||
Line 36: | Line 36: | ||
} | } | ||
− | template | + | template log(string level, PS...) |
{ | { | ||
//pragma(msg, info); | //pragma(msg, info); | ||
− | const char[] | + | const char[] log = `static if(!__traits(compiles, __FUNCTION__ == ""))` ~ |
`{ immutable string __FUNCTION__ = __traits(identifier, __traits(parent, {})) ~` ~ | `{ immutable string __FUNCTION__ = __traits(identifier, __traits(parent, {})) ~` ~ | ||
`"(" ~ StringOf!(PTT!(__traits(parent, {}))) ~ ")";` ~ | `"(" ~ StringOf!(PTT!(__traits(parent, {}))) ~ ")";` ~ | ||
− | `} stderr.writeln(Clock.currTime(), " [ | + | `} stderr.writeln(Clock.currTime(), " [` ~ level ~ `] ", __FILE__, '(', __LINE__, "): ",` ~ |
`__FUNCTION__, ": ",` ~ ArgStringOf!(PS) ~ `);` ; | `__FUNCTION__, ": ",` ~ ArgStringOf!(PS) ~ `);` ; | ||
} | } | ||
− | + | ||
+ | template info(PS...) | ||
+ | { | ||
+ | const char[] info = log!("INFO", PS); | ||
+ | } | ||
+ | |||
+ | template warn(PS...) | ||
+ | { | ||
+ | const char[] warn = log!("WARN", PS); | ||
+ | } | ||
+ | |||
+ | template error(PS...) | ||
+ | { | ||
+ | const char[] error = log!("ERROR", PS); | ||
+ | } | ||
+ | |||
mixin template set_func_name(string fn) | mixin template set_func_name(string fn) | ||
{ | { | ||
immutable string __FUNCTION__ = fn; | immutable string __FUNCTION__ = fn; | ||
} | } | ||
− | + | ||
+ | ///////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | import std.exception; | ||
+ | |||
auto foo(T)(in T val) | auto foo(T)(in T val) | ||
if(is(T==int) || is(T==string)) | if(is(T==int) || is(T==string)) | ||
{ | { | ||
mixin set_func_name!("foo(" ~ T.stringof ~ ")"); //workaround for fwd ref issue | mixin set_func_name!("foo(" ~ T.stringof ~ ")"); //workaround for fwd ref issue | ||
− | mixin (info!(`" | + | mixin (info!(`"starting"`)); |
− | mixin (info!(`" | + | mixin (info!(`"stopping"`)); |
static if (is(T==int)) | static if (is(T==int)) | ||
Line 69: | Line 88: | ||
{ | { | ||
mixin (info!(`"called"`)); | mixin (info!(`"called"`)); | ||
+ | |||
+ | throw new Exception("baz"); | ||
} | } | ||
void main(string[] args) | void main(string[] args) | ||
{ | { | ||
− | mixin (info!(`" | + | mixin (info!(`"starting"`)); |
mixin (info!(`"foo(1) returned: "`, `foo(1)`)); | mixin (info!(`"foo(1) returned: "`, `foo(1)`)); | ||
mixin (info!(`"foo(\"bar\") returned: "`, `foo("bar")`)); | mixin (info!(`"foo(\"bar\") returned: "`, `foo("bar")`)); | ||
− | mixin ( | + | mixin (warn!(`"calling baz()"`)); |
− | baz(); | + | try |
− | mixin (info!(`" | + | { |
+ | baz(); | ||
+ | } | ||
+ | catch(Exception e) | ||
+ | { | ||
+ | mixin (error!(`"Caught exception: "`, `e.toString()`)); | ||
+ | } | ||
+ | mixin (info!(`"stopping"`)); | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | [http://dpaste.dzfl.pl/ | + | [http://dpaste.dzfl.pl/857a5f06 ▶ Run code] |
==Sample Output== | ==Sample Output== | ||
<pre> | <pre> | ||
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4739137 [INFO] /home/c222/c817.d(95): main(string[]): starting |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4741135 [INFO] /home/c222/c817.d(75): foo(int): starting |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4741472 [INFO] /home/c222/c817.d(76): foo(int): stopping |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4741115 [INFO] /home/c222/c817.d(97): main(string[]): foo(1) returned: 1.0123 |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4742436 [INFO] /home/c222/c817.d(75): foo(string): starting |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4742707 [INFO] /home/c222/c817.d(76): foo(string): stopping |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4742431 [INFO] /home/c222/c817.d(98): main(string[]): foo("bar") returned: true |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4743165 [WARN] /home/c222/c817.d(99): main(string[]): calling baz() |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4743386 [INFO] /home/c222/c817.d(88): baz(): called |
− | 2012-Dec-13 | + | 2012-Dec-13 21:09:13.4743744 [ERROR] /home/c222/c817.d(106): main(string[]): Caught exception: object.Exception@/home/c222/c817.d(90): baz |
+ | ---------------- | ||
+ | 2012-Dec-13 21:09:13.4744075 [INFO] /home/c222/c817.d(108): main(string[]): stopping | ||
</pre> | </pre> |
Revision as of 21:25, 13 December 2012
import std.traits : PTT=ParameterTypeTuple;
import std.stdio : stderr;
import std.datetime : Clock;
template StringOf(TS...)
{
static if(TS.length == 0)
{
enum StringOf = "";
}
else static if(TS.length == 1)
{
enum StringOf = (TS[0]).stringof;
}
else
{
enum StringOf = (TS[0]).stringof ~ "," ~ StringOf!(TS[1..$]) ;
}
}
template ArgStringOf(TS...)
{
static if(TS.length == 0)
{
enum ArgStringOf = "";
}
else static if(TS.length == 1)
{
enum ArgStringOf = TS[0];
}
else
{
enum ArgStringOf = TS[0] ~ "," ~ ArgStringOf!(TS[1..$]);
}
}
template log(string level, PS...)
{
//pragma(msg, info);
const char[] log = `static if(!__traits(compiles, __FUNCTION__ == ""))` ~
`{ immutable string __FUNCTION__ = __traits(identifier, __traits(parent, {})) ~` ~
`"(" ~ StringOf!(PTT!(__traits(parent, {}))) ~ ")";` ~
`} stderr.writeln(Clock.currTime(), " [` ~ level ~ `] ", __FILE__, '(', __LINE__, "): ",` ~
`__FUNCTION__, ": ",` ~ ArgStringOf!(PS) ~ `);` ;
}
template info(PS...)
{
const char[] info = log!("INFO", PS);
}
template warn(PS...)
{
const char[] warn = log!("WARN", PS);
}
template error(PS...)
{
const char[] error = log!("ERROR", PS);
}
mixin template set_func_name(string fn)
{
immutable string __FUNCTION__ = fn;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
import std.exception;
auto foo(T)(in T val)
if(is(T==int) || is(T==string))
{
mixin set_func_name!("foo(" ~ T.stringof ~ ")"); //workaround for fwd ref issue
mixin (info!(`"starting"`));
mixin (info!(`"stopping"`));
static if (is(T==int))
return 1.0123;
else static if(is(T==string))
return true;
else
static assert(false, "need int or string");
}
void baz()
{
mixin (info!(`"called"`));
throw new Exception("baz");
}
void main(string[] args)
{
mixin (info!(`"starting"`));
mixin (info!(`"foo(1) returned: "`, `foo(1)`));
mixin (info!(`"foo(\"bar\") returned: "`, `foo("bar")`));
mixin (warn!(`"calling baz()"`));
try
{
baz();
}
catch(Exception e)
{
mixin (error!(`"Caught exception: "`, `e.toString()`));
}
mixin (info!(`"stopping"`));
}
Sample Output
2012-Dec-13 21:09:13.4739137 [INFO] /home/c222/c817.d(95): main(string[]): starting 2012-Dec-13 21:09:13.4741135 [INFO] /home/c222/c817.d(75): foo(int): starting 2012-Dec-13 21:09:13.4741472 [INFO] /home/c222/c817.d(76): foo(int): stopping 2012-Dec-13 21:09:13.4741115 [INFO] /home/c222/c817.d(97): main(string[]): foo(1) returned: 1.0123 2012-Dec-13 21:09:13.4742436 [INFO] /home/c222/c817.d(75): foo(string): starting 2012-Dec-13 21:09:13.4742707 [INFO] /home/c222/c817.d(76): foo(string): stopping 2012-Dec-13 21:09:13.4742431 [INFO] /home/c222/c817.d(98): main(string[]): foo("bar") returned: true 2012-Dec-13 21:09:13.4743165 [WARN] /home/c222/c817.d(99): main(string[]): calling baz() 2012-Dec-13 21:09:13.4743386 [INFO] /home/c222/c817.d(88): baz(): called 2012-Dec-13 21:09:13.4743744 [ERROR] /home/c222/c817.d(106): main(string[]): Caught exception: object.Exception@/home/c222/c817.d(90): baz ---------------- 2012-Dec-13 21:09:13.4744075 [INFO] /home/c222/c817.d(108): main(string[]): stopping