event_logger.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #pragma once
  6. #include <memory>
  7. #include <sstream>
  8. #include <string>
  9. #include <chrono>
  10. #include "logging/log_buffer.h"
  11. #include "rocksdb/env.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. class JSONWriter {
  14. public:
  15. JSONWriter() : state_(kExpectKey), first_element_(true), in_array_(false) {
  16. stream_ << "{";
  17. }
  18. void AddKey(const std::string& key) {
  19. assert(state_ == kExpectKey);
  20. if (!first_element_) {
  21. stream_ << ", ";
  22. }
  23. stream_ << "\"" << key << "\": ";
  24. state_ = kExpectValue;
  25. first_element_ = false;
  26. }
  27. void AddValue(const char* value) {
  28. assert(state_ == kExpectValue || state_ == kInArray);
  29. if (state_ == kInArray && !first_element_) {
  30. stream_ << ", ";
  31. }
  32. stream_ << "\"" << value << "\"";
  33. if (state_ != kInArray) {
  34. state_ = kExpectKey;
  35. }
  36. first_element_ = false;
  37. }
  38. template <typename T>
  39. void AddValue(const T& value) {
  40. assert(state_ == kExpectValue || state_ == kInArray);
  41. if (state_ == kInArray && !first_element_) {
  42. stream_ << ", ";
  43. }
  44. stream_ << value;
  45. if (state_ != kInArray) {
  46. state_ = kExpectKey;
  47. }
  48. first_element_ = false;
  49. }
  50. void StartArray() {
  51. assert(state_ == kExpectValue);
  52. state_ = kInArray;
  53. in_array_ = true;
  54. stream_ << "[";
  55. first_element_ = true;
  56. }
  57. void EndArray() {
  58. assert(state_ == kInArray);
  59. state_ = kExpectKey;
  60. in_array_ = false;
  61. stream_ << "]";
  62. first_element_ = false;
  63. }
  64. void StartObject() {
  65. assert(state_ == kExpectValue);
  66. state_ = kExpectKey;
  67. stream_ << "{";
  68. first_element_ = true;
  69. }
  70. void EndObject() {
  71. assert(state_ == kExpectKey);
  72. stream_ << "}";
  73. first_element_ = false;
  74. }
  75. void StartArrayedObject() {
  76. assert(state_ == kInArray && in_array_);
  77. state_ = kExpectValue;
  78. if (!first_element_) {
  79. stream_ << ", ";
  80. }
  81. StartObject();
  82. }
  83. void EndArrayedObject() {
  84. assert(in_array_);
  85. EndObject();
  86. state_ = kInArray;
  87. }
  88. std::string Get() const { return stream_.str(); }
  89. JSONWriter& operator<<(const char* val) {
  90. if (state_ == kExpectKey) {
  91. AddKey(val);
  92. } else {
  93. AddValue(val);
  94. }
  95. return *this;
  96. }
  97. JSONWriter& operator<<(const std::string& val) {
  98. return *this << val.c_str();
  99. }
  100. template <typename T>
  101. JSONWriter& operator<<(const T& val) {
  102. assert(state_ != kExpectKey);
  103. AddValue(val);
  104. return *this;
  105. }
  106. private:
  107. enum JSONWriterState {
  108. kExpectKey,
  109. kExpectValue,
  110. kInArray,
  111. kInArrayedObject,
  112. };
  113. JSONWriterState state_;
  114. bool first_element_;
  115. bool in_array_;
  116. std::ostringstream stream_;
  117. };
  118. class EventLoggerStream {
  119. public:
  120. template <typename T>
  121. EventLoggerStream& operator<<(const T& val) {
  122. MakeStream();
  123. *json_writer_ << val;
  124. return *this;
  125. }
  126. void StartArray() { json_writer_->StartArray(); }
  127. void EndArray() { json_writer_->EndArray(); }
  128. void StartObject() { json_writer_->StartObject(); }
  129. void EndObject() { json_writer_->EndObject(); }
  130. ~EventLoggerStream();
  131. private:
  132. void MakeStream() {
  133. if (!json_writer_) {
  134. json_writer_ = new JSONWriter();
  135. *this << "time_micros"
  136. << std::chrono::duration_cast<std::chrono::microseconds>(
  137. std::chrono::system_clock::now().time_since_epoch()).count();
  138. }
  139. }
  140. friend class EventLogger;
  141. explicit EventLoggerStream(Logger* logger);
  142. explicit EventLoggerStream(LogBuffer* log_buffer, const size_t max_log_size);
  143. // exactly one is non-nullptr
  144. Logger* const logger_;
  145. LogBuffer* const log_buffer_;
  146. const size_t max_log_size_; // used only for log_buffer_
  147. // ownership
  148. JSONWriter* json_writer_;
  149. };
  150. // here is an example of the output that will show up in the LOG:
  151. // 2015/01/15-14:13:25.788019 1105ef000 EVENT_LOG_v1 {"time_micros":
  152. // 1421360005788015, "event": "table_file_creation", "file_number": 12,
  153. // "file_size": 1909699}
  154. class EventLogger {
  155. public:
  156. static const char* Prefix() {
  157. return "EVENT_LOG_v1";
  158. }
  159. explicit EventLogger(Logger* logger) : logger_(logger) {}
  160. EventLoggerStream Log() { return EventLoggerStream(logger_); }
  161. EventLoggerStream LogToBuffer(LogBuffer* log_buffer) {
  162. return EventLoggerStream(log_buffer, LogBuffer::kDefaultMaxLogSize);
  163. }
  164. EventLoggerStream LogToBuffer(LogBuffer* log_buffer,
  165. const size_t max_log_size) {
  166. return EventLoggerStream(log_buffer, max_log_size);
  167. }
  168. void Log(const JSONWriter& jwriter);
  169. static void Log(Logger* logger, const JSONWriter& jwriter);
  170. static void LogToBuffer(
  171. LogBuffer* log_buffer, const JSONWriter& jwriter,
  172. const size_t max_log_size = LogBuffer::kDefaultMaxLogSize);
  173. private:
  174. Logger* logger_;
  175. };
  176. } // namespace ROCKSDB_NAMESPACE