Find the answer to your Linux question:
Results 1 to 5 of 5
Hi, I have a function for logging purposes in c used by my applications. Now I want to incorporate logging levels to log messages of the category configured. So I ...
  1. #1
    Just Joined!
    Join Date
    Apr 2010
    Posts
    18

    logging levels in C

    Hi,

    I have a function for logging purposes in c used by my applications. Now I want to incorporate logging levels to log messages of the category configured.
    So I am thinking 3 levels of logging 0 for basic msgs and any errors, 1 for some more and 2 for low level debugging. I have 2 methodologies in mind for this and would like some input on which is better and more efficient or if you can suggest a better new method, please do.
    1. have 3 #defines for the 3 levels say DEBUG_ONE, DEBUG_TWO,DEBUG_THREE and at each log call based on the logging level i wud check for that #define so if that is a basic msg I would say
    #ifdef DEBUG_ONE
    log....
    #endif
    and ofcourse in the header I would #define or undef them.

    2. pass a parameter to the log function and check it inside the log function. validate it against the set config value and if yes, print it.

    Thanks,

  2. #2
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    The only way that I could see doing the #define method would be to have multiple functions, that would work something like:
    Code:
    #ifdef DEBUG_ONE
    #define debug_one(...) fprintf(stderr, __VA_ARGS__)
    #else
    #define debug_one(...) ;
    #endif
    This prevents debugging from being set programmatically and prevents, for instance, config files.

    For these reasons, I suggest using the function-based one.

    I would note that there is already a library that does this called log4c:
    log4c: Log4c : Logging for C Library

    This is based on log4j, which is essentially the standard logging facility for Java.
    DISTRO=Arch
    Registered Linux User #388732

  3. #3
    Just Joined!
    Join Date
    Apr 2010
    Posts
    18
    Can you explain a little more on how you mean for the #define to work in your method. Sorry but I dont understand what u mean by calling debug_one function in both and then fprintf in one case..thank you in advance

  4. #4
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    So by using #define, there are basically two routes that you can take. One is to handle the log level in one location, and the other is to handle it everywhere. The first case is what I showed:
    Code:
    #ifdef DEBUG_ONE
    #define debug_one(...) fprintf(stderr, "LOG LEVEL 1: " __VA_ARGS__)
    #else
    #define debug_one(...) ;
    #endif
    Now in your code:
    Code:
    int foo(int bar)
    {
        debug_one("bar is %d\n", bar);
    
        ...
    
        debug_one("about to return %d\n", retval);
        return retval;
    }
    Whether the debug_one() output will actually appear is controlled by the define at the top of the file. This means that you can just call debug_one() whenever you want, and if DEBUG_ONE was defined for the file, the output will print. Otherwise it will not.

    The second approach (which may be what you were thinking of) would be to do this:
    Code:
    int foo(int bar)
    {
    #ifdef DEBUG_ONE
        fprintf(stderr, "bar is %d\n", bar);
    #endif
    
        ...
    
    #ifdef DEBUG_ONE
        fprintf(stderr, "about to return %d\n", retval);
    #endif
    
        return retval;
    }
    It should be obvious why this is an inferior solution. In the first solution, you only need to have the check for the DEBUG_ONE macro in a single place, whereas here you have to check for it whenever you want to print out debug information.

    If you were to use the first solution I gave, this works reasonably well for a single project that is reasonably contained (I'm actually using it for a project right now). However, if you want to create a more fully-featured system, you will find a function-based parameter solution a bit better, I think. Something like:
    Code:
    logger(DEBUG_ONE, "bar is %d\n", bar);
    The "logger" function could then check for whether DEBUG_ONE output is currently enabled. The cool thing about such a system is that these values could be configured from sort of external configuration file, like how log4c works (it uses a combination of config files and programmatic configuration).

    Does this help at all?
    DISTRO=Arch
    Registered Linux User #388732

  5. #5
    Just Joined!
    Join Date
    Apr 2010
    Posts
    18
    Thanks! I definitely got a better picture.

    Herez the thing though.. I plan on having 3-4 levels of logging.
    0 - Basic mesgs
    1 - Level 1 troubleshooting (tracing the application flow)
    2 - Level 2 troubleshooting (printing variable values etc at higher levels)
    3 - Level 3 (printing more detailed stuff)

    So based on the situation I could update my file to say this level and the application would log msgs of that category and lower
    So in the first scenario you mentioned I could not implement it without 4 functions for logging.

    That leaves me with the 2nd and 3rd scenario..now my qn is which is more efficient..more macros or more function calls.
    I thought about passing a parameter in the logMessage function but I was not sure if the function overhead caused by each time invoking it and passing all the parameters and then checking if reqd and returning ...though neater...is it better compared to checking macro definition at each level.

    Ofcourse if you have a solution to maintain the 4 levels and just do 1 check at 1 level that would be excellent.

    Thank you...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...