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