Skip to content
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

Merged
merged 10 commits into from
Oct 17, 2016

Conversation

ccaraman
Copy link
Contributor

Please note that this is a pre-release Amazon DynamoDB feature that is not yet widely available.

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,
Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@theatrus
Copy link

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)
Copy link
Member

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

Copy link
Contributor Author

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Copy link
Member

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) {
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed.

Copy link
Contributor Author

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,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private to DynamoFilter

Copy link
Contributor Author

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;
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.
Copy link
Member

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)

Copy link
Contributor Author

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;
Copy link
Member

@RomanDzhabarov RomanDzhabarov Oct 13, 2016

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).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grammar

Copy link
Contributor Author

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
Copy link
Member

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

Copy link
Contributor Author

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);
Copy link
Member

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.

Copy link
Contributor Author

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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete jsonEx

Copy link
Contributor Author

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 =
Copy link
Member

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

Copy link
Contributor Author

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_));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grammar

Copy link
Contributor Author

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;
Copy link
Member

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.

Copy link
Contributor Author

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")) {
Copy link
Member

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

Copy link
Contributor Author

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.
Copy link
Member

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,
Copy link
Member

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)

Copy link
Contributor Author

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local var not needed

Copy link
Contributor Author

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);
Copy link
Member

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?

Copy link
Contributor Author

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?

@mattklein123
Copy link
Member

Also, minor, can you change the PR/commit title to be prefixed with "dynamo: "

@ccaraman ccaraman changed the title Log stats for partition id per operation DynamoDB: Log stats for partition id per operation Oct 14, 2016
if (table_descriptor_.table_name.empty() || operation_.empty()) {
return;
}
if (!body.empty()) {
Copy link
Member

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.

Copy link
Contributor Author

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.
Copy link
Member

@RomanDzhabarov RomanDzhabarov Oct 14, 2016

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) ?

Copy link
Contributor Author

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()) {
Copy link
Member

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"
Copy link
Member

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

Copy link
Contributor Author

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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: header ordering

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Member

@mattklein123 mattklein123 left a 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", "");
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@RomanDzhabarov
Copy link
Member

RomanDzhabarov commented Oct 17, 2016

lgtm (with small comment), +1

@mattklein123 mattklein123 merged commit 7342353 into master Oct 17, 2016
@mattklein123 mattklein123 deleted the shard-id-header branch October 17, 2016 20:42
PiotrSikora added a commit to PiotrSikora/envoy that referenced this pull request Aug 25, 2019
This allows us to start up to 370 VMs.

Fixes envoyproxy#136.

Signed-off-by: Piotr Sikora <[email protected]>
JimmyCYJ pushed a commit to JimmyCYJ/envoy that referenced this pull request Feb 14, 2020
matcher: add PathMatcher and use in routing, jwt and rbac
mattklein123 pushed a commit that referenced this pull request Jun 30, 2020
PiotrSikora pushed a commit that referenced this pull request Jun 30, 2020
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]>
PiotrSikora pushed a commit that referenced this pull request Jun 30, 2020
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]>
PiotrSikora pushed a commit that referenced this pull request Jun 30, 2020
aimless404 pushed a commit to aimless404/envoy that referenced this pull request Jun 30, 2020
liuxu623 pushed a commit to liuxu623/envoy that referenced this pull request Jul 14, 2020
wolfguoliang pushed a commit to wolfguoliang/envoy that referenced this pull request Jan 23, 2021
…_reporting_service

zh-translation: /intro/arch_overview/upstream/load_reporting_service.rst
jpsim pushed a commit that referenced this pull request Nov 28, 2022
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]>
jpsim pushed a commit that referenced this pull request Nov 29, 2022
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]>
arminabf pushed a commit to arminabf/envoy that referenced this pull request Jun 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants