Reputation: 7
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
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
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
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