io_tracer_parser_tool.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. #ifdef GFLAGS
  6. #include "tools/io_tracer_parser_tool.h"
  7. #include <cinttypes>
  8. #include <cstdio>
  9. #include <iomanip>
  10. #include <memory>
  11. #include <sstream>
  12. #include "port/lang.h"
  13. #include "rocksdb/trace_reader_writer.h"
  14. #include "trace_replay/io_tracer.h"
  15. #include "util/gflags_compat.h"
  16. using GFLAGS_NAMESPACE::ParseCommandLineFlags;
  17. DEFINE_string(io_trace_file, "", "The IO trace file path.");
  18. namespace ROCKSDB_NAMESPACE {
  19. IOTraceRecordParser::IOTraceRecordParser(const std::string& input_file)
  20. : input_file_(input_file) {}
  21. void IOTraceRecordParser::PrintHumanReadableHeader(
  22. const IOTraceHeader& header) {
  23. std::stringstream ss;
  24. ss << "Start Time: " << header.start_time
  25. << "\nRocksDB Major Version: " << header.rocksdb_major_version
  26. << "\nRocksDB Minor Version: " << header.rocksdb_minor_version << "\n";
  27. fprintf(stdout, "%s", ss.str().c_str());
  28. }
  29. void IOTraceRecordParser::PrintHumanReadableIOTraceRecord(
  30. const IOTraceRecord& record) {
  31. std::stringstream ss;
  32. ss << "Access Time : " << std::setw(20) << std::left
  33. << record.access_timestamp << ", File Name: " << std::setw(20) << std::left
  34. << record.file_name.c_str() << ", File Operation: " << std::setw(18)
  35. << std::left << record.file_operation.c_str()
  36. << ", Latency: " << std::setw(10) << std::left << record.latency
  37. << ", IO Status: " << record.io_status.c_str();
  38. // Each bit in io_op_data stores which corresponding info from IOTraceOp will
  39. // be added in the trace. Foreg, if bit at position 1 is set then
  40. // IOTraceOp::kIOLen (length) will be logged in the record (Since
  41. // IOTraceOp::kIOLen = 1 in the enum). So find all the set positions in
  42. // io_op_data one by one and, update corresponsing info in the trace record,
  43. // unset that bit to find other set bits until io_op_data = 0.
  44. /* Read remaining options based on io_op_data set by file operation */
  45. int64_t io_op_data = static_cast<int64_t>(record.io_op_data);
  46. while (io_op_data) {
  47. // Find the rightmost set bit.
  48. uint32_t set_pos = static_cast<uint32_t>(log2(io_op_data & -io_op_data));
  49. switch (set_pos) {
  50. case IOTraceOp::kIOFileSize:
  51. ss << ", File Size: " << record.file_size;
  52. break;
  53. case IOTraceOp::kIOLen:
  54. ss << ", Length: " << record.len;
  55. break;
  56. case IOTraceOp::kIOOffset:
  57. ss << ", Offset: " << record.offset;
  58. break;
  59. default:
  60. assert(false);
  61. }
  62. // unset the rightmost bit.
  63. io_op_data &= (io_op_data - 1);
  64. }
  65. int64_t trace_data = static_cast<int64_t>(record.trace_data);
  66. while (trace_data) {
  67. // Find the rightmost set bit.
  68. uint32_t set_pos = static_cast<uint32_t>(log2(trace_data & -trace_data));
  69. switch (set_pos) {
  70. case IODebugContext::TraceData::kRequestID:
  71. ss << ", Request Id: " << record.request_id;
  72. break;
  73. default:
  74. assert(false);
  75. }
  76. // unset the rightmost bit.
  77. trace_data &= (trace_data - 1);
  78. }
  79. ss << "\n";
  80. fprintf(stdout, "%s", ss.str().c_str());
  81. }
  82. int IOTraceRecordParser::ReadIOTraceRecords() {
  83. Status status;
  84. Env* env(Env::Default());
  85. std::unique_ptr<TraceReader> trace_reader;
  86. std::unique_ptr<IOTraceReader> io_trace_reader;
  87. status = NewFileTraceReader(env, EnvOptions(), input_file_, &trace_reader);
  88. if (!status.ok()) {
  89. fprintf(stderr, "%s: %s\n", input_file_.c_str(), status.ToString().c_str());
  90. return 1;
  91. }
  92. io_trace_reader.reset(new IOTraceReader(std::move(trace_reader)));
  93. // Read the header and dump it in a file.
  94. IOTraceHeader header;
  95. status = io_trace_reader->ReadHeader(&header);
  96. if (!status.ok()) {
  97. fprintf(stderr, "%s: %s\n", input_file_.c_str(), status.ToString().c_str());
  98. return 1;
  99. }
  100. PrintHumanReadableHeader(header);
  101. // Read the records one by one and print them in human readable format.
  102. while (status.ok()) {
  103. IOTraceRecord record;
  104. status = io_trace_reader->ReadIOOp(&record);
  105. if (!status.ok()) {
  106. break;
  107. }
  108. PrintHumanReadableIOTraceRecord(record);
  109. }
  110. return 0;
  111. }
  112. int io_tracer_parser(int argc, char** argv) {
  113. ParseCommandLineFlags(&argc, &argv, true);
  114. if (FLAGS_io_trace_file.empty()) {
  115. fprintf(stderr, "IO Trace file path is empty\n");
  116. return 1;
  117. }
  118. IOTraceRecordParser io_tracer_parser(FLAGS_io_trace_file);
  119. return io_tracer_parser.ReadIOTraceRecords();
  120. }
  121. } // namespace ROCKSDB_NAMESPACE
  122. #endif // GFLAGS