Implement Minimal logging program in c++ - c++

I am developing a disk based tree for a database engine and i like to maintain a log file for my program. I basically need two kinds of functionality from the log program. It must allow me to log a message into a log file and also must write any variable that i pass it as an argument into the log file. I need only these two functions. The first is fairly simple to achieve but i am finding it hard to achieve the second one. I want to pass any number of arguments of any type to the log program to write it into the log file. I tried to achieve the second one using variable argument function but the problem is we must know the type of the variables that are being passed. I am sure there must be some way to do this. Can anyone enlighten me on this?

log4C++ provides the functionality you're looking for.
If that is a little too heavy weight for you you can do something similar using templates. Something like:
class log
{
private:
std::ostream& stream;
public:
log(std::ostream& src) : stream(src) {}
...
std::ostream& getStream() { return stream; }
}
template <typename T> log& operator<<(log&, const T& val)
{
log.getStream() << val;
return log;
}
Here log::stream is some std::ostream instance you defined for output to a file, to a console or whatever. You can make it a bit fancier by distinguishing between different types of logging events.

Have a look at the implementation of this simple logging system from Dr Dobs article: http://drdobbs.com/cpp/201804215
It is template based, has logging levels (that don't incur any overhead at run-time if not needed) and is small

Related

How to use streams in abstract classes

This might seem like an opinion question but I'm really looking for some good ways to go about doing this. so what's this? I basically want to have an abstract class named Repo let's say. This class is going to define the abstraction for what a Repo should be capable of doing. In this case, I just want to be able to save something, say you provide a name and data and it's supposed to store it for you. Then we can have a FileRepository that would save them on disc, S3Repository for example to store them in the AWS S3, or even MemoryRepository where we just save them in the memory.
Great, but how do I abstract this out? obviously I could get the bytes and each derived class would use their own stream to save it but what if the data is large and we don't want to load it up in the memory? let's say we want to save a 5GB file, we don't want to load that up in the memory.
I looked at the AWS SDK for C++ and it seems like they take a lambda with an ostream in it so you can write content. I tried to mimic something like that here so you can either just pass your istream, or give a lambda that takes an ostream and does whatever its heart desires.
Just wondering if there is a better way for this? it's often difficult to find good practices in c++ since there are a billion ways to do the same thing and many people do things very differently. I'd just love some insight here. I'm fairly new to C++ so a good explanation would be highly appreciated.
class Repo {
public:
virtual void add_with_ostream(const string& name, const std::function<void (ostream&)>& f) = 0;
template<typename T>
void add(const string& name, const T& data) {
this->add_with_ostream(name, [&data](ostream& output_stream) {
output_stream << data;
});
}
virtual void add_with_istream(const string&name, const istream& input_stream) {
this->add_with_ostream(name, [&input_stream](ostream& output_stream) {
output_stream << input_stream.rdbuf();
});
}
};

C++ logging class instance identifier

In my project, some classes are instantiated more than once. Each class logs some events. The logging method is a generic one used all around the project and it uses the standard cout. The log message contains the time, name of the class, name of the method, a variable value, and a custom message.
The disadvantage is that the log is not instance specific. I do not know which instance of the class wrote the log.
Is there a nice way to solve this problem without adding additional static members as instance counters to the classes? I am using boost and C++11. Maybe boost has something that might help.
The only solution I can think of is to include the instance address (this) to the log.
You will need to differentiate between different classes somewhere, these are a few options (all rely on some kind of ID):
Add some additional static variable.
Not an option for you, but in my opinion, the best way to go if you aim for readability.
Use this, as you suggested:
This obviously generates unique IDs, but they will tend to be unreadable and hard to distinguish with growing address lengths (as only one or two characters might differ in a lengthy address string). Also, the addresses are likely to change between every run of the application (especially when employing ASLR), so you won't be able to see which exact instance created which line of output (if that's required).
Use this and hash the value:
To be honest, I don't see much of a difference to 2), but it might trigger some further ideas. Some ugly hack could look like this:
#include <iostream>
#include <functional>
#include <cstddef>
class Logger
{
public:
static void log(void* ptr)
{
using hash_type = std::uintptr_t;
std::cout << std::hash<hash_type>{}(reinterpret_cast<hash_type>(ptr))
<< " logged something..." << std::endl;
}
};
You can also consider specializing std::hash for your classes and use that in the logging output. This would remove the problem of changing addresses between different runs, if implemented properly.
Generate an ID during construction (e.g. by passing some identifier to the constructor):
This is not really an option since you have no evidence or control that a unique ID is generated for each class - unless you use some kind of (abstract) factory with access to a private constructor or some kind of global registry (see below).
Use some helper utility where your logging classes are registered and unique IDs are generated (something like a registration class).
For simple logging purposes, IMHO this is bloat and does not add any value compared to 1).
Conclusion:
I would go for option 1) if readability for humans is of concern and for 2) if you simply want some number to distinguish between log messages (e.g. for piping and filtering).
You can quite easily generate IDs via CRTP adaptor like that (if you can modify your classes a bit)
template<typename T>
struct enable_id
{
int id = global_id++;
private:
static int global_id;
};
template<typename T>
int enable_id<T>::global_id = 0;
class foo : public enable_id<foo>
{
};
template<typename T>
void log(const T& t)
{
// if is_base_of
std::cout << t.id << std::endl;
}
The easier way to fix the problom is to print the address to indicate which object it is. As following:
cout<<static_cast<void*>(this)<<endl;
Or output some features.
I usually have a protected class member containing the time of instance's creation at the root of all my class hierarchies, at least at the debugging stage. Very helpful for multi-threaded applications also.
Convert this time to whatever you want - string, milliseconds, epoch time - and you have a unique id for each and every instance.
If there are only a few instances of class going to be, I would suggest you introduce a string member and initialize it with a unique name during object creation. It will help you in logs reading. By default, it may be initialized with object's address.

C++ logging wrapper design

I would like to add a log to my application. I've picked a logging library but I'd like to be able to switch to a different library without having to alter any code that uses logging.
Therefore, I need some sort of logging wrapper that is flexible enough to utilize pretty much any underlying logging library's functionality.
Any suggestions for such a wrapper's design?
EDIT: one feature I must have in this wrapper is component tagging. I want my algorithm class to have "X:" appear ahead of its log lines, and my manager class to have "Y:" appear. How to propagate this these tags onto the underling log and how to build the component tag naming mechanism is one major design question here.
Your best bet is to make the interface as simple as possible. Completely separate the logging user's interface from how the logging actually gets implemented.
Cross-cutting concerns always are expensive to maintain, so making things any more complicated will make you hate life.
Some library only wants something simple like this:
void logDebug(const std::string &msg);
void logWarning(const std::string &msg);
void logError(const std::string &msg);
They shouldn't add or specify any more context. No one can use the information anyway, so don't over design it.
If you start adding more information to your logging calls it makes it harder to reuse the client code that uses it. Usually you will see this surface when components are used at different levels of abstraction. Especially when some low level code is providing debug information that is only relevant to higher levels.
This doesn't force your logging implementation (or even the interface the logging implementation conforms to!) into anything either, so you can change it whenever.
UPDATE:
Insofar as the tagging, that is a high level concern. I'm going to speculate that it doesn't belong in the log, but that is neither here nor there.
Keep it out of the logging message specification. Low level code shouldn't give a flying truck who you or your manager is.
I don't know how you specify X or Y in your example. How you do that isn't really obvious from the description we are given. I'm going to just use a string for demonstration, but you should replace it with something type safe if at all possible.
If this is always on, then just having an instance context (probably a global variable) might be appropriate. When you log in, set the context and forget about it. If it ever isn't set, throw with extreme prejudice. If you can't throw when it isn't set, then it isn't always on.
void setLoggingContext("X:");
If this changes at different levels of abstraction, I would consider a stack based RAII implementation.
LoggingTag tag("X:");
I'm not sure what your requirements are in the scenario when different stack frames pass in different values. I could see where either the top or the bottom of the stack would be reasonable for differing use cases.
void foo() {
LoggingTag tag("X:");
logWarning("foo");
bar();
baz();
}
void bar() {
LoggingTag tag("Y:");
logWarning("bar");
baz();
}
void baz() {
logWarning("baz");
}
Either way this shouldn't affect how you add a message to the log. The baz function doesn't have the context to specify the LoggingTag. It's very important that using logWarning doesn't know about tags for this reason.
If you wanted to tag based on some type, you could do something simple like this.
struct LoggingTag {
LoggingTag(const std::string &tag_) : tag(tag_) {}
template<typename T>
static LoggingTag ByType() {
return LoggingTag(typeid(T).name());
}
std::string tag;
};
void foo() {
LoggingTag tag = LogginTag::ByType<int>();
}
This wouldn't force someone to use typeid(T).name() if they didn't want to, but gave you the convenience.
I like this approach:
class Log {
public:
virtual logString(const std::string&)=0;
};
template <typename T>
Log& operator<<(Log& logger, const T& object) {
std::stringstream converter;
converter << object;
logger.logString(converter.str());
return logger;
}
Simple and quick! All you need to do is reimplement the logString method...
Take a look at zf_log library. It is very small (~2000k lines, ~10KB when compiled) and fast (see comparison table in README.md). It is very close to what you describe as wrapper. It gives you an abstract API that you can use in your project and allows to specify what actual logging implementation to use. See custom_output.c example where syslog is used as output facility. It also could be used privately inside libraries without risk of getting into conflict with other code that could use this library (see ZF_LOG_LIBRARY_PREFIX define for more info).
Even if it's not exactly what you are looking for, I guess it could be a good example for your wrapper thing.

Efficiently maintain slightly different (logging/non-logging) functions

I have a number of algorithms for community detection on graphs that I want to now visualise them. This visualisation requires me to 'hijack' these algorithms while they execute and log what they are doing. Specifically this will mean passing a reference to a std::vector<graph_partition> as an argument to these algorithms, and appending to that vector as the algorithm proceeds.
Therefore to each algorithm (which are typically just functions), I would need to add a further argument for the &std::vector<graph_partition>, and one or two lines of code for the logging.
I will not always want/need to log however, and so doing this in an intelligent way has proved non-trivial. I have thought of:
Write separate logging versions of each algorithm: The problem here is that I'll be repeating myself massively, since 95% of the logging and non-logging functions will be the same. You could say my code should be so modular that no repetition should occur, but in practice unless I have lots of tiny trivial functions I would have to repeat myself.
Have single function with a conditional argument to decide whether to log or not: Problem is what do I pass for &std::vector<graph_partition> when I don't want to use it? Also (probably minuscule) runtime hit of continuously evaluating conditional.
Some macro wizardry: Macros are a bit evil and would prefer to avoid them if possible.
Just log by default, discard if I don't need it: Convenient but wasteful, both in terms of runtime and space.
Any ideas or thoughts on these would be appreciated.
If you fancy using templates, I don't think you really need variadic templates. If you're happy to recompile in order to switch logging on and off:
struct NoLogging {
void log(const graph_partition &) {}
};
struct Logging {
std::vector<graph_partition> vec;
void log(const graph_partition &p) {
vec.push_back(p);
}
};
template <typename Logger>
void some_algorithm(Logger &logger) {
// do some stuff
logger.log(something);
}
// optionally, for convenience
void some_algorithm() {
NoLogging l;
some_algorithm(l);
}
// user writes:
some_algorithm();
// or
Logging l;
some_algorithm(l);
// do something with l.vec
The difference between this and "just log by default, even if I don't need it", is that an even vaguely decent compiler will completely remove the calls to log in some_algorithm<NoLogging>, because it can see that they do nothing.
If you don't want to have to recompile, you could have a runtime switch between the two different sets of instantiations - it may or may not be convenient to do this via some polymorphic interface that provides all the algorithms and has two derived classes, from a template like so:
template <typename Logger>
struct ConcreteAlgorithms : public Algorithms {
Logger logger;
static void some_algorithm() {
::some_algorithm(logger);
}
// more algorithms
};
Algorithms *get_algorithms(bool with_logging) {
if (with_logging) {
return new ConcreteAlgorithms<Logging>;
} else {
return new ConcreteAlgorithms<NoLogging>;
}
}
However, at this point you're going to have the code bloat of two different versions of the algorithms, so you might prefer to make the logger polymorphic and take the (probably tiny) runtime overhead instead, as per Mark's answer.
Pass a pointer to a parent logging class to each function. Have a child of the logging class that implements the logging function as a do-nothing, and use that one when you don't need logging. The real logging class would also be a child, and would contain the vector or a reference to it.

How to perform type scanning in C++?

I have an ESB. Any serialized message transports its own fully qualified name (that is, namespace + class name). I have a concrete type for each message that encapsulates a specific logic to be executed.
Every time I receive a message, I need to deserialize it at first, so I can perform its operations --once more, depending on its concrete type--.
I need a way to register every single class at compile time or during my application initialization.
With .net I would use reflection to scan assemblies and discover the message types during initialization, but how would you do it in C++?
C++ has no reflection capability. I suppose you could try to scan object files, etc., but there's no reliable way to do this (AFAIK); the compiler may entirely eliminate or mangle certain things.
Essentially, for serialization, you will have to do the registration (semi-)manually. But you may be interested in a serialization library that will help out with the chores, such as Boost Serialization.
Since there is no reflection in C++, I would suggest using an external script to scan your source code for all relevant classes (which is easy if you use empty dummy #defines to annotate them in the source code) and have it generate the registration code.
I personally use the manual registration road. If you forget to register... then the test don't work anyway.
You just have to use a factory, and implement some tag dispatching. For example:
typedef void (*ActOnMessageType)(Message const&);
typedef std::map<std::string, ActOnMessageType> MessageDispatcherType;
static MessageDispatcherType& GetDispatcher() {
static MessageDispatcherType D; return D;
}
static bool RegisterMessageHandler(std::string name, ActOnMessageType func) {
return GetDispatcher().insert(std::make_pair(name, func)).second;
}
Then you just prepare your functions:
void ActOnFoo(Message const& m);
void ActOnBar(Message const& m);
And register them:
bool const gRegisteredFoo = RegisterMessageHandler("Foo", ActOnFoo);
bool const gRegisteredBar = RegsiterMessageHandler("Bar", ActOnBar);
Note: I effectively use a lazily initialized Singleton, in order to allow decoupling. That is the registration is done during the library load and thus each Register... call is placed in the file where the function is defined. The one difference with a global variable is that here the dispatching map is actually constant once the initialization ends.