74c755c552
Summary: Added a new flag --json to the ldb manifest_dump command that prints out the version edits as JSON objects for easier reading and parsing of information. Test Plan: **Sample usage: ** ``` ./ldb manifest_dump --json --path=path/to/manifest/file ``` **Sample output:** ``` {"EditNumber": 0, "Comparator": "leveldb.BytewiseComparator", "ColumnFamily": 0} {"EditNumber": 1, "LogNumber": 0, "ColumnFamily": 0} {"EditNumber": 2, "LogNumber": 4, "PrevLogNumber": 0, "NextFileNumber": 7, "LastSeq": 35356, "AddedFiles": [{"Level": 0, "FileNumber": 5, "FileSize": 1949284, "SmallestIKey": "'", "LargestIKey": "'"}], "ColumnFamily": 0} ... {"EditNumber": 13, "PrevLogNumber": 0, "NextFileNumber": 36, "LastSeq": 290994, "DeletedFiles": [{"Level": 0, "FileNumber": 17}, {"Level": 0, "FileNumber": 20}, {"Level": 0, "FileNumber": 22}, {"Level": 0, "FileNumber": 24}, {"Level": 1, "FileNumber": 13}, {"Level": 1, "FileNumber": 14}, {"Level": 1, "FileNumber": 15}, {"Level": 1, "FileNumber": 18}], "AddedFiles": [{"Level": 1, "FileNumber": 25, "FileSize": 2114340, "SmallestIKey": "'", "LargestIKey": "'"}, {"Level": 1, "FileNumber": 26, "FileSize": 2115213, "SmallestIKey": "'", "LargestIKey": "'"}, {"Level": 1, "FileNumber": 27, "FileSize": 2114807, "SmallestIKey": "'", "LargestIKey": "'"}, {"Level": 1, "FileNumber": 30, "FileSize": 2115271, "SmallestIKey": "'", "LargestIKey": "'"}, {"Level": 1, "FileNumber": 31, "FileSize": 2115165, "SmallestIKey": "'", "LargestIKey": "'"}, {"Level": 1, "FileNumber": 32, "FileSize": 2114683, "SmallestIKey": "'", "LargestIKey": "'"}, {"Level": 1, "FileNumber": 35, "FileSize": 1757512, "SmallestIKey": "'", "LargestIKey": "'"}], "ColumnFamily": 0} ... ``` Reviewers: sdong, anthony, yhchiang, igor Reviewed By: igor Subscribers: dhruba Differential Revision: https://reviews.facebook.net/D41727
197 lines
4.5 KiB
C++
197 lines
4.5 KiB
C++
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
|
// This source code is licensed under the BSD-style license found in the
|
|
// LICENSE file in the root directory of this source tree. An additional grant
|
|
// of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <chrono>
|
|
|
|
#include "rocksdb/env.h"
|
|
#include "util/log_buffer.h"
|
|
|
|
namespace rocksdb {
|
|
|
|
class JSONWriter {
|
|
public:
|
|
JSONWriter() : state_(kExpectKey), first_element_(true), in_array_(false) {
|
|
stream_ << "{";
|
|
}
|
|
|
|
void AddKey(const std::string& key) {
|
|
assert(state_ == kExpectKey);
|
|
if (!first_element_) {
|
|
stream_ << ", ";
|
|
}
|
|
stream_ << "\"" << key << "\": ";
|
|
state_ = kExpectValue;
|
|
first_element_ = false;
|
|
}
|
|
|
|
void AddValue(const char* value) {
|
|
assert(state_ == kExpectValue || state_ == kInArray);
|
|
if (state_ == kInArray && !first_element_) {
|
|
stream_ << ", ";
|
|
}
|
|
stream_ << "\"" << value << "\"";
|
|
if (state_ != kInArray) {
|
|
state_ = kExpectKey;
|
|
}
|
|
first_element_ = false;
|
|
}
|
|
|
|
template <typename T>
|
|
void AddValue(const T& value) {
|
|
assert(state_ == kExpectValue || state_ == kInArray);
|
|
if (state_ == kInArray && !first_element_) {
|
|
stream_ << ", ";
|
|
}
|
|
stream_ << value;
|
|
if (state_ != kInArray) {
|
|
state_ = kExpectKey;
|
|
}
|
|
first_element_ = false;
|
|
}
|
|
|
|
void StartArray() {
|
|
assert(state_ == kExpectValue);
|
|
state_ = kInArray;
|
|
in_array_ = true;
|
|
stream_ << "[";
|
|
first_element_ = true;
|
|
}
|
|
|
|
void EndArray() {
|
|
assert(state_ == kInArray);
|
|
state_ = kExpectKey;
|
|
in_array_ = false;
|
|
stream_ << "]";
|
|
first_element_ = false;
|
|
}
|
|
|
|
void StartObject() {
|
|
assert(state_ == kExpectValue);
|
|
state_ = kExpectKey;
|
|
stream_ << "{";
|
|
first_element_ = true;
|
|
}
|
|
|
|
void EndObject() {
|
|
assert(state_ == kExpectKey);
|
|
stream_ << "}";
|
|
first_element_ = false;
|
|
}
|
|
|
|
void StartArrayedObject() {
|
|
assert(state_ == kInArray && in_array_);
|
|
state_ = kExpectValue;
|
|
if (!first_element_) {
|
|
stream_ << ", ";
|
|
}
|
|
StartObject();
|
|
}
|
|
|
|
void EndArrayedObject() {
|
|
assert(in_array_);
|
|
EndObject();
|
|
state_ = kInArray;
|
|
}
|
|
|
|
std::string Get() const { return stream_.str(); }
|
|
|
|
JSONWriter& operator<<(const char* val) {
|
|
if (state_ == kExpectKey) {
|
|
AddKey(val);
|
|
} else {
|
|
AddValue(val);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
JSONWriter& operator<<(const std::string& val) {
|
|
return *this << val.c_str();
|
|
}
|
|
|
|
template <typename T>
|
|
JSONWriter& operator<<(const T& val) {
|
|
assert(state_ != kExpectKey);
|
|
AddValue(val);
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
enum JSONWriterState {
|
|
kExpectKey,
|
|
kExpectValue,
|
|
kInArray,
|
|
kInArrayedObject,
|
|
};
|
|
JSONWriterState state_;
|
|
bool first_element_;
|
|
bool in_array_;
|
|
std::ostringstream stream_;
|
|
};
|
|
|
|
class EventLoggerStream {
|
|
public:
|
|
template <typename T>
|
|
EventLoggerStream& operator<<(const T& val) {
|
|
MakeStream();
|
|
*json_writer_ << val;
|
|
return *this;
|
|
}
|
|
|
|
void StartArray() { json_writer_->StartArray(); }
|
|
void EndArray() { json_writer_->EndArray(); }
|
|
void StartObject() { json_writer_->StartObject(); }
|
|
void EndObject() { json_writer_->EndObject(); }
|
|
|
|
~EventLoggerStream();
|
|
|
|
private:
|
|
void MakeStream() {
|
|
if (!json_writer_) {
|
|
json_writer_ = new JSONWriter();
|
|
*this << "time_micros"
|
|
<< std::chrono::duration_cast<std::chrono::microseconds>(
|
|
std::chrono::system_clock::now().time_since_epoch()).count();
|
|
}
|
|
}
|
|
friend class EventLogger;
|
|
explicit EventLoggerStream(Logger* logger);
|
|
explicit EventLoggerStream(LogBuffer* log_buffer);
|
|
// exactly one is non-nullptr
|
|
Logger* const logger_;
|
|
LogBuffer* const log_buffer_;
|
|
// ownership
|
|
JSONWriter* json_writer_;
|
|
};
|
|
|
|
// here is an example of the output that will show up in the LOG:
|
|
// 2015/01/15-14:13:25.788019 1105ef000 EVENT_LOG_v1 {"time_micros":
|
|
// 1421360005788015, "event": "table_file_creation", "file_number": 12,
|
|
// "file_size": 1909699}
|
|
class EventLogger {
|
|
public:
|
|
static const char* Prefix() {
|
|
return "EVENT_LOG_v1";
|
|
}
|
|
|
|
explicit EventLogger(Logger* logger) : logger_(logger) {}
|
|
EventLoggerStream Log() { return EventLoggerStream(logger_); }
|
|
EventLoggerStream LogToBuffer(LogBuffer* log_buffer) {
|
|
return EventLoggerStream(log_buffer);
|
|
}
|
|
void Log(const JSONWriter& jwriter);
|
|
static void Log(Logger* logger, const JSONWriter& jwriter);
|
|
static void LogToBuffer(LogBuffer* log_buffer, const JSONWriter& jwriter);
|
|
|
|
private:
|
|
Logger* logger_;
|
|
};
|
|
|
|
} // namespace rocksdb
|