Difference between revisions of "Using string mixins for logging"

From D Wiki
Jump to: navigation, search
(updated version)
m (small edit)
Line 40: Line 40:
 
     //pragma(msg, info);
 
     //pragma(msg, info);
 
     const char[] log = `static if(!__traits(compiles, __FUNCTION__ == ""))` ~  
 
     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(), " [` ~ level ~ `] ", __FILE__, '(', __LINE__, "): ",` ~
+
                      `} stderr.writeln(Clock.currTime(), " [` ~ level ~ `] ", __FILE__, '(', __LINE__, "): ",` ~
                                          `__FUNCTION__, ": ",` ~ ArgStringOf!(PS) ~ `);` ;
+
                                        `__FUNCTION__, ": ",` ~ ArgStringOf!(PS) ~ `);` ;
 
}
 
}
  

Revision as of 21:58, 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"`));	
}

▶ Run code

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