2

I wonder, what is the best trace technique for you. Currently, I am defining trace level for each source witch macro just before including trace header, which is using defined macro.

For example: trace.h:

#if DEBUG == 0
#define debug(...) 
#define trace(...)

#elif DEBUG==1
#define debug(...) 
#define trace(...) printf(__VA_ARGS__)

#elif DEBUG==2
#define debug(...) printf(__VA_ARGS__)
#define trace(...) printf(__VA_ARGS__)

#else
#error Bad DEBUG value
#endif

For all sources.c (trace_value varies)

#define DEBUG trace_value
#include "trace.h"

void func(){
  debug("func()");
  trace("func() ok");
  reurn;
}

However, project grows and I want to use precompiled header. It would be great to include trace header in my precompiled header. So I am wondering, what are your trace techniques? Thank you.

EDIT: I forgot to write important thing, I am interested in logging technique for latency critical application.

Mihalko
  • 563
  • 2
  • 5
  • 14
  • Have a look at log4c (http://log4c.sourceforge.net/) and how it's done there. – alk May 07 '14 at 07:41
  • See how that is done in [Gstreamer](https://community.freescale.com/docs/DOC-93791) and [wine](http://wiki.winehq.org/DebugChannels) – alexander May 07 '14 at 08:07

1 Answers1

1

Logging is a complex issue and what it does/how you use it depends greatly on the needs of your application.

In small applications, I tend to use either injected std::ostream references, or custom code for logging specifically. I also stay away from the C formatted printing APIs (and define my own operator<< for things I need to trace).

In large applications, if you have complex tracing needs (rotate log files between executions, logs per category and configurable from outside the application, automatic log formatting, high-throughput/performance logging, and so on) use an external library (like log4cpp).

I also tend to use/define macros, only after all my code can be written without them.

Example implementation with injected logging stream:

#include<iosfwd>

class http_server {
public:
    http_server(std::string server, std::uint16_t listening_port,
        std::ostream& log = cnull); // cnull is as defined at 
                                    // http://stackoverflow.com/a/6240980/186997
private:
    std::ostream& log_;
};

Main (console) code:

int main(...) {
    http_server("localhost", 8080, std::clog);
}

Unit test code:

std::ostringstream server_log;
http_server("localhost", 8080, server_log);
// assert on the contents of server_log

Basically, I consider that if I need tracing, it is a part of the API interface and not an afterthought, something I would disable through macros, or something to hardcode.

If I need formatted logging, I would consider specializing a std::ostream, or (most probably) wrapping it into a specialized formatting class and injecting that around.

Macros for tracing code are usually reserved for performance-critical code (where you cannot afford to call stuff if it doesn't do anything).

utnapistim
  • 26,809
  • 3
  • 46
  • 82