mongo_sink.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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. {
  28. try
  29. {
  30. client_ = spdlog::details::make_unique<mongocxx::client>(mongocxx::uri{uri});
  31. db_name_ = db_name;
  32. coll_name_ = collection_name;
  33. }
  34. catch (const std::exception)
  35. {
  36. throw spdlog_ex("Error opening database");
  37. }
  38. }
  39. ~mongo_sink()
  40. {
  41. flush_();
  42. }
  43. protected:
  44. void sink_it_(const details::log_msg &msg) override
  45. {
  46. using bsoncxx::builder::stream::document;
  47. using bsoncxx::builder::stream::finalize;
  48. if (client_ != nullptr)
  49. {
  50. auto doc = document{} << "timestamp" << bsoncxx::types::b_date(msg.time) << "level" << level::to_string_view(msg.level).data()
  51. << "message" << std::string(msg.payload.begin(), msg.payload.end()) << "logger_name"
  52. << std::string(msg.logger_name.begin(), msg.logger_name.end()) << "thread_id"
  53. << static_cast<int>(msg.thread_id) << finalize;
  54. client_->database(db_name_).collection(coll_name_).insert_one(doc.view());
  55. }
  56. }
  57. void flush_() override {}
  58. private:
  59. static mongocxx::instance instance_;
  60. std::string db_name_;
  61. std::string coll_name_;
  62. std::unique_ptr<mongocxx::client> client_ = nullptr;
  63. };
  64. template<>
  65. mongocxx::instance mongo_sink<std::mutex>::instance_{};
  66. #include "spdlog/details/null_mutex.h"
  67. #include <mutex>
  68. using mongo_sink_mt = mongo_sink<std::mutex>;
  69. using mongo_sink_st = mongo_sink<spdlog::details::null_mutex>;
  70. } // namespace sinks
  71. template<typename Factory = spdlog::synchronous_factory>
  72. inline std::shared_ptr<logger> mongo_logger_mt(const std::string &logger_name, const std::string &db_name,
  73. const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
  74. {
  75. return Factory::template create<sinks::mongo_sink_mt>(logger_name, db_name, collection_name, uri);
  76. }
  77. template<typename Factory = spdlog::synchronous_factory>
  78. inline std::shared_ptr<logger> mongo_logger_st(const std::string &logger_name, const std::string &db_name,
  79. const std::string &collection_name, const std::string &uri = "mongodb://localhost:27017")
  80. {
  81. return Factory::template create<sinks::mongo_sink_st>(logger_name, db_name, collection_name, uri);
  82. }
  83. } // namespace spdlog