mirror of
https://github.com/gabime/spdlog.git
synced 2026-04-10 11:34:29 +08:00
There can only be one instance in the whole program, so programs that use the Mongo sink and also separately use MongoCXX may have problems if the Mongo sink owns the instance. MongoCXX recommends that the main application manage its own instance so configuration parameters can be passed to the constructor: http://mongocxx.org/api/current/classmongocxx_1_1instance.html However, this commit is not a breaking change. If no instance has been created at construction time, the Mongo sink will still create and own the instance.
115 lines
3.8 KiB
C++
115 lines
3.8 KiB
C++
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
|
|
|
#pragma once
|
|
|
|
//
|
|
// Custom sink for mongodb
|
|
// Building and using requires mongocxx library.
|
|
// For building mongocxx library check the url below
|
|
// http://mongocxx.org/mongocxx-v3/installation/
|
|
//
|
|
|
|
#include "spdlog/common.h"
|
|
#include "spdlog/details/log_msg.h"
|
|
#include "spdlog/sinks/base_sink.h"
|
|
#include <spdlog/details/synchronous_factory.h>
|
|
|
|
#include <bsoncxx/builder/stream/document.hpp>
|
|
#include <bsoncxx/types.hpp>
|
|
#include <bsoncxx/view_or_value.hpp>
|
|
|
|
#include <mongocxx/client.hpp>
|
|
#include <mongocxx/exception/logic_error.hpp>
|
|
#include <mongocxx/instance.hpp>
|
|
#include <mongocxx/uri.hpp>
|
|
|
|
namespace spdlog {
|
|
namespace sinks {
|
|
template<typename Mutex>
|
|
class mongo_sink : public base_sink<Mutex>
|
|
{
|
|
public:
|
|
mongo_sink(const std::string &db_name, const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017",
|
|
bool create_instance = true)
|
|
{
|
|
try
|
|
{
|
|
if (create_instance && !instance_)
|
|
{
|
|
try
|
|
{
|
|
instance_ = std::make_shared<mongocxx::instance>();
|
|
}
|
|
catch (const mongocxx::logic_error&)
|
|
{
|
|
// A MongoCXX instance already exists, so this object doesn't need to own it
|
|
instance_ = nullptr;
|
|
}
|
|
}
|
|
client_ = spdlog::details::make_unique<mongocxx::client>(mongocxx::uri{uri});
|
|
db_name_ = db_name;
|
|
coll_name_ = collection_name;
|
|
}
|
|
catch (const std::exception&)
|
|
{
|
|
throw spdlog_ex("Error opening database");
|
|
}
|
|
}
|
|
|
|
~mongo_sink()
|
|
{
|
|
flush_();
|
|
}
|
|
|
|
protected:
|
|
void sink_it_(const details::log_msg &msg) override
|
|
{
|
|
using bsoncxx::builder::stream::document;
|
|
using bsoncxx::builder::stream::finalize;
|
|
|
|
if (client_ != nullptr)
|
|
{
|
|
auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time)
|
|
<< "level" << level::to_string_view(msg.level).data() << "level_num" << msg.level
|
|
<< "message" << std::string(msg.payload.begin(), msg.payload.end()) << "logger_name"
|
|
<< std::string(msg.logger_name.begin(), msg.logger_name.end()) << "thread_id"
|
|
<< static_cast<int>(msg.thread_id) << finalize;
|
|
client_->database(db_name_).collection(coll_name_).insert_one(doc.view());
|
|
}
|
|
}
|
|
|
|
void flush_() override {}
|
|
|
|
private:
|
|
static std::shared_ptr<mongocxx::instance> instance_;
|
|
std::string db_name_;
|
|
std::string coll_name_;
|
|
std::unique_ptr<mongocxx::client> client_ = nullptr;
|
|
};
|
|
template<>
|
|
std::shared_ptr<mongocxx::instance> mongo_sink<std::mutex>::instance_{};
|
|
|
|
#include "spdlog/details/null_mutex.h"
|
|
#include <mutex>
|
|
using mongo_sink_mt = mongo_sink<std::mutex>;
|
|
using mongo_sink_st = mongo_sink<spdlog::details::null_mutex>;
|
|
|
|
} // namespace sinks
|
|
|
|
template<typename Factory = spdlog::synchronous_factory>
|
|
inline std::shared_ptr<logger> mongo_logger_mt(const std::string &logger_name, const std::string &db_name,
|
|
const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
|
|
{
|
|
return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri);
|
|
}
|
|
|
|
template<typename Factory = spdlog::synchronous_factory>
|
|
inline std::shared_ptr<logger> mongo_logger_st(const std::string &logger_name, const std::string &db_name,
|
|
const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
|
|
{
|
|
return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name, uri);
|
|
}
|
|
|
|
} // namespace spdlog
|