mongo_sink.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
  2. // Distributed under the MIT License (http://opensource.org/licenses/MIT)
  3. #pragma once
  4. //
  5. // Custom sink for mongodb
  6. // Building and using requires mongocxx library.
  7. // For building mongocxx library check the url below
  8. // http://mongocxx.org/mongocxx-v3/installation/
  9. //
  10. #include "spdlog/common.h"
  11. #include "spdlog/details/log_msg.h"
  12. #include "spdlog/sinks/base_sink.h"
  13. #include <spdlog/details/synchronous_factory.h>
  14. #include <bsoncxx/builder/stream/document.hpp>
  15. #include <bsoncxx/types.hpp>
  16. #include <bsoncxx/view_or_value.hpp>
  17. #include <mongocxx/client.hpp>
  18. #include <mongocxx/instance.hpp>
  19. #include <mongocxx/uri.hpp>
  20. namespace spdlog {
  21. namespace sinks {
  22. template<typename Mutex>
  23. class mongo_sink : public base_sink<Mutex>
  24. {
  25. public:
  26. mongo_sink(const std::string &db_name, const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
  27. try : mongo_sink(std::make_shared<mongocxx::instance>(), db_name, collection_name, uri)
  28. {}
  29. catch (const std::exception &e)
  30. {
  31. throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what()));
  32. }
  33. mongo_sink(std::shared_ptr<mongocxx::instance> instance, const std::string &db_name, const std::string &collection_name,
  34. const std::string &uri = "mongodb://localhost:27017")
  35. : instance_(std::move(instance))
  36. , db_name_(db_name)
  37. , coll_name_(collection_name)
  38. {
  39. try
  40. {
  41. client_ = spdlog::details::make_unique<mongocxx::client>(mongocxx::uri{uri});
  42. }
  43. catch (const std::exception &e)
  44. {
  45. throw_spdlog_ex(fmt_lib::format("Error opening database: {}", e.what()));
  46. }
  47. }
  48. ~mongo_sink()
  49. {
  50. flush_();
  51. }
  52. protected:
  53. void sink_it_(const details::log_msg &msg) override
  54. {
  55. using bsoncxx::builder::stream::document;
  56. using bsoncxx::builder::stream::finalize;
  57. if (client_ != nullptr)
  58. {
  59. auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level" << level::to_string_view(msg.level).data()
  60. << "level_num" << msg.level << "message" << std::string(msg.payload.begin(), msg.payload.end())
  61. << "logger_name" << std::string(msg.logger_name.begin(), msg.logger_name.end()) << "thread_id"
  62. << static_cast<int>(msg.thread_id) << finalize;
  63. client_->database(db_name_).collection(coll_name_).insert_one(doc.view());
  64. }
  65. }
  66. void flush_() override {}
  67. private:
  68. std::shared_ptr<mongocxx::instance> instance_;
  69. std::string db_name_;
  70. std::string coll_name_;
  71. std::unique_ptr<mongocxx::client> client_ = nullptr;
  72. };
  73. #include "spdlog/details/null_mutex.h"
  74. #include <mutex>
  75. using mongo_sink_mt = mongo_sink<std::mutex>;
  76. using mongo_sink_st = mongo_sink<spdlog::details::null_mutex>;
  77. } // namespace sinks
  78. template<typename Factory = spdlog::synchronous_factory>
  79. inline std::shared_ptr<logger> mongo_logger_mt(const std::string &logger_name, const std::string &db_name,
  80. const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
  81. {
  82. return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri);
  83. }
  84. template<typename Factory = spdlog::synchronous_factory>
  85. inline std::shared_ptr<logger> mongo_logger_st(const std::string &logger_name, const std::string &db_name,
  86. const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
  87. {
  88. return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name, uri);
  89. }
  90. } // namespace spdlog