-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DynamoDB: Log stats for partition id per operation #147
Changes from all commits
6695db2
46732a4
3eca229
9ed557d
6532da8
1a3197f
ae1e2e7
5887f69
a2fd649
3891f85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
#include "dynamo_request_parser.h" | ||
|
||
#include "common/common/utility.h" | ||
#include "common/json/json_loader.h" | ||
|
||
namespace Dynamo { | ||
|
||
|
@@ -60,60 +59,51 @@ std::string RequestParser::parseOperation(const Http::HeaderMap& headerMap) { | |
} | ||
|
||
RequestParser::TableDescriptor RequestParser::parseTable(const std::string& operation, | ||
const std::string& data) { | ||
const Json::Object& json_data) { | ||
TableDescriptor table{"", true}; | ||
|
||
// Simple operations on a single table, have "TableName" explicitly specified. | ||
if (find(SINGLE_TABLE_OPERATIONS.begin(), SINGLE_TABLE_OPERATIONS.end(), operation) != | ||
SINGLE_TABLE_OPERATIONS.end()) { | ||
Json::StringLoader json(data); | ||
if (json.hasObject("TableName")) { | ||
table.table_name = json.getString("TableName"); | ||
} | ||
table.table_name = json_data.getString("TableName", ""); | ||
} else if (find(BATCH_OPERATIONS.begin(), BATCH_OPERATIONS.end(), operation) != | ||
BATCH_OPERATIONS.end()) { | ||
Json::StringLoader json(data); | ||
if (json.hasObject("RequestItems")) { | ||
Json::Object tables = json.getObject("RequestItems"); | ||
tables.iterate([&table](const std::string& key, const Json::Object&) { | ||
if (table.table_name.empty()) { | ||
table.table_name = key; | ||
} else { | ||
if (table.table_name != key) { | ||
table.table_name = ""; | ||
table.is_single_table = false; | ||
return false; | ||
} | ||
Json::Object tables = json_data.getObject("RequestItems", true); | ||
tables.iterate([&table](const std::string& key, const Json::Object&) { | ||
if (table.table_name.empty()) { | ||
table.table_name = key; | ||
} else { | ||
if (table.table_name != key) { | ||
table.table_name = ""; | ||
table.is_single_table = false; | ||
return false; | ||
} | ||
|
||
return true; | ||
}); | ||
} | ||
} | ||
return true; | ||
}); | ||
} | ||
|
||
return table; | ||
} | ||
std::vector<std::string> RequestParser::parseBatchUnProcessedKeys(const std::string& data) { | ||
std::vector<std::string> RequestParser::parseBatchUnProcessedKeys(const Json::Object& json_data) { | ||
std::vector<std::string> unprocessed_tables; | ||
Json::StringLoader json(data); | ||
if (json.hasObject("UnprocessedKeys")) { | ||
Json::Object tables = json.getObject("UnprocessedKeys"); | ||
tables.iterate([&unprocessed_tables](const std::string& key, const Json::Object&) { | ||
unprocessed_tables.emplace_back(key); | ||
return true; | ||
}); | ||
} | ||
Json::Object tables = json_data.getObject("UnprocessedKeys", true); | ||
tables.iterate([&unprocessed_tables](const std::string& key, const Json::Object&) { | ||
unprocessed_tables.emplace_back(key); | ||
return true; | ||
}); | ||
|
||
return unprocessed_tables; | ||
} | ||
std::string RequestParser::parseErrorType(const std::string& data) { | ||
Json::StringLoader json(data); | ||
|
||
if (json.hasObject("__type")) { | ||
std::string error_type = json.getString("__type"); | ||
for (const std::string& supported_error_type : SUPPORTED_ERROR_TYPES) { | ||
if (StringUtil::endsWith(error_type, supported_error_type)) { | ||
return supported_error_type; | ||
} | ||
std::string RequestParser::parseErrorType(const Json::Object& json_data) { | ||
std::string error_type = json_data.getString("__type", ""); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if __type is not set on the json, we'll iterate though all supported_error_types. we could early exit if __type is missing or if error_type after json_data.getString("__type", ""); is empty. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
if (error_type.empty()) { | ||
return ""; | ||
} | ||
|
||
for (const std::string& supported_error_type : SUPPORTED_ERROR_TYPES) { | ||
if (StringUtil::endsWith(error_type, supported_error_type)) { | ||
return supported_error_type; | ||
} | ||
} | ||
|
||
|
@@ -125,4 +115,24 @@ bool RequestParser::isBatchOperation(const std::string& operation) { | |
BATCH_OPERATIONS.end(); | ||
} | ||
|
||
std::vector<RequestParser::PartitionDescriptor> | ||
RequestParser::parsePartitions(const Json::Object& json_data) { | ||
std::vector<RequestParser::PartitionDescriptor> partition_descriptors; | ||
|
||
Json::Object partitions = | ||
json_data.getObject("ConsumedCapacity", true).getObject("Partitions", true); | ||
partitions.iterate([&partition_descriptors, &partitions](const std::string& key, | ||
const Json::Object&) { | ||
// For a given partition id, the amount of capacity used is returned in the body as a double. | ||
// A stat will be created to track the capacity consumed for the operation, table and partition. | ||
// Stats counter only increments by whole numbers, capacity is round up to the nearest integer | ||
// to account for this. | ||
uint64_t capacity_integer = static_cast<uint64_t>(std::ceil(partitions.getDouble(key, 0.0))); | ||
partition_descriptors.emplace_back(key, capacity_integer); | ||
return true; | ||
}); | ||
|
||
return partition_descriptors; | ||
} | ||
|
||
} // Dynamo |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
|
||
#include "envoy/http/header_map.h" | ||
|
||
#include "common/json/json_loader.h" | ||
|
||
namespace Dynamo { | ||
|
||
/* | ||
|
@@ -18,6 +20,13 @@ class RequestParser { | |
bool is_single_table; | ||
}; | ||
|
||
struct PartitionDescriptor { | ||
PartitionDescriptor(const std::string& partition, uint64_t capacity) | ||
: partition_id_(partition), capacity_(capacity) {} | ||
std::string partition_id_; | ||
uint64_t capacity_; | ||
}; | ||
|
||
/** | ||
* Parse operation out of x-amz-target header. | ||
* @return empty string if operation cannot be parsed. | ||
|
@@ -40,7 +49,7 @@ class RequestParser { | |
* | ||
* @throw Json::Exception if data is not in valid Json format. | ||
*/ | ||
static TableDescriptor parseTable(const std::string& operation, const std::string& data); | ||
static TableDescriptor parseTable(const std::string& operation, const Json::Object& json_data); | ||
|
||
/** | ||
* Parse error details which might be provided for a given response code. | ||
|
@@ -52,20 +61,29 @@ class RequestParser { | |
* | ||
* @throw Json::Exception if data is not in valid Json format. | ||
*/ | ||
static std::string parseErrorType(const std::string& data); | ||
static std::string parseErrorType(const Json::Object& json_data); | ||
|
||
/** | ||
* Parse unprocessed keys for batch operation results. | ||
* @return empty set if there are no unprocessed keys or a set of table names that did not get | ||
* processed in the batch operation. | ||
*/ | ||
static std::vector<std::string> parseBatchUnProcessedKeys(const std::string& data); | ||
static std::vector<std::string> parseBatchUnProcessedKeys(const Json::Object& json_data); | ||
|
||
/** | ||
* @return true if the operation is in the set of supported BATCH_OPERATIONS | ||
*/ | ||
static bool isBatchOperation(const std::string& operation); | ||
|
||
/** | ||
* Parse the Partition ids and the consumed capacity from the body. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: for consistency name method as parsePartitions(const std::string& body) ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For this file, data is the consistent variable name. |
||
* @return empty set if there is no partition data or a set of partition data containing | ||
* the partition id as a string and the capacity consumed as an integer. | ||
* | ||
* @throw Json::Exception if data is not in valid Json format. | ||
*/ | ||
static std::vector<PartitionDescriptor> parsePartitions(const Json::Object& json_data); | ||
|
||
private: | ||
static const Http::LowerCaseString X_AMZ_TARGET; | ||
static const std::vector<std::string> SINGLE_TABLE_OPERATIONS; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (body.empty()) {
return;
}