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.
Related
Suppose I have a situation, where I have an SDK which provides certain interface, which implies some manual resources management or state changes. It is supposed to be used like this:
// SDK has state B by default
SDK->setStateA();
something();
requiring();
stateA();
SDK->setStateB();
Is it a good idea to incapsulate state changes as custom allocator/deleter for unique_ptr object or, probably, it would be better to get this behaviour through some manual Dispose pattern implementation.
Since it's not a resource allocation, I have doubts. It might cause confusion and make code cryptic.
My other concern is that I need a return code from both init and clean up steps. I could use lambdas and get those through captures, but it looks even more cryptic.
Maybe someone tried it already and saw how it makes code look after a while?
Generally, it is best to design the interface of the code in such a way that it is easy to use and intuitive, or, put differently, that it's hard to use it wrongly. In particular, if the interface is able to prevent bugs by refusing compilation, it can save a lot of debugging time.
One possibility to achieve such an interface would be something that can be loosely related to the std::mutex <---> std::unique_lock mechanics:
class state_guard {
std::unique_ptr<SDK_type>& SDK;
state_guard(std::unique_ptr<SDK_type>& s) : SDK{ s } {
SDK->setStateA();
}
~state_guard() {
SDK->setStateB();
}
};
void something(state_guard&, ...);
void requiring(state_guard&, ...);
void stateA(state_guard&, ...);
std::unique_ptr<SDK_type> SDK{ get_sdk() };
{
state_guard guard{ SDK };
something(guard, ...);
requiring(guard, ...);
stateA(guard, ...);
}
By forcing to pass the guard as a function argument (even if it is unused in the respective function), the user cannot forget to set to stateA (and thanks to RAII, to reset it to stateB).
Given the following, working code.
#include <iostream>
template<class Detail>
class AbstractLogger
{
public:
static void log(const char* str) {
Detail::log_detailled(str);
}
};
class Logger : public AbstractLogger<Logger>
{
public:
static void log_detailled(const char* str) {
std::cerr << str << std::endl;
}
};
int main(void)
{
AbstractLogger<Logger>::log("main function running!");
return 0;
}
Now, I want to put AbstractLogger into a library, and let the library user define his own logger, like the Logger class here. This has one drawback: AbstractLogger<Logger> can not be used inside the library, since the library can not know Logger.
Notes:
Please no virtual functions or questions why not. Also, I am aware of the similar problem that "static virtual" members are invalid. Maybe, there is a workaround in CRTP :)
C++11 will be interesting, however, I need "usual" C++.
If what you mean is that you want to have a library that uses this as a logging mechanism without knowing the exact instantiating type, I would advice against it.
The only way of doing it while meeting your other requirements (i.e. no virtual functions) is that all your functions/types in the library that need to log are converted into templates that take the Logger type. The net result is that most of your interface becomes a template (although you can probably move a good amount of the implementation to non-templated code, it will make your life much harder than needed, and it will still generate a much larger binary).
If your concern with virtual functions is performance, then you should reconsider your approach and the problems it brings. In particular, logging is expensive. Most logging libraries tackle it by optimizing the non-logging case (by means of macros that avoid calling the logger if the log level/group/... are not enabled), but still leave dynamic dispatch for the actual writting. The cost of the dynamic dispatch is negligible compared with the cost of writing to the console, or a file, or even with the cost of generating the message that will be logged (I am assuming that you not only log literal strings)
The usual approach is to code against a concept, while providing helpers so that users may easily produce types that satisfy one or more of those concepts. As an example, something like boost::iterator_facade is a CRTP helper that makes it easier for a user to write an iterator. Then, that iterator can be used anywhere an iterator is accepted -- for instance in the range constructor of std::vector. Notice how that particular constructor has no foreknowledge of the user-defined type.
In your case, AbstractLogger would be the CRTP helper. The missing piece would be to define e.g. a logger concept. As a result, notice that everything that needs a logger either needs to be implemented as a template or you need a type-erasing container to hold arbitrary loggers.
Concept checks (like those provided by Boost) are convenient for this kind of programming, since they allow to represent a concept with actual code.
Template classes can't be 'put in a library' since they are instantiated by the compiler as specializations of their template parameters.
You may put parameter independent stuff used in the template implementation into a library though.
I have written/am writing a piece of physics analysis code, initially for myself, that will now hopefully be used and extended by a small group of physicists. None of us are C++ gurus. I have put together a small framework that abstracts the "physics event" data into objects acted on by a chain of tools that can easily be swapped in and out depending on the analysis requirements.
This has created two halves to the code: the "physics analysis" code that manipulates the event objects and produces our results via derivatives of a base "Tool"; and the "structural" code that attaches input files, splits the job into parallel runs, links tools into a chain according to some script, etc.
The problem is this: for others to make use of the code it is essential that every user should be able to follow every single step that modifies the event data in any way. The (many) extra lines of difficult structural code could therefore be daunting, unless it is obviously and demonstrably peripheral to the physics. Worse, looking at it in too much detail might give people ideas - and I'd rather they didn't edit the structural code without very good reason - and most importantly they must not introduce anything that affects the physics.
I would like to be able to:
A) demonstrate in an obvious way that
the structural code does not edit the
event data in any way
B) enforce this once other users
begin extending the code themselves
(none of us are
expert, and the physics always comes
first - translation: anything not
bolted down is fair game for a nasty
hack)
In my ideal scenario the event data would be private, with the derived physics tools inheriting access from the Tool base class. Of course in reality this is not allowed. I hear there are good reasons for this, but that's not the issue.
Unfortunately, in this case the method of calling getters/setters from the base (which is a friend) would create more problems than it solves - the code should be as clean, as easy to follow, and as connected to the physics as possible in the implementation of the tool itself (a user should not need to be an expert in either C++ or the inner workings of the program to create a tool).
Given that I have a trusted base class and any derivatives will be subject to close scrutiny, is there any other roundabout but well tested way of allowing access to only these derivatives? Or any way of denying access to the derivatives of some other base?
To clarify the situation I have something like
class Event
{
// The event data (particle collections etc)
};
class Tool
{
public:
virtual bool apply(Event* ev) = 0;
};
class ExampleTool : public Tool
{
public:
bool apply(Event* ev)
{
// do something like loop over the electron collection
// and throw away those will low energy
}
};
The ideal would be to limit access to the contents of Event to only these tools for the two reasons (A and B) above.
Thanks everyone for the solutions proposed. I think, as I suspected, the perfect solution I was wishing for is impossible. dribeas' solution would be perfect in any other setting, but its precisely in the apply() function that the code needs to be as clear and succinct as possible as we will basically spend all day writing/editing apply() functions, and will also need to understand every line of these written by each of the others. Its not so much about capability as readability and effort. I do like the preprocessor solution from "Useless". It doesn't really enforce the separation, but someone would need to be genuinely malicious to break it. To those who suggested a library, I think this will definitely be a good first step, but doesn't really address the two main issues (as I'll still need to provide the source anyway).
There are three access qualifiers in C++: public, protected and private. The sentence with the derived physics tools inheriting access from the Tool base class seems to indicate that you want protected access, but it is not clear whether the actual data that is private is in Tool (and thus protected suffices) or is currently private in a class that befriends Tool.
In the first case, just make the data protected:
class Tool {
protected:
type data;
};
In the second case, you can try to play nasty tricks on the language, like for example, providing an accessor at the Tool level:
class Data {
type this_is_private;
friend class Tool;
};
class Tool {
protected:
static type& gain_acces_to_data( Data& d ) {
return d.this_is_private;
}
};
class OneTool : public Tool {
public:
void foo( Data& d ) {
operate_on( gain_access_to_data(d) );
}
};
But I would avoid it altogether. There is a point where access specifiers stop making sense. They are tools to avoid mistakes, not to police your co-workers, and the fact is that as long as you want them to write code that will need access to that data (Tool extensions) you might as well forget about having absolute protection: you cannot.
A user that wants to gain access to the data might as well just use the newly created backdoor to do so:
struct Evil : Tool {
static type& break_rule( Data & d ) {
return gain_access_to_data( d );
}
};
And now everyone can simply use Evil as a door to Data. I recommend that you read the C++FAQ-lite for more insight on C++.
Provide the code as a library with headers to be used by whoever wants to create tools. This nicely encapsulates the stuff you want to keep intact. It's impossible to prevent hacks if everyone has access to the source and are keen to make changes to anything.
There is also the C-style approach, of restricting visibility rather than access rights. It is enforced more by convention and (to some extent) your build system, rather than the language - although you could use a sort of include guard to prevent "accidental" leakage of the Tool implementation details into the structural code.
-- ToolInterface.hpp --
class Event; // just forward declare it
class ToolStructuralInterface
{
// only what the structural code needs to invoke tools
virtual void invoke(std::list<Event*> &) = 0;
};
-- ToolImplementation.hpp --
class Event
{
// only the tool code sees this header
};
// if you really want to prevent accidental inclusion in the structural code
#define TOOL_PRIVATE_VISIBILITY
-- StructuralImplementation.hpp --
...
#ifdef TOOL_PRIVATE_VISIBILITY
#error "someone leaked tool implementation details into the structural code"
#endif
...
Note that this kind of partitioning lends itself to putting the tool and structural code in seperate libraries - you might even be able to restrict access to the structural code seperately to the tool code, and just share headers and the compiled library.
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.
I have been working a year now as a software developer for a at the computer-vision department of a company. My main job is integration of third-party software into a framework, so i usually end up writing wrapper libraries because a lot of this third party software does not work the way we want it to work(not thread safe, pain in the a** to use etc.).
Normally i just wrap the whole library and guard the calls to the library with mutual exclusions(thread safety is somehow the major problem with most extern libraries). I really enjoy doing this, as it puts you into a lot of interesting situations and you get to see a lot of interesting code. However i often think that i am not doing it properly or that my implementation is not really good. I feel like i am lacking some sort of design knowledge on how to properly do stuff like that.
Basically i want to know if there are any good guidelines or hints about designing a proper 'API ontop of broken API', or if this is always bound to be quite hackish and ugly.
I will quote an answer to another question on here the other day:
Does your current method pass testing?
Is it fast enough?
If yes, keep doing what you are doing.
As an alternative
Just ensure your new API encompasses both the intended functionality and the conventional or accidental functionality of the original. Also ensure it presents a 'fit-for-purpose' re-presentation. Take a peek at the C++ wrapping of C libraries in FOSS projects such as GTK/GTK for C++ (which just wraps the former).
If the API is broken, fix it and submit a patch ... get involved with the third-parties (I am assuming having access to the source means they won't mind this) ... You could re-write some of their API to be 'wrapping friendly' and suggest they merge some changes. If there is a problem, be the one to fix it.
Not much to it, just wrap A with B and ensure B does what A was supposed to, or is used for.
The only thing that I can add to Aiden's response is that you should also look to replace code that requires explicit initialization and termination with RAII techniques. When I've been faced with providing a façade over APIs, I always seem to run into a class that looks like:
struct ADVERTISER {
/* a bunch of members here */
};
void adv_Initialize(ADVERTISER *adv, /* a bunch of arguments */);
void adv_DoStuff(ADVERTISER *adv);
void adv_Terminate(ADVERTISER *adv);
I've seen this wrapped in a C++ class in the following manner:
namespace wrapper {
class Advertiser {
public:
Advertiser(): inited_(false) {}
void initialize(/* a bunch of arguments */) {
terminate();
adv_Initialize(&adv_, ...);
inited_ = true;
}
void doStuff() {
validate();
adv_DoStuff(&adv_);
}
void terminate() {
if (inited_) {
adv_Terminate(&adv_);
inited_ = false;
}
}
protected:
void validate() {
if (!inited_) {
throw std::runtime_error("instance is not valid");
}
}
private:
ADVERTISER adv_;
bool inited_;
};
}
The problem is that the Advertiser class doesn't really make the API any easier to use or even cleaner IMHO. If you run into cases like this, then:
Use a fully parameterized constructor to ensure that invalid instances do not exist
Clean up all resources in the destructor
Write a copy constructor and assignment operator if they make sense or make them private and don't implement them.
My goal is to make sure that whatever API I am presenting/creating/wrapping works with our existing coding style. I also try to bend the API into a more OO style than it may currently be in. I have seen a number of what I call object-oriented C like the one that I presented above. If you want to make them really fit into C++, then make then truly object-oriented and take advantage of what C++ gives you:
Be careful to manage any state variables.
If actions like copying don't make sense, then hide them.
If there is any possibility of leaking resources, then find some way to prevent it from happening (usually employing RAII helps).
Restrict the creation of instances using constructors to eliminate invalid instances and other edge cases.