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.
lower case 'c' for capacity.
|
From a stats generation standpoint, this looks fine |
| }; | ||
|
|
||
| struct PartitionDescriptor { | ||
| PartitionDescriptor(std::string partition, uint64_t capacity) |
There was a problem hiding this comment.
pass as const std::string& partition
|
|
||
| chargeBasicStats(status); | ||
|
|
||
| chargeTablePartitionIdStats(data); |
There was a problem hiding this comment.
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.
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.
i'd just remove jsonEx as it's not used.
source/common/dynamo/dynamo_filter.h
Outdated
| encoder_callbacks_ = &callbacks; | ||
| } | ||
|
|
||
| static std::string buildPartitionStatString(const std::string& stat_prefix, |
There was a problem hiding this comment.
I will create a utility class for this method. I want to keep this public to improve testability within dynamo_filter_test.cc
source/common/dynamo/dynamo_filter.h
Outdated
| 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.
risky as this depends on stats const, why not use const from RawStats directly?
There was a problem hiding this comment.
Updated to use RawStats var.
| 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.
is the partition_id uuid4? (wondering what those 7 chars look like)
There was a problem hiding this comment.
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.
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.
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.
looks like assert is broken, should be <= MAX_NAME_SIZE.
|
|
||
| *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 |
| :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.
did you preview output? I think this probably has to be on the same line
There was a problem hiding this comment.
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.
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.
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.
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.
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.
Cleaned up all 'Dynamo::' in the code.
source/common/json/json_loader.cc
Outdated
| 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_)); |
| * @param name supplies the key name. | ||
| * @param default_value supplies the value to return if name does not exist. | ||
| * @return double the value. | ||
| */ |
There was a problem hiding this comment.
just double, const double& not needed.
| Json::StringLoader json(data); | ||
| std::vector<RequestParser::PartitionDescriptor> partition_descriptors; | ||
|
|
||
| if (json.hasObject("ConsumedCapacity")) { |
There was a problem hiding this comment.
You can make this logic less nested by using getObject() with allow_empty=true
|
|
||
| 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.
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.
comment (talk about all of the truncations, etc. that are done)
| Json::StringLoader json(data); | ||
| std::vector<RequestParser::PartitionDescriptor> partition_descriptors; | ||
|
|
||
| Json::Object consumed_capacity = json.getObject("ConsumedCapacity", true); |
|
|
||
| std::vector<RequestParser::PartitionDescriptor> | ||
| RequestParser::parsePartitions(const std::string& data) { | ||
| Json::StringLoader json(data); |
There was a problem hiding this comment.
In the common case are we parsing the JSON multiple times?
There was a problem hiding this comment.
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.
nit: place body.empty() in the if above, makes code below less nested.
There was a problem hiding this comment.
Moved body.empty check to above if.
| 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.
nit: for consistency name method as parsePartitions(const std::string& body) ?
There was a problem hiding this comment.
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.
if (body.empty()) {
return;
}
source/common/dynamo/dynamo_filter.h
Outdated
|
|
||
| #include "dynamo_request_parser.h" | ||
|
|
||
| #include "common/json/json_loader.h" |
There was a problem hiding this comment.
nit: include goes below envoy headers, separated by new line
| @@ -1,5 +1,6 @@ | |||
| #pragma once | |||
|
|
|||
| #include "common/json/json_loader.h" | |||
| 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.
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.
|
lgtm (with small comment), +1 |
This allows us to start up to 370 VMs. Fixes envoyproxy#136. Signed-off-by: Piotr Sikora <piotrsikora@google.com>
matcher: add PathMatcher and use in routing, jwt and rbac
Signed-off-by: Tony Allen <tony@allen.gg>
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 <tony@allen.gg> Signed-off-by: Dmitri Dolguikh <ddolguik@redhat.com>
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 <tony@allen.gg> Signed-off-by: Dmitri Dolguikh <ddolguik@redhat.com>
Signed-off-by: Tony Allen <tony@allen.gg>
Signed-off-by: Tony Allen <tony@allen.gg> Signed-off-by: Yifan Yang <needyyang@google.com>
Signed-off-by: Tony Allen <tony@allen.gg>
…_reporting_service zh-translation: /intro/arch_overview/upstream/load_reporting_service.rst
Signed-off-by: Mike Schore <mike.schore@gmail.com> 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 <jp@jpsim.com>
Signed-off-by: Mike Schore <mike.schore@gmail.com> 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 <jp@jpsim.com>
Co-authored-by: José Carlos Chávez <jcchavezs@gmail.com>
closes #147 --------- Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
Please note that this is a pre-release Amazon DynamoDB feature that is not yet widely available.