when I used GLog for logfile, I want to write my glog file to differnt logfile like log4j,but It seems like that the Glog don't support this, How can I do and can I init two glog in one function, please help
Here are some suggestions.
Glog support user defined logger. You can implement your own logger like below.
class AsyncLogger : public google::base::Logger
You can pass some flag in message and then store the log to the corresponding file according to the flag.
void AsyncLogger::Write(bool force_flush, time_t timestamp, const char* message,
int message_len) {
int flag = GetFlag(message);
string file_= file_name + flag + ".txt";
fwrite(message, 1, message_len, file_);
}
Create macro definition and add flag to message
#define ALOG_MODULE_STREAM_INFO(module) \
google::LogMessage(__FILE__, __LINE__, google::INFO).stream() \
<< flag << ","
And then set the logger to glog
google::base::SetLogger(FLAGS_minloglevel, async_logger);
Related
I created a shared library using BOOST using the following to specify the factory method:
BOOST_DLL_ALIAS_SECTIONED(
MyPlugin::create, // Plugin's factory method being exported
create_plugin, // Alias for factory method.
MySectionName) // The section name that all factory methods are grouped in.
The create() method returns a shared pointer to the MyPlugin object.
I then load the shared library and try to fetch the particular section using:
boost::dll::library_info inf(shared_library_path);
And then locate the above section with:
std::vector<std::string> sections = inf.sections();
if (std::find(sections.begin(), sections.end(), "MySectionName") == sections.end()) {
// Do something
} else
{
// Error out
}
If the shared library was not stripped, the above allows me to find
MySectionName within its contents and perform actions within the bracket.
If I however strip the shared library (default: strip library_name.so), the
above library info no longer lists the defined section and I hit the error out
condition.
I can protect the particular factory method during strip by specifying
"-Kcreate" flag, but while that works with this simple shared library, more
complex libraries end up with more missing symbols and it almost feels
counterproductive to keep expanding the "-K" flag.
Is here an easier way of using BOOST for plugin creation using the above method
and still allow stripping out debug information without having to expand with
"-K" flag?
Thank you
I couldn't reproduce this with shorter section names:
File test.cpp
#include <boost/dll.hpp>
#include <boost/dll/alias.hpp>
namespace MyPlugin {
struct X{};
static auto create() {
return std::make_shared<X>();
}
}
BOOST_DLL_ALIAS_SECTIONED(
MyPlugin::create,
Factory,
MySect)
File test1.cpp
#include <boost/dll.hpp>
#include <iostream>
int main() {
boost::dll::library_info inf("libsotest.so");
std::vector<std::string> s = inf.sections();
auto found = (std::find(s.begin(), s.end(), "MySect") != s.end());
std::cout << "Found: " << std::boolalpha << found << "\n";
}
Prints:
In fact, I cannot compile it at all when the section name exceeds 9 characters:
test.cpp|11 col 1| error: static assertion failed: Some platforms require section names to be at most 8 bytes
|| 11 | BOOST_DLL_ALIAS_SECTIONED(
Perhaps your problem is related to such restrictions?
I tried a example on Auto for variable initialization and STL in C++. For normal variable, type was printed using : typeid(var_name).name() to print i (integer) / d(float) / pi(pointer) which works fine.
But while working on STL,
`#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<string> st;
st.push_back("geeks");
st.push_back("for");
for (auto it = st.begin(); it != st.end(); it++)
cout << typeid(it).name() << "\n";
return 0;
}
`
which gives output like,
`N9__gnu_cxx17__normal_iteratorIPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt6vectorIS6_SaIS6_EEEE
N9__gnu_cxx17__normal_iteratorIPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt6vectorIS6_SaIS6_EEEE`
and I am unable to understand the output logic behind it, can anyone explain why it is giving output like this? and thanks in advance
That's the "name mangled" version of the name of the type of it. typeinfo::name() is not required by the standard to return a name in human-readable format (a shortcoming IMHO) and GCC doesn't do so.
To get the actual, human-readable name, you need to call the abi::__cxa_demangle() function provided by GCC, but note that this is non-portable so if your project needs to work on different compilers you'll need to wrap it appropriately.
I need a Boost logger which logs to console (and later on to a file), with following parameters:
"[%TimeStamp%] [%Severity%] [%File%(%Line%)] %Message%".
I have read the Boost.Log v2 docs and got some "inspiraton" from other places but I can't really get this to work.
// cswlogger.h
#pragma once
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
BOOST_LOG_GLOBAL_LOGGER(sysLogger,
boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>);
class CswLogger
{
public:
/// Init with default info level logging
static void init(boost::log::trivial::severity_level level = boost::log::trivial::info);
/// Disable logging
static void disable();
};
#define LOG_LOG_LOCATION(LOGGER, LEVEL, ARG) \
BOOST_LOG_SEV(LOGGER, boost::log::trivial::LEVEL) \
<< boost::log::add_value("Line", __LINE__) \
<< boost::log::add_value("File", __FILE__) << ARG
/// System Log macros.
/// TRACE < DEBUG < INFO < WARN < ERROR < FATAL
#define LOG_TRACE(ARG) LOG_LOG_LOCATION(sysLogger::get(), trace, ARG);
#define LOG_DEBUG(ARG) LOG_LOG_LOCATION(sysLogger::get(), debug, ARG);
#define LOG_INFO(ARG) LOG_LOG_LOCATION(sysLogger::get(), info, ARG);
#define LOG_WARN(ARG) LOG_LOG_LOCATION(sysLogger::get(), warning, ARG);
#define LOG_ERROR(ARG) LOG_LOG_LOCATION(sysLogger::get(), error, ARG);
#define LOG_FATAL(ARG) LOG_LOG_LOCATION(sysLogger::get(), fatal, ARG);
And source file:
// cswlogger.cpp
#include "cswlogger.h"
#include <boost/log/core.hpp>
#include <boost/log/common.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
BOOST_LOG_GLOBAL_LOGGER_DEFAULT(sysLogger,
boost::log::sources::severity_channel_logger_mt<boost::log::trivial::severity_level>);
void CswLogger::init(boost::log::trivial::severity_level level)
{
boost::log::add_console_log
(
std::clog,
boost::log::keywords::format = "[%TimeStamp%] [%Severity%] [%File%(%Line%)] %Message%"
);
boost::log::core::get()->set_filter
(
boost::log::trivial::severity >= level
);
// Indicate start of logging
LOG_INFO("Log Start");
}
void CswLogger::disable()
{
boost::log::core::get()->set_logging_enabled(false);
}
main.cpp
#include "cswlogger.h"
CswLogger::init();
LOG_INFO("This is a info trace");
The output of this will be: "[ ] [ ] main.cpp(3) This is a info trace"
The Timestamp and Severity paramaters are missing.
Is it possible to use the "BOOST_LOG_SEV" log macro and add custom log parameters or do I need to use another approach?
First, the TimeStamp attribute is missing in the output because you haven't added it to the logging core. You can add it as described here:
boost::log::core::get()->add_global_attribute(
"TimeStamp",
boost::log::attributes::local_clock());
Or you could add it as one of the commonly used attributes by calling add_common_attributes.
Next, the Severity attribute is present, it is provided by the logger. However, the value type of that attribute (which is boost::log::trivial::severity_level) is not supported by default for filters and formatters parsed from strings. You can solve this in two ways.
First, you can switch to the manual setup of the logging sinks, which will allow you to set the filter and formatter for the sink as a lambda expression. This way you will be able to provide the attribute type to the formatter. For example:
BOOST_LOG_ATTRIBUTE_KEYWORD(a_timestamp, "TimeStamp", boost::log::attributes::local_clock::value_type)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_severity, "Severity", boost::log::trivial::severity_level)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_file, "File", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(a_line, "Line", int)
typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > sink_t;
auto sink = boost::make_shared< sink_t >();
sink->set_formatter(boost::log::expressions::ostream
<< "[" << a_timestamp << "] "
<< "[" << a_severity << "] "
<< "[" << a_file << "(" << a_line << ")] "
<< boost::log::expressions::message);
boost::log::core::get()->add_sink(sink);
Alternatively, you can register the formatter and filter factories for the Severity attribute so that the formatter and filter parsers are able to associate that attribute with the boost::log::trivial::severity_level type. This is described in detail here. In your case, you can just add this call before any formatters are parsed (i.e. before the add_console_log call):
boost::log::register_simple_formatter_factory<
boost::log::trivial::severity_level, char >("Severity");
I am trying to run sample rsa/dsa code using libtomcrypt.
I have installed LibTomMath first as make install, as a result following files are created.
/usr/lib/libtommath.a
/usr/include/tommath.h
After that I installed libtomcrypt with LibTomMath as external library
CFLAGS="-DLTM_DESC -DUSE_LTM -I/usr/include" EXTRALIBS="/usr/lib/libtommath.a " make install
As a result following file is created
/usr/lib/libtomcrypt.a
I am not getting any error while running following command
CFLAGS="-DLTM_DESC -DUSE_LTM -I/usr/include" EXTRALIBS="/usr/lib/libtommath.a " make test
I have gone through this document libtomcrypt_installation and libtomcrypt_resolved to successfully compile using
gcc -DLTM_DESC rsa_make_key_example.c -o rsa -ltomcrypt
or
gcc rsa_make_key_example.c -o rsa -ltomcrypt
no compile error. However when I try to run, I got following error.
./rsa
LTC_ARGCHK 'ltc_mp.name != NULL' failure on line 34 of file src/pk/rsa/rsa_make_key.c
Aborted
Here is my sample rsa code
#include <tomcrypt.h>
#include <stdio.h>
int main(void) {
# ifdef USE_LTM
ltc_mp = ltm_desc;
# elif defined (USE_TFM)
ltc_mp = tfm_desc;
# endif
rsa_key key;
int err;
register_prng(&sprng_desc);
if ((err = rsa_make_key(NULL, find_prng("sprng"), 1024/8, 65537,&key)) != CRYPT_OK) {
printf("make_key error: %s\n", error_to_string(err));
return -1;
}
/* use the key ... */
return 0;
}
Here is my sample dsa code
#include <tomcrypt.h>
#include <stdio.h>
int main(void) {
# ifdef USE_LTM
ltc_mp = ltm_desc;
# elif defined (USE_TFM)
ltc_mp = tfm_desc;
# endif
int err;
register_prng(&sprng_desc);
dsa_key key;
if ((err = dsa_make_key(NULL, find_prng("sprng"), 20, 128,&key)) != CRYPT_OK) {
printf("make_key error: %s\n", error_to_string(err));
return -1;
}
/* use the key ... */
return 0;
}
Here is how I have compiled it successfully,
gcc dsa_make_key_example.c -o dsa -ltomcrypt
When I try to run the code , I am getting following error .
./dsa
segmentation fault
EDIT 1:
I investigated further and found the reason for segmentation fault
#ifdef LTC_MPI
#include <stdarg.h>
int ltc_init_multi(void **a, ...)
{
...
...
if (mp_init(cur) != CRYPT_OK) ---> This line causes segmentation fault
Where am I making mistakes ? How to resolve this problem to run these programs successfully?
I am using linux , gcc. Any help/link will be highly appreciated. Thanks in advance.
It's been a year or so since this was asked, but I have some component of an answer, and a workaround.
The reason mp_init fails is that the "math_descriptor" is uninitialized. mp_init is a defined as
#define mp_init(a) ltc_mp.init(a)
where ltc_mp is a global struct (of type ltc_math_descriptor) that holds pointers to the math routines.
There are several implementations of the math routines available, and a user can choose which they want. For whatever reason, there does not seem to be a default math implementation chosen for certain builds of libtomcrypt. Thus, the init member of ltc_mp is null, and we get the SIGSEGV.
Here is a manual workaround:
You can make your desired ltc_math_descriptor struct available to your main() routine by #defineing one of
LTM_DESC -- built-in math lib
TFM_DESC -- an external fast math package
GMP_DESC -- presumably a GNU MultiPrecision implementation?
Before #include <tomcrypt.h> (or by using -D on the command-line).
Whichever you choose, a corresponding object will be declared:
extern const ltc_math_descriptor ltm_desc;
extern const ltc_math_descriptor tfm_desc;
extern const ltc_math_descriptor gmp_desc;
To use it, manually copy it to the global math descriptor:
E.g., in my case, for the local math imlpementation,
ltc_mp = ltm_desc;
Now libtomcrypt works.
I'm new to Protocol Buffers(PB). Now i need to communicate with 2 third-party service using PB.
But it fails to work with this compiling error:
cxs_service.pb.h: ISO C++ forbids declaration of TSResponse' with no type
cxs_service.pb.h: error: invalid use of::'
My header files include 2 3rd-party .h files looking like this:
#include "mob/include/ts_service.pb.h"
#include "pc/include/cxs_service.pb.h"
//### pc/include/cxs_service.pb.h ###
// The compiler seems to find ts_service.pb.h under pc/include successfully
// but it cannot recognize ::pc::TSResponse which is defined in it
# include "ts_service.pb.h"
namespace pc {
class CXSRequest : public ::google::protobuf::Message {
inline const ::pc::TSResponse& ts_response() const;
} // class CXSRequest
} // namespace pc
// i've found that mob/include/ts_service.pb.h, pc/include/ts_service.pb.h have the same header guard.
// Thus pc/include/cxs_service.pb.h really found pc/include/ts_service.pb.h.
// but cannot include it's content because of exactly the same header guard.
#ifndef PROTOBUF_ts_5fservice_2eproto__INCLUDED
#define PROTOBUF_ts_5fservice_2eproto__INCLUDED
#endif
the first 3rd-party PB message:
// ts_service.proto
package mob;
message TSResponse {
required uint64 id = 1;
}
the second 3rd-party PB message:
// cxs_service.proto
package pc;
import ts_service.proto;
message CXSRequest {
optional TSResponse ts_response = 1;
}
// which depends on its own ts_service.proto:
// ts_service.proto
package pc;
message TSResponse {
optional string name = 1;
}
It sounds like the problem is that there are two different ts_service.proto files with conflicting definitions. Normally you would solve this by putting each package's protos in a different directory, e.g. pc/ts_service.proto and mob/ts_service.proto.
Note that when using protoc to compile these files, you will want to set up the import path to point at the parent of these two directories; do not add each directory to the path directly as this will lead to the same conflict. That is:
# BAD
protoc -Isrc/pc -Isrc/mob src/pc/cxs_service.proto
# GOOD
protoc -Isrc src/pc/cxs_service.proto
Note that the import statements in each .proto will have to be updated to give the full path of the file being imported, i.e. import "/pc/ts_service.proto"; instead of import "ts_service.proto";.