event_logger.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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 <chrono>
  7. #include <memory>
  8. #include <sstream>
  9. #include <string>
  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())
  138. .count();
  139. }
  140. }
  141. friend class EventLogger;
  142. explicit EventLoggerStream(Logger* logger);
  143. explicit EventLoggerStream(LogBuffer* log_buffer, const size_t max_log_size);
  144. // exactly one is non-nullptr
  145. Logger* const logger_;
  146. LogBuffer* const log_buffer_;
  147. const size_t max_log_size_; // used only for log_buffer_
  148. // ownership
  149. JSONWriter* json_writer_;
  150. };
  151. // here is an example of the output that will show up in the LOG:
  152. // 2015/01/15-14:13:25.788019 1105ef000 EVENT_LOG_v1 {"time_micros":
  153. // 1421360005788015, "event": "table_file_creation", "file_number": 12,
  154. // "file_size": 1909699}
  155. class EventLogger {
  156. public:
  157. static const char* Prefix() { return "EVENT_LOG_v1"; }
  158. explicit EventLogger(Logger* logger) : logger_(logger) {}
  159. EventLoggerStream Log() { return EventLoggerStream(logger_); }
  160. EventLoggerStream LogToBuffer(LogBuffer* log_buffer) {
  161. return EventLoggerStream(log_buffer, LogBuffer::kDefaultMaxLogSize);
  162. }
  163. EventLoggerStream LogToBuffer(LogBuffer* log_buffer,
  164. const size_t max_log_size) {
  165. return EventLoggerStream(log_buffer, max_log_size);
  166. }
  167. void Log(const JSONWriter& jwriter);
  168. static void Log(Logger* logger, const JSONWriter& jwriter);
  169. static void LogToBuffer(
  170. LogBuffer* log_buffer, const JSONWriter& jwriter,
  171. const size_t max_log_size = LogBuffer::kDefaultMaxLogSize);
  172. private:
  173. Logger* logger_;
  174. };
  175. } // namespace ROCKSDB_NAMESPACE