mongo_sink.h 3.9 KB

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