Boost log select destination file - c++

Is it possible with one instance of Boost log, to log into severeal files.
I mean is it possible to specify in which file the log will be written:
BOOST_LOG_..(...) << "aaa" <- go to **A.log**
BOOST_LOG_..(...) << "bbb" <- go to **B.log**

Yes, it's possible - using filters.
How you do it exactly depends on your preferences, but here's an example with scoped logger tags:
void SomeFunction()
{
{
// everything in this scope gets logged to A.log
BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Log", std::string, "LogA")
BOOST_LOG(lg) << "aaa";
BOOST_LOG(lg) << "aaa2";
}
{
// everything in this scope gets logged to B.log
BOOST_LOG_SCOPED_LOGGER_TAG(lg, "Log", std::string, "LogB")
BOOST_LOG(lg) << "bbb";
BOOST_LOG(lg) << "bbb2";
}
}
// This is your log initialization routine
void InitLogs()
{
// Initialize sinkA to use a file backend that writes to A.log and sinkB to B.log.
// ...
// ...
// Make sink A only accept records with the Log attribute "LogA"
// while sink B will only accept records where it is "LogB".
sinkA.set_filter(flt::attr<std::string>("Log") == "LogA");
sinkB.set_filter(flt::attr<std::string>("Log") == "LogB");
}

Related

How to access AWS "subfolders" using ListObjects() in C++ SDK?

I am trying to list the objects in the "noaa-goes16/GLM-L2-LCFA/2021/140/05" bucket. The AWS C++ SDK says that in order to list the objects, you need to use the following function:
bool ListObjects(const Aws::String& bucketName,
const Aws::Client::ClientConfiguration& clientConfig) {
Aws::S3::S3Client s3_client(clientConfig);
Aws::S3::Model::ListObjectsRequest request;
request.WithBucket(bucketName);
auto outcome = s3_client.ListObjects(request);
if (!outcome.IsSuccess()) {
std::cerr << "Error: ListObjects: " <<
outcome.GetError().GetMessage() << std::endl;
}
else {
Aws::Vector<Aws::S3::Model::Object> objects =
outcome.GetResult().GetContents();
for (Aws::S3::Model::Object& object : objects) {
std::cout << object.GetKey() << std::endl;
}
}
return outcome.IsSuccess();
}
After passing the string to the function, I get the following error:
Aws::SDKOptions options;
Aws::InitAPI(options);
Aws::Client::ClientConfiguration clientConfig;
std::string object = "noaa-goes16/GLM-L2-LCFA/2021/140/05";
ListObject(object, clientConfig);
Output:
Error: ListObjects: The specified key does not exist.
noaa-goes16/GLM-L2-LCFA/2021/140/05
I have tried to add a "/" to the bucket name, and it states again that it does not exist.
If I just try "noaa-goes16" as the bucket name, it lists 1000 files that are not relevant to my application. How do I list the files in the "/05" subfolder using the AWS C++ SDK?
I tried to list the files in a subfolder of the noaa-goes16 bucket using the ListObjects() function in the AWS C++ SDK. I recieved an error that the subfolder I asked for does not exist. However, I know that the subfolder I am asking for does exist. I have tried to add a "/" to the end of the bucket, thinking this would resolve the error. This did not help. I have found that if I only put the main bucket object as the name ("noaa-goes16"), it works. However, I cannot list objects in a specific subfolder and would like to know how.
All! I have just figured it out! Hopefully, this thread helps others.
In order to get the subfolder, you need to use a method on the request object.
For example, in order to list all of the objects in the "GLM-L2-LCFA/2021/140/05" subfolder, add the Aws::String &prefix:
bool ListObjects(const Aws::String& bucketName, const Aws::String &prefix,
const Aws::Client::ClientConfiguration& clientConfig) {
Aws::S3::S3Client s3_client(clientConfig);
Aws::S3::Model::ListObjectsRequest request;
request.WithBucket(bucketName).WithPrefix(prefix);
auto outcome = s3_client.ListObjects(request);
if (!outcome.IsSuccess()) {
std::cerr << "Error: ListObjects: " <<
outcome.GetError().GetMessage() << std::endl;
}
else {
Aws::Vector<Aws::S3::Model::Object> objects =
outcome.GetResult().GetContents();
for (Aws::S3::Model::Object& object : objects) {
std::cout << object.GetKey() << std::endl;
}
}
return outcome.IsSuccess();
Now, pass the following:
Aws::Client::ClientConfiguration clientConfig;
std::string bucket = "noaa-goes16";
std::string prefix = "GLM-L2-LCFA/2021/140/05";
ListObjects(bucket, prefix, clientConfig);
Viola!

V8 Cannot set ObjectTemplate with name "console"

I try to set a global object named console, but that specific name causes a crash and to me it seems like it's telling me that the object already exists. I can though set it to anything else. Why can I not set the object to name "console"?
V8 Version is 6.5.254.6
Error
# Fatal error in ../../src/objects.cc, line 6007
# Debug check failed: !it.IsFound().
Code Snippet
isolate->Enter();
v8::HandleScope handle_scope(isolate);
// Create globals
auto globalObj = v8::ObjectTemplate::New(isolate);
// Create console object
auto consoleObj = v8::ObjectTemplate::New(isolate);
// Log
auto logcb = [](V8CallbackArgs args) {
auto& log = Log::Instance();
for (size_t i = 1; i < args.Length(); i++)
log << *v8::String::Utf8Value(args[i]);
log << std::endl;
};
consoleObj->Set(v8::String::NewFromUtf8(isolate, "log"), v8::FunctionTemplate::New(isolate, logcb));
// Set global object
globalObj->Set(v8::String::NewFromUtf8(isolate, "console"), consoleObj); // nonono cannot have it console, con is ok though
// Create script context
context = v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>>(isolate, v8::Context::New(isolate, nullptr, globalObj));
{
v8::Context::Scope context_scope(context.Get(isolate));
v8::TryCatch tc(isolate);
auto source = v8::String::NewFromUtf8(src.c_str());
auto script = v8::Script::Compile(source);
if (script->Run().IsEmpty() && CV8ScriptRuntime::isDebug) {
v8loge "Error loading script \"" << filepath << "\n" << std::endl
<< "Exception: " << *v8::String::Utf8Value(tc.Exception()) << std::endl
<< "Stack trace: " << *v8::String::Utf8Value(tc.StackTrace()) << std::endl << Log::White;
}
}
Your observation is correct. When V8 initializes a Context, it installs a global console object into it, and assumes (guarded by a check) that a property with that name does not exist yet. When you provide your own "console", that check fails.
If you want to overwrite V8's built-in console, you'll have to create the Context first (via v8::Context::New), then delete (or overwrite) the console property on its global object.
If all you wanted was to have a console object in your embedder just like the one you know from browsers, then I'm happy to inform you that this work has already been done and you can simply use it :-)

Can you change a bsoncxx object (document/value/element)?

I'm using the mongocxx driver and I am considering keeping the query results given in BSON as a data holder in a couple of objects instead of parsing the BSON to retrieve the values and then discard it.
This would make some sense "if" I can edit the BSON on the fly. I couldn't find anything in the bsoncxx driver documentation besides the builder that would allow me to manipulate a bsoncxx document/value/view/element after it's been constructed.
As an example, imagine that I have something like this
fruit["orange"];
where fruit is a bsoncxx::document::element
I can get the value by using one of the .get_xxx operators.
What I can't find is something like
fruit["orange"] = "ripe";
Is there a way of doing this, or the idea behind the builder is "just" to create a query to give to the database?
There was a question with same theme, see here
So, bsoncxx objects seem to be immutable, and we have to re-create them if we need to edit them.. :(
I've written a really bad solution which re-creates document from scratch
But this is a solution, I guess.
std::string bsoncxx_string_viewToString(core::v1::string_view gotStringView) {
std::stringstream convertingStream;
convertingStream << gotStringView;
return std::move(convertingStream.str());
}
std::string b_utf8ToString(bsoncxx::types::b_utf8 gotB_utf8) {
return std::move(bsoncxx_string_viewToString(core::v1::string_view(gotB_utf8)));
}
template <typename T>
bsoncxx::document::value editBsoncxx(bsoncxx::document::view documentToEdit, std::string keyToEdit, T newValue, bool appendValueIfKeyNotExist = true) {
auto doc = bsoncxx::builder::stream::document{};
std::string currentKey;
for (auto i : documentToEdit) {
currentKey = bsoncxx_string_viewToString(i.key());
if (currentKey == keyToEdit) {
doc << keyToEdit << newValue;
appendValueIfKeyNotExist = false;
} else {
doc << currentKey << i.get_value();
}
}
if (appendValueIfKeyNotExist) // Maybe this would be better with documentToEdit.find(key), but I don't know how to check if iterator is past-the-end
//If there is a way to check if bsoncxx contains key, we can achieve ~o(log(n)) [depending on 'find key' implementation] which is better than o(n)
doc << keyToEdit << newValue;
return doc.extract();
}
Usage:
auto doc = document{} << "foo0" << "bar0" << "foo1" << 1 << "foo2" << 314 << finalize;
std::cout << bsoncxx::to_json(doc) << std::endl << std::endl;
doc = editBsoncxx<std::string> (doc.view(), "foo1", "edited"); //replace "foo1" with string "edited"
doc = editBsoncxx<int>(doc.view(), "baz_noappend", 123, false); //do nothing if key "baz_noappend" is not found. <- if key-existance algorythm will be applied, we'd spend about o(lob(n)) here, not o(n)
doc = editBsoncxx<int>(doc.view(), "baz_append", 123, true); //key will not be found => it'll be appended which is default behaviour
std::cout << bsoncxx::to_json(doc) << std::endl;
Result:
{
"foo0" : "bar0",
"foo1" : 1,
"foo2" : 314
}
{
"foo0" : "bar0",
"foo1" : "edited",
"foo2" : 314,
"baz_append" : 123
}
So, in your case you can use
fruit = editBsoncxx<std::string>(fruit.view(), "orange", "ripe");
But, again, see already-mentioned related question you're right when saying that
the idea behind the builder is "just" to create a query to give to the database?
I think, the solution will be "do not edit documents".
also you can write something like type-converter from bsoncxx to other json storing fomat (for example, rapidjson)
Beware of {value:"valid_json"}: bsoncxx::to_json does not add backslashes to quote signs in values => injection can be made.

Why Isn't find_one working in MongoDB C++?

I have a MongoDB 3.0.7 database, created with the mongo shell. The following works fine:
% mongo test
> vs = db.myCollection.findOne({"somefield.subfield": "somevalue"})
but when I do this in C++:
mongocxx::instance inst{};
mongocxx::client conn{};
auto db = conn["test"];
bsoncxx::stdx::optional< bsoncxx::document::value> docObj;
try {
docObj =
db["myCollection"]
.find_one(document{} <<
"somefield.subfield" << "someValue" <<
bsoncxx::builder::stream::finalize);
} catch (mongocxx::exception::operation e) {
std::cerr << "Retrieval failed (and exception thrown)";
}
if (docObj == bsoncxx::stdx::nullopt)
std::cerr << "Failed to find object";
I get "Failed to find object". What am I missing here?
Update: 11/23/2015, 10:00
I've installed the latest cxx driver (0.3.0), and made the following changes:
mongocxx::instance inst{};
mongocxx::client *connPtr;
bsoncxx::stdx::string_view connectionString("mongodb://localhost");
connPtr = new mongocxx::client(mongocxx::uri(connectionString));
auto db = connPtr->database("test");;
bsoncxx::stdx::optional< bsoncxx::document::value> docObj;
try {
docObj =
db["myCollection"]
.find_one(document{} <<
"somefield.subfield" << "someValue" <<
bsoncxx::builder::stream::finalize);
} catch (mongocxx::exception::operation e) {
std::cerr << "Retrieval failed (and exception thrown)";
}
if (docObj == bsoncxx::stdx::nullopt)
std::cerr << "Failed to find object";
I'm back to exactly the same thing. Calling db.list_collections(document{}) retrieves no results.
The bsoncxx library has two document types, views and values. A document::value contains the actual document data, and a document::view is just a reference to some underlying value. Values must outlive the views that use them.
There's a bug in the new c++11 driver with how document::values are passed around. This code produces a document::value :
document{} << "someField" << "someValue" << finalize;
The collection.find_one() method takes a document::view, and document::values convert implicitly to document::views. Unfortunately, this means if you dynamically build a document in your call to find_one(), as above, you can shoot yourself in the foot:
collection.find_one(document{} << "someField" << "someValue" << finalize);
finalize makes a temporary document::value, then find_one converts that to a document::view. The temporary value is dropped on the floor, leaving your view value-less, like a dangling pointer.
A workaround is to make your value in a separate call, and keep it around:
document::value doc = document{} << "someField" << "someValue" << finalize;
collection.find_one(doc.view());
I suspect this is what's causing your queries to fail; if not, it's something to make your code resilient to nonetheless!
You can track this ticket for the real fix for this problem.

NetworkManager and Qt Problem

I am still new to using Qt4/Dbus, and i am trying to get a list of acccess points with Qt API to send/receive Dbus messeges.
I got the following error:
org.freedesktop.DBus.Error.UnknownMethod
Method "GetAccessPoint" with signature "" on interface "org.freedesktop.NetworkManager.Device.Wireless" doesn't exist
The code is:
QStringList *netList = new QStringList();
QDBusConnection sysbus = QDBusConnection::systemBus();
QDBusInterface callNM("org.freedesktop.NetworkManager","/org/freedesktop/NetworkManager","org.freedesktop.NetworkManager.Device.Wireless",sysbus);
if(callNM.isValid())
{
QDBusMessage query= callNM.call("GetAccessPoints");
if(query.type() == QDBusMessage::ReplyMessage)
{
QDBusArgument arg = query.arguments().at(0).value<QDBusArgument>();
arg.beginArray();
while(!arg.atEnd())
{
QString element = qdbus_cast<QString>(arg);
netList->append(element);
}
arg.endArray();
}else{
std::cout<< query.errorName().toStdString() << std::endl;
std::cout<< query.errorMessage().toStdString() << std::endl;
}
int x= netList->size();
for(int y=0; y< x ;y++)
{
widget.avail_nets->addItem(netList->at(y)); // just print it to my gui from the stringlist array
}
}else{
std::cout<<"fail" << std::endl;
}
Whats wrong?My naming was correct and I am following the exact specs from here
The method name is GetAccessPoints.
While your error is:
org.freedesktop.DBus.Error.UnknownMethod
Method "GetAccessPoint" with signature
"" on interface
"org.freedesktop.NetworkManager.Device.Wireless"
doesn't exist
Highlight on "GetAccessPoint". Thus you might have misspelled the method name in the code, although the code you pasted here uses the correct method name, maybe you fixed it and forgot to rebuild or clean the project?
I had the same issue, but then I noticed that it only happened when I called the GetAccessPoints method on a wired device. Make sure the device is a wireless device (i.e. DeviceType equals NM_DEVICE_TYPE_WIFI), and everything should work fine.
i modify this and works for me
QDBusInterface callNM("org.freedesktop.NetworkManager","/org/freedesktop/NetworkManager/Devices/0","org.freedesktop.NetworkManager.Device.Wireless",sysbus);
and the result is
"/org/freedesktop/NetworkManager/AccessPoint/2"
"/org/freedesktop/NetworkManager/AccessPoint/1"
i think /org/freedesktop/NetworkManager is not correct path for specific device (wireless devices).
QDBusInterface dbus_iface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Devices/0", "org.freedesktop.NetworkManager.Device.Wireless", bus);
QDBusMessage query = dbus_iface.call("GetAccessPoints");
if(query.type() == QDBusMessage::ReplyMessage) {
QDBusArgument arg = query.arguments().at(0).value<QDBusArgument>();
arg.beginArray();
while(!arg.atEnd()) {
QString element = qdbus_cast<QString>(arg);
netList->append(element);
showAccessPointProperties(element);
}
arg.endArray();
} else {
qDebug() << "got dbus error: " << query.errorName();
qDebug() << "check the parameters like service, path, interface and method name !!!";
}
Hope this will help.