vikash448
vikash448

Reputation: 7

Printing Debug statements at runtime in C per function

I want to understand if there is a way to print debug statements for Particular method in C program.

For example:

Say I have a main function which calls other 3 functions abc(), def() and xyz(). Each of these methods has some print statements for debug logging purpose. If I enable the debug macro currently all the functions debug messages are getting printed, ehich creates a large log file. Say I am having some issue in function xyz() and I just want to turn on the debug statements of this function, how I can achieve this in C?

Upvotes: 0

Views: 764

Answers (3)

Catch22
Catch22

Reputation: 401

This is what I like to do:

#define LOG_ABC 1
#define LOG_DEF 0
#define LOG_XYZ 0

void mylogger(const char *funcname, const char *fmt, ...) 
{
   if ((strcmp(funcname, "abc") == 0 && LOG_ABC) ||
       (strcmp(funcname, "def") == 0 && LOG_DEF) ||
       (strcmp(funcname, "xyz") == 0 && LOG_XYZ)) 
   {
        va_list ap;
        va_start(ap, fmt);

        vprintf(fmt, ap);
        va_end(ap);
    }
}

#define MYLOG(fmt, ...) mylogger(__FUNCTION__, fmt, __VA_ARGS__);

void abc(char *name) {
   MYLOG("Hello %s\n", name);
}

void def(int x) {
   MYLOG("Received x = %d\n", x);
}

//... and so on

Simply change the LOG_ABC /LOG_DEF / LOG_XYZ to enable disable logging from each function.

Infact in my own projects I use a variation of this. I also pass __FILE__ and __LINE__ so that the logger can also show me the file and line number of the log message - makes it easy for debugging.

More importantly, instead of using the function name, I define log categories, and log severity. So my logging looks like this:

MYLOG(LOG_DATAPATH, LOG_WARNING, "My log message %d %s", x, y);

And I can enable and disable individual categories, and also specify the minimum severity.

Upvotes: 1

pifor
pifor

Reputation: 7882

A solution without macros but requiring C coding and using an environment variable that avoids to recompile:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void mylog(char *fc, char *msg)
{
    char *debug;

    debug = getenv("DEBUG");
    if (debug != NULL)
    {
      if (strcmp(fc, "abc") == 0 && strstr(debug, ":abc") != NULL) 
        printf("%s", msg);
      if (strcmp(fc, "def") == 0  && strstr(debug, ":def") != NULL) 
        printf("%s", msg);
      if (strcmp(fc, "xyz") == 0  && strstr(debug, ":xyz") != NULL) 
        printf("%s", msg);
    }
}

void abc()
{
    mylog("abc", "entry abc\n");
    mylog("abc", "exit abc\n");
}

void def()
{
    mylog("def", "entry def\n");
    mylog("def", "exit def\n");
}

void xyz()
{
    mylog("xyz", "entry xyz\n");
    mylog("xyz", "exit xyz\n");
}


int main(int argc, char **argv)
{

    abc();
    def();
    xyz();

    return 0;
}

Execution:

$ export  DEBUG=:xyz
$ ./debug
entry xyz
exit xyz
$ export  DEBUG=:abc:xyz
$ ./debug
entry abc
exit abc
entry xyz
exit xyz

Upvotes: 1

Some programmer dude
Some programmer dude

Reputation: 409146

For a very simple solution, you might be able to do it with conditional compilation and naming your macros differently depending on what they will be use for (or from).

For example you could have something like (pseudo-code):

#ifdef ENABLE_LOG_ABC
# define LOG_ABC(...) real_logging_function(...)
#else
# define LOG_ABC(...) /* empty */
#endif

Then add something similar for the def and xyz functions.

To enable logging for only the abc function, only define ENABLE_LOG_ABC but no other when building. To enable for abc and xyz then define both ENABLE_LOG_ABC and ENABLE_LOG_XYZ.

With that said, if you want more advanced control and possibly by able to change such things at rtun-time, then I really recommend you try to find a third-part library which can do it for you.

Upvotes: 3

Related Questions