-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Issue 596: Add profiler path to configuration #603
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
Changes from 4 commits
6a3b748
2059a8b
45eeba9
f9968bb
9e3ae3d
a92b095
0aa7ac9
8dd2764
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 |
|---|---|---|
|
|
@@ -899,6 +899,7 @@ const std::string Json::Schema::TOP_LEVEL_CONFIG_SCHEMA(R"EOF( | |
| "type" : "object", | ||
| "properties" : { | ||
| "access_log_path" : {"type" : "string"}, | ||
| "profiler_path" : {"type" : "string"}, | ||
|
Member
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. Ditto etc.
Member
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. When you change
Member
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. You can also defer the |
||
| "address" : {"type" : "string"} | ||
| }, | ||
| "required" : ["access_log_path", "address"], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,7 @@ class Cpu { | |
| /** | ||
| * Start the profiler and write to the specified path. | ||
| */ | ||
| static void startProfiler(const std::string& output_path); | ||
| static bool startProfiler(const std::string& output_path); | ||
|
Member
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. Add some return value documentation. |
||
|
|
||
| /** | ||
| * Stop the profiler. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -163,7 +163,11 @@ Http::Code AdminImpl::handlerCpuProfiler(const std::string& url, Buffer::Instanc | |
|
|
||
| bool enable = query_params.begin()->second == "y"; | ||
| if (enable && !Profiler::Cpu::profilerEnabled()) { | ||
| Profiler::Cpu::startProfiler("/var/log/envoy/envoy.prof"); | ||
| if (!Profiler::Cpu::startProfiler(profiler_path_)) { | ||
| response.add("?enable=<y|n>\n"); | ||
|
Member
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. I think a more meaningful response would indicate there was a failure to start the profiler. |
||
| return Http::Code::BadRequest; | ||
|
Member
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. This returns a 400. I think it's not actually a bad client formed request, it's an internal server error, so you want to return a 500. |
||
| } | ||
|
|
||
| } else if (!enable && Profiler::Cpu::profilerEnabled()) { | ||
| Profiler::Cpu::stopProfiler(); | ||
| } | ||
|
|
@@ -295,8 +299,8 @@ void AdminFilter::onComplete() { | |
| AdminImpl::NullRouteConfigProvider::NullRouteConfigProvider() | ||
| : config_(new Router::NullConfigImpl()) {} | ||
|
|
||
| AdminImpl::AdminImpl(const std::string& access_log_path, Network::Address::InstancePtr address, | ||
| Server::Instance& server) | ||
| AdminImpl::AdminImpl(const std::string& access_log_path, const std::string& profiler_path, | ||
| Network::Address::InstancePtr address, Server::Instance& server) | ||
| : server_(server), socket_(new Network::TcpListenSocket(address, true)), | ||
| stats_(Http::ConnectionManagerImpl::generateStats("http.admin.", server_.stats())), | ||
| tracing_stats_(Http::ConnectionManagerImpl::generateTracingStats("http.admin.tracing.", | ||
|
|
@@ -317,7 +321,7 @@ AdminImpl::AdminImpl(const std::string& access_log_path, Network::Address::Insta | |
| {"/server_info", "print server version/status information", | ||
| MAKE_HANDLER(handlerServerInfo)}, | ||
| {"/stats", "print server stats", MAKE_HANDLER(handlerStats)}} { | ||
|
|
||
|
Member
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: unrelated line deletion? |
||
| profiler_path_ = profiler_path; | ||
|
Member
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. It might be nicer to initialize this in the above constructor member initialization list, i.e.
|
||
| access_logs_.emplace_back(new Http::AccessLog::InstanceImpl( | ||
| access_log_path, {}, Http::AccessLog::AccessLogFormatUtils::defaultAccessLogFormatter(), | ||
| server.accessLogManager())); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -105,10 +105,12 @@ TEST_F(IntegrationTest, Admin) { | |
| EXPECT_TRUE(response->complete()); | ||
| EXPECT_STREQ("400", response->headers().Status()->value().c_str()); | ||
|
|
||
| // TO DO: Change to expect 200 when profiler path is a configurable parameter | ||
|
Member
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. The convention used in Envoy is |
||
| // via the Envoy config JSON. Currently call returns 400 due to inaccessable profiler path | ||
| response = IntegrationUtil::makeSingleRequest(ADMIN_PORT, "GET", "/cpuprofiler?enable=y", "", | ||
| Http::CodecClient::Type::HTTP1); | ||
| EXPECT_TRUE(response->complete()); | ||
| EXPECT_STREQ("200", response->headers().Status()->value().c_str()); | ||
| EXPECT_STREQ("400", response->headers().Status()->value().c_str()); | ||
|
|
||
| response = IntegrationUtil::makeSingleRequest(ADMIN_PORT, "GET", "/cpuprofiler?enable=n", "", | ||
| Http::CodecClient::Type::HTTP1); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| #include "common/http/message_impl.h" | ||
| #include "common/profiler/profiler.h" | ||
| #include "server/http/admin.h" | ||
|
|
||
| #include "test/mocks/server/mocks.h" | ||
|
|
@@ -13,13 +14,17 @@ class AdminFilterTest : public testing::Test { | |
| public: | ||
| // TODO(mattklein123): Switch to mocks and do not bind to a real port. | ||
| AdminFilterTest() | ||
| : admin_("/dev/null", Network::Utility::resolveUrl("tcp://127.0.0.1:9002"), server_), | ||
| : admin_("/dev/null", "/tmp/envoy.prof", Network::Utility::resolveUrl("tcp://127.0.0.1:9002"), | ||
|
Member
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. This isn't a fault in this PR (it's a widespread issue in Envoy today), but using
Member
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. I've filed #605 to track this work. |
||
| server_), | ||
| admin_bad_profiler_path_("/dev/null", "/var/log/envoy/envoy.prof", | ||
| Network::Utility::resolveUrl("tcp://127.0.0.1:9002"), server_), | ||
| filter_(admin_), request_headers_{{":path", "/"}} { | ||
| filter_.setDecoderFilterCallbacks(callbacks_); | ||
| } | ||
|
|
||
| NiceMock<MockInstance> server_; | ||
| AdminImpl admin_; | ||
| AdminImpl admin_bad_profiler_path_; | ||
|
Member
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. I don't think this needs to be a member of |
||
| AdminFilter filter_; | ||
| NiceMock<Http::MockStreamDecoderFilterCallbacks> callbacks_; | ||
| Http::TestHeaderMapImpl request_headers_; | ||
|
|
@@ -45,4 +50,18 @@ TEST_F(AdminFilterTest, Trailers) { | |
| filter_.decodeTrailers(request_headers_); | ||
| } | ||
|
|
||
| TEST_F(AdminFilterTest, AdminProfiler) { | ||
| Buffer::OwnedImpl data; | ||
| admin_.runCallback("/cpuprofiler?enable=y", data); | ||
| EXPECT_TRUE(Profiler::Cpu::profilerEnabled()); | ||
| admin_.runCallback("/cpuprofiler?enable=n", data); | ||
| EXPECT_FALSE(Profiler::Cpu::profilerEnabled()); | ||
| } | ||
|
|
||
| TEST_F(AdminFilterTest, AdminBadProfiler) { | ||
| Buffer::OwnedImpl data; | ||
| admin_bad_profiler_path_.runCallback("/cpuprofiler?enable=y", data); | ||
| EXPECT_FALSE(Profiler::Cpu::profilerEnabled()); | ||
| } | ||
|
|
||
| } // namespace Server | ||
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.
Actually, it might be more semantically correct to call this profilePath (and similar renames elsewhere). It's where the profile is emitted, not the profiler itself. The comment might then be "@return const std::string& profiler output path."