librdkafka custom logger, function signature - c++

I'm using the librdkafka c++ API and I would like to change the default behavior of the logger.
In the c API there is this function rd_kafka_conf_set_log_cb() to set the log callback. It takes a function with the signature:
void(*)(const rd_kafka_t *rk, int level, const char *fac, const char *buf)
However I can't figure out what const char *fac does in the function signature. I can see that strings such as "FAIL" or "BGQUEUE" are passed when using it, but I can't find any documentation on what they mean or how to use them.
What is the const char *fac used for, and are there docs on its use or a dictionary for their definitions?

The facility string is a semi-unique name for the context where the log is emitted. It is mainly there to help librdkafka maintainers identify the source of a log line, but can also be used for filtering purposes.
It was originally inspired by Cisco IOS like system logs which came in the form of:
FAC-LVL-SUBFAC: Message...
The librdkafka counterpart would be:
RDKAFKA-7-JOIN: Joining consumer group xyx
where JOIN is the librdkafka logging facility.

Related

C++ Interface for logger

I am working a big legacy project and need to redo the common logger.
I tried to make same logger interface with before to avoiding changing ton of loggers.
The reason I need to redo the logger is the old one is syslog UDP which was using built-in library functions, while the new one I'm using GELF UDP.
Suppose I have a log with two parts of message, severity is info. The old interface is like below:
Log_INFO<< "First part message" <<"Second part message"<< endl;
Log_INFO is like 'std::cout', but it has two functionality:
Print out message in the command line.
Collect it in Graylog.
My new function is like below:
//Severity = {debug,info,warning, error, critical}
Log(Severity, whole_message)
For the same example,
Log("info",first_part_message+ second_part_message)
My question is how can I make my function is able to read log like the old one.
One common way of doing this is creating a custom streambuf-derived class, say LogStreambuf, and an ostream-derived class, say LogStream, that uses LogStreambuf (but is otherwise a plain jane ostream).
Then your log objects would be
LogStream Log_INFO("info");
LogStream Log_WARN("warn");
etc.
Your custom streambuf probably should call your Log function from its sync method.
See e.g. this for an example, and this for further guidance.

Dump apache thrift messages for debugging purposes?

Apache Thrift is one of the more popular choices for an opensource RPC frameworks (gRPC is also one that gets lot of tracktion since release into the open).
In my setup in c++ Im using a TMultiplexedProcessor. I guess this could be any TProcessor for that matter since Im just interested in printing whatever is sent.
This has a method called:
bool process(std::shared_ptr<protocol::TProtocol> in,
std::shared_ptr<protocol::TProtocol> out,
void* connectionContext) override {
My idea was to override this again, so that I could print the in argument - but how can I write TProtocol to output ? (at a glance, it does not seem straightforward to serialize into a string)
I get a feeling there maybe is some other or an easier method. So my question is how can I dump all messages recieved via thrift (for debugging purpose) ?
There's TProtocolTap and TDebugProtocol.
Usage example can be found in thrift_dump.cpp:
shared_ptr<TProtocol> iprot(new TBinaryProtocol(itrans));
shared_ptr<TProtocol> oprot(
new TDebugProtocol(
shared_ptr<TTransport>(new TBufferedTransport(
shared_ptr<TTransport>(new TFDTransport(STDOUT_FILENO))))));
TProtocolTap tap(iprot, oprot);
std::string name;
TMessageType messageType;
int32_t seqid;
for (;;) {
tap.readMessageBegin(name, messageType, seqid);
tap.skip(T_STRUCT);
tap.readMessageEnd();
}

How to retrieve Steamwork SDK's current version

Is it possible to get steamworks SDK's current version through C++ from the Steamworks API?
If yes, how?
This is what I'm looking for
You can use
ISteamAppList * GetISteamAppList( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion );
...
pchVersion const char * The version string that identifies the version of the interface that you receive.
Retrieves the ISteamAppList interface associated with the specified user handle, only available on specially registered apps.

Can you use multiple message domains in boost::locale?

I have a number of applications that share a number of general libraries. I am trying to internationalize my applications using boost::locale. It will be easy for me to create a separate .mo file for each general library and for each specific application. I was wandering if it is possible to simultaneously use multiple message domains like this:
boost::locale::generator gen;
gen.add_messages_path(".");
gen.add_messages_domain("lib1");
gen.add_messages_domain("lib2");
std::locale::global(gen("zh_CN.UTF-8"));
.
.
.
boost::locale::gettext("Show image");
I was expecting boost::locale to search in both lib1.mo and lib2.mo, however this doesn't seem to work. Only messages from the first domain added are found, in this case from lib1.mo. If I add lib2 before lib1, then only messages from lib2 are found.
I know you can use a domain explicitly in the call like this:
boost::locale::dgettext("lib2", "Show image");
This does work, but I would like to avoid specifying the domain for every call. I am also not sure that this will work well with extracting the strings with xgettext.
Is it possible what I am trying to do? Am I missing something?
Please suggest any alternative if you know one.
I use msvc 9.0 (2008) and boost 1.48.
Since there were no answers posted to this question I assume that this is not possible with boost::locale. I will shortly therefore outline what I did to achieve my required functionality:
I created a singleton class with the following interface
class MY_GETTEXT
{
public:
void SetPath(const std::string& i_path);
void AddDomain(const std::string& i_domain);
void ChangeLocale(const std::string& i_locale);
std::string gettext(const std::string i_msg_id);
};
AddDomain is called for each domain you want to use, and adds it to a member set m_language_domains_a. ChangeLocale does some locale manipulation and stores a locale in the member m_locale, I will ignore its implementation here.
To translate you should simply call MY_GETTEXT::gettext. Its implementation looks like this:
std::string MY_GETTEXT::gettext(const std::string i_msg_id)
{
BOOST_FOREACH(const std::string& domain , m_language_domains_a)
{
if (boost::locale::translate(i_msg_id).str(m_locale, domain) != i_msg_id)
{
return boost::locale::translate(i_msg_id).str(m_locale, domain);
}
}
return i_msg_id;
}

Disable debug output in libxml2 and xmlsec

In my software, I use libxml2 and xmlsec to manipulate (obviously) XML data structures. I mainly use XSD schema validation and so far, it works well.
When the data structure input by the client doesn't match the XSD schema, libxml2 (or xmlsec) output some debug strings to the console.
Here is an example:
Entity: line 1: parser error : Start tag expected, '<' not found
DUMMY<?xml
^
While those strings are useful for debugging purposes, I don't want them to appear and polute the console output in the released software. So far, I couldn't find an official way of doing this.
Do you know how to suppress the debug output or (even better) to redirect it to a custom function ?
Many thanks.
I would investigate the xmlSetGenericErrorFunc() and xmlThrDefSetGenericErrorFunc() functions, they seem right. The documentation is .. sparse, though.
Here is some Python code that seems to use these functions to disable error messages, the relevant lines look like this:
# dummy function: no debug output at all
cdef void _nullGenericErrorFunc(void* ctxt, char* msg, ...) nogil:
pass
# setup for global log:
cdef void _initThreadLogging():
# disable generic error lines from libxml2
xmlerror.xmlThrDefSetGenericErrorFunc(NULL, _nullGenericErrorFunc)
xmlerror.xmlSetGenericErrorFunc(NULL, _nullGenericErrorFunc)
I was looking for the same solution for some C code:
static void __xmlGenericErrorFunc (void *ctx, const char *msg, ...) { }
xmlSetGenericErrorFunc(nil, __xmlGenericErrorFunc);
xmlThrDefSetGenericErrorFunc(nil, __xmlGenericErrorFunc);