-
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
Conversation
std::string stats_table_prefix = fmt::format("{}table.{}", stat_prefix, table_name); | ||
// Use only the last 7 characters from the partition id. | ||
std::string stats_partition_postfix = | ||
fmt::format(".Capacity.{}.__partition_id={}", operation, |
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.
lower case 'c' for capacity.
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.
Fixed.
From a stats generation standpoint, this looks fine |
@@ -18,6 +18,13 @@ class RequestParser { | |||
bool is_single_table; | |||
}; | |||
|
|||
struct PartitionDescriptor { | |||
PartitionDescriptor(std::string partition, uint64_t capacity) |
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.
pass as const std::string& partition
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.
fixed
@@ -57,6 +57,8 @@ void DynamoFilter::onEncodeComplete(const Buffer::Instance& data) { | |||
|
|||
chargeBasicStats(status); | |||
|
|||
chargeTablePartitionIdStats(data); |
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.
we'd need to update docs, once review is close to the final state: https://lyft.github.io/envoy/docs/configuration/http_filters/dynamodb_filter.html#config-http-filters-dynamo
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.
added
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.
nit: remove newline at 60 and 62
stat_prefix_, table_descriptor_.table_name, operation_, partition.partition_id_); | ||
stats_.counter(stats_string).add(partition.capacity_); | ||
} | ||
} catch (const Json::Exception& jsonEx) { |
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.
i'd just remove jsonEx as it's not used.
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.
removed.
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.
removed.
@@ -37,6 +37,11 @@ class DynamoFilter : public Http::StreamFilter { | |||
encoder_callbacks_ = &callbacks; | |||
} | |||
|
|||
static std::string buildPartitionStatString(const std::string& stat_prefix, |
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.
private to DynamoFilter
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.
I will create a utility class for this method. I want to keep this public to improve testability within dynamo_filter_test.cc
@@ -46,11 +51,13 @@ class DynamoFilter : public Http::StreamFilter { | |||
uint64_t status); | |||
void chargeFailureSpecificStats(const Buffer::Instance& data); | |||
void chargeUnProcessedKeysStats(const Buffer::Instance& data); | |||
void chargeTablePartitionIdStats(const Buffer::Instance& data); | |||
|
|||
static const size_t MAX_NAME_SIZE = 127; |
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.
risky as this depends on stats const, why not use const from RawStats directly?
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.
Updated to use RawStats var.
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.
Updated.
const std::string& operation, | ||
const std::string& partition_id) { | ||
std::string stats_table_prefix = fmt::format("{}table.{}", stat_prefix, table_name); | ||
// Use only the last 7 characters from the partition id. |
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.
is the partition_id uuid4? (wondering what those 7 chars look like)
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.
Yes, the partition_id is a uuid. We are choosing to use the last 7 characters for now.
fmt::format(".Capacity.{}.__partition_id={}", operation, | ||
partition_id.substr(partition_id.size() - 7, partition_id.size())); | ||
// Calculate how many characters are available for the table prefix. | ||
size_t remaining_size = MAX_NAME_SIZE - stats_partition_postfix.size() - 1; |
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.
why do we have here -1, MAX_NAME_SIZE is the actual length we can have in stats name, see RawStatData struct (it allocates MAX_NAME_SIZE+1 for \0).
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.
Our check is size < MAX_NAME_SIZE
https://github.com/lyft/envoy/blob/master/source/common/stats/stats_impl.cc#L19
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.
looks like assert is broken, should be <= MAX_NAME_SIZE.
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.
Fixed.
@@ -54,6 +54,18 @@ in all operations from the batch. | |||
upstream_rq_total_xxx, Counter, Total number of requests on <table_name> table per response code (503/2xx/etc) | |||
upstream_rq_time_xxx, Timer, Time spent on <table_name> table per response code (400/3xx/etc) | |||
|
|||
*Disclaimer: Please note that this is a pre-release Amazon DynamoDB feature that is not yet widely available.* | |||
Per partition and operation stats can be found in the *http.<stat_prefix>.dynamodb.table.<table_name>.* | |||
namespace. For Batch operations, Envoy tracks per partition and operation stats in the case only if it is the same |
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.
grammar
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.
Fixed.
:header: Name, Type, Description | ||
:widths: 1, 1, 2 | ||
|
||
capacity.<operation_name>.__partition_id=<last_seven_characters_from_partition_id>, Counter, Total number of |
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.
did you preview output? I think this probably has to be on the same line
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.
It does have to be on the same line. Fixed
if (table_descriptor_.table_name.empty() || operation_.empty()) { | ||
return; | ||
} | ||
std::string body = buildBody(encoder_callbacks_->encodingBuffer(), data); |
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.
you are potentially going to buildBody() multiple times I think, and now this is always going to happen in general. Let's make sure this only happens once.
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.
buildBody is now being called from onEncodeComplete.
stat_prefix_, table_descriptor_.table_name, operation_, partition.partition_id_); | ||
stats_.counter(stats_string).add(partition.capacity_); | ||
} | ||
} catch (const Json::Exception& jsonEx) { |
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.
delete jsonEx
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.
Deleted for all instances.
std::string body = buildBody(encoder_callbacks_->encodingBuffer(), data); | ||
if (!body.empty()) { | ||
try { | ||
std::vector<Dynamo::RequestParser::PartitionDescriptor> partitions = |
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.
Nit, remove Dynamo:: from everywhere in this file. You don't need to specify the namespace prefix within the namespace. Makes code less verbose
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.
Cleaned up all 'Dynamo::' in the code.
double Object::getDouble(const std::string& name) const { | ||
json_t* real = json_object_get(json_, name.c_str()); | ||
if (!real || !json_is_real(real)) { | ||
throw Exception(fmt::format("key '{}' missing or not an double in '{}'", name, name_)); |
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.
grammar
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.
fixed.
* @param default_value supplies the value to return if name does not exist. | ||
* @return double the value. | ||
*/ | ||
double getDouble(const std::string& name, const double& default_value) const; |
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.
just double, const double& not needed.
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.
fixed.
Json::StringLoader json(data); | ||
std::vector<RequestParser::PartitionDescriptor> partition_descriptors; | ||
|
||
if (json.hasObject("ConsumedCapacity")) { |
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.
You can make this logic less nested by using getObject() with allow_empty=true
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.
Fixed.
|
||
partitions.iterate( | ||
[&partition_descriptors, &partitions](const std::string& key, const Json::Object&) { | ||
// Capacity is a double and it is rounded up to the nearest integer. |
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.
it's not intuitive to me what is going on here. Since this is not yet in the public docs, can you have a slightly larger comment on what the API returns here and how we are processing it
|
||
class Utility { | ||
public: | ||
static std::string buildPartitionStatString(const std::string& stat_prefix, |
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.
comment (talk about all of the truncations, etc. that are done)
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.
Comments added.
Json::StringLoader json(data); | ||
std::vector<RequestParser::PartitionDescriptor> partition_descriptors; | ||
|
||
Json::Object consumed_capacity = json.getObject("ConsumedCapacity", true); |
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.
local var not needed
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.
Fixed
@@ -125,4 +125,26 @@ bool RequestParser::isBatchOperation(const std::string& operation) { | |||
BATCH_OPERATIONS.end(); | |||
} | |||
|
|||
std::vector<RequestParser::PartitionDescriptor> | |||
RequestParser::parsePartitions(const std::string& data) { | |||
Json::StringLoader json(data); |
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.
In the common case are we parsing the JSON multiple times?
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.
It is possible. Maybe I should update DynamoFilter::buildBody to return Json and update all of dynamo_request_parser to take in a json object?
Also, minor, can you change the PR/commit title to be prefixed with "dynamo: " |
if (table_descriptor_.table_name.empty() || operation_.empty()) { | ||
return; | ||
} | ||
if (!body.empty()) { |
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.
nit: place body.empty() in the if above, makes code below less nested.
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.
Moved body.empty check to above if.
@@ -66,6 +73,15 @@ class RequestParser { | |||
*/ | |||
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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
For this file, data is the consistent variable name.
if (RequestParser::isBatchOperation(operation_)) { | ||
chargeUnProcessedKeysStats(body); | ||
std::string body = buildBody(encoder_callbacks_->encodingBuffer(), data); | ||
if (!body.empty()) { |
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;
}
@@ -2,6 +2,7 @@ | |||
|
|||
#include "dynamo_request_parser.h" | |||
|
|||
#include "common/json/json_loader.h" |
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.
nit: include goes below envoy headers, separated by new line
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.
Fixed.
@@ -1,5 +1,6 @@ | |||
#pragma once | |||
|
|||
#include "common/json/json_loader.h" |
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.
nit: header ordering
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.
Fixed.
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.
lgtm after nits
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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
lgtm (with small comment), +1 |
This allows us to start up to 370 VMs. Fixes envoyproxy#136. Signed-off-by: Piotr Sikora <[email protected]>
matcher: add PathMatcher and use in routing, jwt and rbac
Signed-off-by: Tony Allen <[email protected]>
This patch adds support for global accepted connection limits. May be configured simultaneously with per-listener connection limits and enforced separately. If the global limit is unconfigured, Envoy will emit a warning during start-up. Global downstream connection count tracking (across all listeners and threads) is performed by the network listener implementation upon acceptance of a socket. The mapping of active socket objects to the actual accepted downstream sockets is assumed to remain bijective. Given that characteristic, the connection counts are tied to the lifetime of the objects. Signed-off-by: Tony Allen <[email protected]> Signed-off-by: Dmitri Dolguikh <[email protected]>
This patch adds support for global accepted connection limits. May be configured simultaneously with per-listener connection limits and enforced separately. If the global limit is unconfigured, Envoy will emit a warning during start-up. Global downstream connection count tracking (across all listeners and threads) is performed by the network listener implementation upon acceptance of a socket. The mapping of active socket objects to the actual accepted downstream sockets is assumed to remain bijective. Given that characteristic, the connection counts are tied to the lifetime of the objects. Signed-off-by: Tony Allen <[email protected]> Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Tony Allen <[email protected]>
Signed-off-by: Tony Allen <[email protected]> Signed-off-by: Yifan Yang <[email protected]>
Signed-off-by: Tony Allen <[email protected]>
…_reporting_service zh-translation: /intro/arch_overview/upstream/load_reporting_service.rst
Signed-off-by: Mike Schore <[email protected]> Description: Welp. Maybe we need this after all. Risk Level: Low Testing: Saw more ceilf errors and this fixed them again. Signed-off-by: JP Simard <[email protected]>
Signed-off-by: Mike Schore <[email protected]> Description: Welp. Maybe we need this after all. Risk Level: Low Testing: Saw more ceilf errors and this fixed them again. Signed-off-by: JP Simard <[email protected]>
Co-authored-by: José Carlos Chávez <[email protected]>
Please note that this is a pre-release Amazon DynamoDB feature that is not yet widely available.