Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c226497
Save state on origin timeing
oschaaf Jun 15, 2020
c6697de
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Jun 15, 2020
28e0d34
Fix clang-tidy, format, and test build
oschaaf Jun 16, 2020
94ad984
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 19, 2020
933c589
stats naming
oschaaf Aug 19, 2020
a1691ec
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 21, 2020
740d0ca
Track request receipt deltas. Configure response header name.
oschaaf Aug 21, 2020
1afe2f1
Save state before context switching
oschaaf Aug 21, 2020
ae0c08e
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 21, 2020
3487e19
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 24, 2020
1d1f03a
Fix format
oschaaf Aug 24, 2020
a9d99eb
Suppress clang-tidy on MUTABLE_CONSTRUCT_ON_FIRST_USE
oschaaf Aug 24, 2020
0aa8630
Proper locking, add TODOs and doc comments.
oschaaf Aug 24, 2020
db01e40
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 24, 2020
5e48513
Small fixes
oschaaf Aug 24, 2020
d9569cb
Add unit test for StreamDecoder
oschaaf Aug 25, 2020
cf1170c
Review feedback
oschaaf Aug 26, 2020
421feb8
check_format introduced proto comment issues. Add punctuation.
oschaaf Aug 26, 2020
af148ea
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 27, 2020
e813e75
Review feedback
oschaaf Aug 27, 2020
505495c
Save state on splitting out a separate extension and stopwatch
oschaaf Aug 27, 2020
5405dc9
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 27, 2020
d858b55
Small corrections
oschaaf Aug 28, 2020
3cf32b8
Add threaded spam test for stopwatch. Add doc comments.
oschaaf Aug 28, 2020
35aee47
clang-tidy: fix for loop
oschaaf Aug 28, 2020
027c00f
Merge remote-tracking branch 'upstream/master' into origin-timings
oschaaf Aug 29, 2020
70502e1
Review feedback: doc comments
oschaaf Aug 29, 2020
7774e2d
review feedback
oschaaf Sep 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/server/response_options.proto
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ message ResponseOptions {
// Concurrency based linear delay configuration.
ConcurrencyBasedLinearDelay concurrency_based_linear_delay = 5;
}
// If set, makes the extension include timing data in the supplied response header name.
// For example, when set to "x-abc", and 3 requests are performed, the test server will respond
// with: Response 1: No x-abc header because there's no previous response. Response 2: Header
// x-abc: <ns elapsed between responses 2 and 1>. Response 3: Header x-abc: <ns elapsed between
// responses 3 and 2>.
string emit_previous_request_delta_in_response_header = 6;
}
12 changes: 12 additions & 0 deletions include/nighthawk/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,15 @@ envoy_basic_cc_library(
"@envoy//source/common/http:headers_lib",
],
)

envoy_basic_cc_library(
name = "stopwatch_lib",
hdrs = [
"stopwatch.h",
],
include_prefix = "nighthawk/common",
deps = [
"@envoy//include/envoy/common:base_includes",
"@envoy//include/envoy/common:time_interface",
],
)
22 changes: 22 additions & 0 deletions include/nighthawk/common/stopwatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "envoy/common/pure.h"
#include "envoy/common/time.h"

namespace Nighthawk {

/**
* Interface for measuring elapsed time between events.
*/
class Stopwatch {
public:
virtual ~Stopwatch() = default;
/**
* @param time_source used to obtain a sample of the current time.
* @return uint64_t 0 on the first invocation, and the number of elapsed nanoseconds since the
* last invocation otherwise.
*/
virtual uint64_t getElapsedNsAndReset(Envoy::TimeSource& time_source) PURE;
};

} // namespace Nighthawk
14 changes: 10 additions & 4 deletions source/client/benchmark_client_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ BenchmarkClientStatistic::BenchmarkClientStatistic(BenchmarkClientStatistic&& st
latency_3xx_statistic(std::move(statistic.latency_3xx_statistic)),
latency_4xx_statistic(std::move(statistic.latency_4xx_statistic)),
latency_5xx_statistic(std::move(statistic.latency_5xx_statistic)),
latency_xxx_statistic(std::move(statistic.latency_xxx_statistic)) {}
latency_xxx_statistic(std::move(statistic.latency_xxx_statistic)),
origin_latency_statistic(std::move(statistic.origin_latency_statistic)) {}

BenchmarkClientStatistic::BenchmarkClientStatistic(
StatisticPtr&& connect_stat, StatisticPtr&& response_stat,
StatisticPtr&& response_header_size_stat, StatisticPtr&& response_body_size_stat,
StatisticPtr&& latency_1xx_stat, StatisticPtr&& latency_2xx_stat,
StatisticPtr&& latency_3xx_stat, StatisticPtr&& latency_4xx_stat,
StatisticPtr&& latency_5xx_stat, StatisticPtr&& latency_xxx_stat)
StatisticPtr&& latency_5xx_stat, StatisticPtr&& latency_xxx_stat,
StatisticPtr&& origin_latency_stat)
: connect_statistic(std::move(connect_stat)), response_statistic(std::move(response_stat)),
response_header_size_statistic(std::move(response_header_size_stat)),
response_body_size_statistic(std::move(response_body_size_stat)),
Expand All @@ -46,7 +48,8 @@ BenchmarkClientStatistic::BenchmarkClientStatistic(
latency_3xx_statistic(std::move(latency_3xx_stat)),
latency_4xx_statistic(std::move(latency_4xx_stat)),
latency_5xx_statistic(std::move(latency_5xx_stat)),
latency_xxx_statistic(std::move(latency_xxx_stat)) {}
latency_xxx_statistic(std::move(latency_xxx_stat)),
origin_latency_statistic(std::move(origin_latency_stat)) {}

Envoy::Http::ConnectionPool::Cancellable*
Http1PoolImpl::newStream(Envoy::Http::ResponseDecoder& response_decoder,
Expand Down Expand Up @@ -97,6 +100,7 @@ BenchmarkClientHttpImpl::BenchmarkClientHttpImpl(
statistic_.latency_4xx_statistic->setId("benchmark_http_client.latency_4xx");
statistic_.latency_5xx_statistic->setId("benchmark_http_client.latency_5xx");
statistic_.latency_xxx_statistic->setId("benchmark_http_client.latency_xxx");
statistic_.origin_latency_statistic->setId("benchmark_http_client.origin_latency_statistic");
}

void BenchmarkClientHttpImpl::terminate() {
Expand All @@ -121,6 +125,7 @@ StatisticPtrMap BenchmarkClientHttpImpl::statistics() const {
statistics[statistic_.latency_4xx_statistic->id()] = statistic_.latency_4xx_statistic.get();
statistics[statistic_.latency_5xx_statistic->id()] = statistic_.latency_5xx_statistic.get();
statistics[statistic_.latency_xxx_statistic->id()] = statistic_.latency_xxx_statistic.get();
statistics[statistic_.origin_latency_statistic->id()] = statistic_.origin_latency_statistic.get();
return statistics;
};

Expand Down Expand Up @@ -160,7 +165,8 @@ bool BenchmarkClientHttpImpl::tryStartRequest(CompletionCallback caller_completi
dispatcher_, api_.timeSource(), *this, std::move(caller_completion_callback),
*statistic_.connect_statistic, *statistic_.response_statistic,
*statistic_.response_header_size_statistic, *statistic_.response_body_size_statistic,
request->header(), shouldMeasureLatencies(), content_length, generator_, http_tracer_);
*statistic_.origin_latency_statistic, request->header(), shouldMeasureLatencies(),
content_length, generator_, http_tracer_);
requests_initiated_++;
pool_ptr->newStream(*stream_decoder, *stream_decoder);
return true;
Expand Down
4 changes: 3 additions & 1 deletion source/client/benchmark_client_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ struct BenchmarkClientStatistic {
StatisticPtr&& response_body_size_stat, StatisticPtr&& latency_1xx_stat,
StatisticPtr&& latency_2xx_stat, StatisticPtr&& latency_3xx_stat,
StatisticPtr&& latency_4xx_stat, StatisticPtr&& latency_5xx_stat,
StatisticPtr&& latency_xxx_stat);
StatisticPtr&& latency_xxx_stat,
StatisticPtr&& origin_latency_statistic);

// These are declared order dependent. Changing ordering may trigger on assert upon
// destruction when tls has been involved during usage.
Expand All @@ -71,6 +72,7 @@ struct BenchmarkClientStatistic {
StatisticPtr latency_4xx_statistic;
StatisticPtr latency_5xx_statistic;
StatisticPtr latency_xxx_statistic;
StatisticPtr origin_latency_statistic;
};

class Http1PoolImpl : public Envoy::Http::Http1::ProdConnPoolImpl {
Expand Down
1 change: 1 addition & 0 deletions source/client/factories_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ BenchmarkClientPtr BenchmarkClientFactoryImpl::create(
std::make_unique<SinkableHdrStatistic>(scope, worker_id),
std::make_unique<SinkableHdrStatistic>(scope, worker_id),
std::make_unique<SinkableHdrStatistic>(scope, worker_id),
std::make_unique<SinkableHdrStatistic>(scope, worker_id),
std::make_unique<SinkableHdrStatistic>(scope, worker_id));
auto benchmark_client = std::make_unique<BenchmarkClientHttpImpl>(
api, dispatcher, scope, statistic, options_.h2(), cluster_manager, http_tracer, cluster_name,
Expand Down
14 changes: 14 additions & 0 deletions source/client/stream_decoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ void StreamDecoder::decodeHeaders(Envoy::Http::ResponseHeaderMapPtr&& headers, b
response_header_sizes_statistic_.addValue(response_headers_->byteSize());
const uint64_t response_code = Envoy::Http::Utility::getResponseStatus(*response_headers_);
stream_info_.response_code_ = static_cast<uint32_t>(response_code);
const auto timing_header_name =
Envoy::Http::LowerCaseString("x-nighthawk-do-not-use-origin-timings");
const Envoy::Http::HeaderEntry* timing_header = response_headers_->get(timing_header_name);
if (timing_header != nullptr) {
absl::string_view timing_value = timing_header->value().getStringView();
int64_t origin_delta;
if (absl::SimpleAtoi(timing_value, &origin_delta) && origin_delta >= 0) {
origin_latency_statistic_.addValue(origin_delta);
} else {
// TODO(#484): avoid high frequency logging.
ENVOY_LOG(warn, "Bad origin delta: '{}'.", timing_value);
}
}

if (complete_) {
onComplete(true);
}
Expand Down
6 changes: 4 additions & 2 deletions source/client/stream_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ class StreamDecoder : public Envoy::Http::ResponseDecoder,
StreamDecoderCompletionCallback& decoder_completion_callback,
OperationCallback caller_completion_callback, Statistic& connect_statistic,
Statistic& latency_statistic, Statistic& response_header_sizes_statistic,
Statistic& response_body_sizes_statistic, HeaderMapPtr request_headers,
bool measure_latencies, uint32_t request_body_size,
Statistic& response_body_sizes_statistic, Statistic& origin_latency_statistic,
HeaderMapPtr request_headers, bool measure_latencies, uint32_t request_body_size,
Envoy::Random::RandomGenerator& random_generator,
Envoy::Tracing::HttpTracerSharedPtr& http_tracer)
: dispatcher_(dispatcher), time_source_(time_source),
Expand All @@ -53,6 +53,7 @@ class StreamDecoder : public Envoy::Http::ResponseDecoder,
connect_statistic_(connect_statistic), latency_statistic_(latency_statistic),
response_header_sizes_statistic_(response_header_sizes_statistic),
response_body_sizes_statistic_(response_body_sizes_statistic),
origin_latency_statistic_(origin_latency_statistic),
request_headers_(std::move(request_headers)), connect_start_(time_source_.monotonicTime()),
complete_(false), measure_latencies_(measure_latencies),
request_body_size_(request_body_size), stream_info_(time_source_),
Expand Down Expand Up @@ -103,6 +104,7 @@ class StreamDecoder : public Envoy::Http::ResponseDecoder,
Statistic& latency_statistic_;
Statistic& response_header_sizes_statistic_;
Statistic& response_body_sizes_statistic_;
Statistic& origin_latency_statistic_;
HeaderMapPtr request_headers_;
Envoy::Http::ResponseHeaderMapPtr response_headers_;
Envoy::Http::ResponseTrailerMapPtr trailer_headers_;
Expand Down
18 changes: 18 additions & 0 deletions source/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,24 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "thread_safe_monotonic_time_stopwatch_lib",
srcs = [
"thread_safe_monotonic_time_stopwatch.cc",
],
hdrs = [
"thread_safe_monotonic_time_stopwatch.h",
],
repository = "@envoy",
visibility = ["//visibility:public"],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

no changes required for this (not even sure if it's possible), but it would be nice if we could set this at the package level instead of on every single target in common/BUILD. But that doesn't seem to be supported by envoy_package.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think this is a good point, I filed an issue tagged as tech-debt to track this: #502

deps = [
"//include/nighthawk/common:stopwatch_lib",
"@envoy//include/envoy/common:time_interface",
"@envoy//source/common/common:lock_guard_lib_with_external_headers",
"@envoy//source/common/common:thread_lib_with_external_headers",
],
)

envoy_cc_library(
name = "nighthawk_common_lib",
srcs = [
Expand Down
16 changes: 16 additions & 0 deletions source/common/thread_safe_monotonic_time_stopwatch.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "common/thread_safe_monotonic_time_stopwatch.h"

namespace Nighthawk {

uint64_t ThreadSafeMontonicTimeStopwatch::getElapsedNsAndReset(Envoy::TimeSource& time_source) {
Envoy::Thread::LockGuard guard(lock_);
// Note that we obtain monotonic time under lock, to ensure that start_ will be updated
// monotonically.
const Envoy::MonotonicTime new_time = time_source.monotonicTime();
const uint64_t elapsed_ns =
start_ == Envoy::MonotonicTime::min() ? 0 : (new_time - start_).count();
start_ = new_time;
return elapsed_ns;
}

} // namespace Nighthawk
40 changes: 40 additions & 0 deletions source/common/thread_safe_monotonic_time_stopwatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include "nighthawk/common/stopwatch.h"

#include "external/envoy/source/common/common/lock_guard.h"
#include "external/envoy/source/common/common/thread.h"

namespace Nighthawk {

/**
* Utility class for thread safe tracking of elapsed monotonic time.
* Example usage:
*
* ThreadSafeMontonicTimeStopwatch stopwatch;
* int i = 0;
* do {
* std::cerr << stopwatch.getElapsedNsAndReset() <<
* "ns elapsed since last iteration." << std::endl;
* } while (++i < 100);
*/
class ThreadSafeMontonicTimeStopwatch : public Stopwatch {
public:
/**
* Construct a new ThreadSafe & MontonicTime-based Stopwatch object.
*/
ThreadSafeMontonicTimeStopwatch() : start_(Envoy::MonotonicTime::min()) {}

/**
* @param time_source used to obtain a sample of the current monotonic time.
* @return uint64_t 0 on the first invocation, and the number of elapsed nanoseconds since the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In google-convention, we'd most likely try to use absl::duration here, rather than an int representing a unit of time. Would that be reasonable here, or no?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Well, while I didn't consider absl::Duration (I didn't know it existed). But I did consider std::chrono::duration, and ended up leaning towards uint64_t because that:

Having said that, I feel this is a subjective matter, so I'd be happy to change this if you lean towards absl::Duration after reading my considerations above.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That makes sense. I don't know if it's worth bringing in absl::Duration just for this. If we wanted to, we could try to bring in absl::Duration on a more global change later.

* last invocation otherwise.
*/
uint64_t getElapsedNsAndReset(Envoy::TimeSource& time_source) override;

private:
Envoy::Thread::MutexBasicLockable lock_;
Envoy::MonotonicTime start_ GUARDED_BY(lock_);
};

} // namespace Nighthawk
25 changes: 25 additions & 0 deletions source/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "http_time_tracking_filter_lib",
srcs = ["http_time_tracking_filter.cc"],
hdrs = ["http_time_tracking_filter.h"],
repository = "@envoy",
deps = [
":configuration_lib",
":well_known_headers_lib",
"//api/server:response_options_proto_cc_proto",
"//source/common:thread_safe_monotonic_time_stopwatch_lib",
"@envoy//source/exe:envoy_common_lib_with_external_headers",
"@envoy//source/extensions/filters/http/common:pass_through_filter_lib_with_external_headers",
],
)

envoy_cc_library(
name = "http_dynamic_delay_filter_lib",
srcs = ["http_dynamic_delay_filter.cc"],
Expand Down Expand Up @@ -77,3 +92,13 @@ envoy_cc_library(
"@envoy//include/envoy/server:filter_config_interface_with_external_headers",
],
)

envoy_cc_library(
name = "http_time_tracking_filter_config",
srcs = ["http_time_tracking_filter_config.cc"],
repository = "@envoy",
deps = [
":http_time_tracking_filter_lib",
"@envoy//include/envoy/server:filter_config_interface_with_external_headers",
],
)
71 changes: 71 additions & 0 deletions source/server/http_time_tracking_filter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "server/http_time_tracking_filter.h"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This directory is starting to grow. Would it make sense to create a separate PR that moves this and other filters all into a filters subdirectory?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes I think that would make sense. Alternatively, we could keep this directory just for extensions and their configuration, and re-home everything else that's in there so far: configuration.h/cc (helpers), well_known_headers.h (http header name definitions). Should I file an issue to track this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

An issue to track this would be great. I'm happy to defer to you on what makes the most sense. The filters subdirectory was just what made sense to me on a quick lookthrough.


#include <string>

#include "envoy/server/filter_config.h"

#include "common/thread_safe_monotonic_time_stopwatch.h"

#include "server/configuration.h"
#include "server/well_known_headers.h"

#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"

namespace Nighthawk {
namespace Server {

HttpTimeTrackingFilterConfig::HttpTimeTrackingFilterConfig(
nighthawk::server::ResponseOptions proto_config)
: server_config_(std::move(proto_config)),
stopwatch_(std::make_unique<ThreadSafeMontonicTimeStopwatch>()) {}

uint64_t
HttpTimeTrackingFilterConfig::getElapsedNanosSinceLastRequest(Envoy::TimeSource& time_source) {
return stopwatch_->getElapsedNsAndReset(time_source);
}

HttpTimeTrackingFilter::HttpTimeTrackingFilter(HttpTimeTrackingFilterConfigSharedPtr config)
: config_(std::move(config)) {}

Envoy::Http::FilterHeadersStatus
HttpTimeTrackingFilter::decodeHeaders(Envoy::Http::RequestHeaderMap& headers, bool /*end_stream*/) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two questions here, both likely out of ignorance.

  1. Is it necessary to document that this anonymous argument is end_stream here?

  2. Is it a problem that our pass through filter here is sometimes throwing an error, rather than passing through?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

My 2p:

  1. I was thinking that this doesn't hurt, and may avoid a future reader having to look it up?
  2. For context: we derive from PassThroughFilter it as it conveniently stubs all the overrides precisely like we need, allowing us to override and focus on just the virtual methods of the interface that we are interested in. Maybe this deserves a code-level comment, wdyt? By throwing an error, do you mean that it replies with a 500 when it doesn't understand the configuration? Could you elaborate on the nature of the potential problem you would like to rule out?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. Sounds good. I was going back and forth on whether it was helpful. Decided to raise the question to hear your opinion.
  2. I did mean reply with a 500, sorry for being unclear. I think all of that makes sense. Just wasn't sure if we were breaking some sort of envoy contract. I had looked up PassThroughFilter and it specifies that it always returns Continue. I wanted to make sure that we were using this as a convenience and it was okay to break that rule, rather than it being a contract for the class that is relied upon

base_config_ = config_->server_config();
const auto* request_config_header = headers.get(TestServer::HeaderNames::get().TestServerConfig);
if (request_config_header) {
json_merge_error_ = !Configuration::mergeJsonConfig(
request_config_header->value().getStringView(), base_config_, error_message_);
if (json_merge_error_) {
decoder_callbacks_->sendLocalReply(
static_cast<Envoy::Http::Code>(500),
fmt::format("time-tracking didn't understand the request: {}", error_message_), nullptr,
absl::nullopt, "");
return Envoy::Http::FilterHeadersStatus::StopIteration;
}
}
return Envoy::Http::FilterHeadersStatus::Continue;
}

Envoy::Http::FilterHeadersStatus
HttpTimeTrackingFilter::encodeHeaders(Envoy::Http::ResponseHeaderMap& response_headers, bool) {
if (!json_merge_error_) {
const std::string previous_request_delta_in_response_header =
base_config_.emit_previous_request_delta_in_response_header();
if (!previous_request_delta_in_response_header.empty() && last_request_delta_ns_ > 0) {
response_headers.appendCopy(
Envoy::Http::LowerCaseString(previous_request_delta_in_response_header),
absl::StrCat(last_request_delta_ns_));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should this be SimpleAToi? I think you're trying to use StrCat here just for int conversion to an int

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Well, we're converting an uint64_t to a string here, and what made me think absl::StrCat was the right way to do it was a comment over at absl's number.h:

// This package contains functions for converting strings to numbers. For
--
  | // converting numbers to strings, use `StrCat()` or `StrAppend()` in str_cat.h,
  | // which automatically detect and convert most number values appropriately.

I do agree though, that I suspect that if I would be at the other end of this review, the same thing would have popped up in my mind. Maybe we should define a shorthand that does look more intuitive in the case where we're converting a single int to string, otoh I'm not sure it's worth it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oops got that backward. My bad. This probably doesn't matter unless we are worrying about very high performance here, but I think StrCat might be a heavy hand for converting one int to a string. It's optimized for concatenating strings and ints together efficiently. Happy to leave it here, and agree that it's not worth creating a helper function.

}
}
return Envoy::Http::FilterHeadersStatus::Continue;
}

void HttpTimeTrackingFilter::setDecoderFilterCallbacks(
Envoy::Http::StreamDecoderFilterCallbacks& callbacks) {
Envoy::Http::PassThroughFilter::setDecoderFilterCallbacks(callbacks);
last_request_delta_ns_ =
config_->getElapsedNanosSinceLastRequest(callbacks.dispatcher().timeSource());
}

} // namespace Server
} // namespace Nighthawk
Loading