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

Add DTRACE points to measure request timings. #11245

Merged
merged 18 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
devel
-----

* Add DTRACE points to track a request through the infrastructure.

* Agency ttl bug fix

* Added the SNI feature for TLS. This means that one can configure multiple
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,12 @@ if (STATIC_EXECUTABLES)
endif ()
endif()

# enable dtrace
option(USE_DTRACE "enable dtrace probes" OFF)
if (USE_DTRACE)
add_definitions("-DUSE_DTRACE=1")
endif ()

# enable enterprise features
set(ENTERPRISE_INCLUDE_DIR "enterprise")
option(USE_ENTERPRISE "enable enterprise build" OFF)
Expand Down
19 changes: 18 additions & 1 deletion arangod/GeneralServer/CommTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
#include "Basics/HybridLogicalClock.h"
#include "Basics/StaticStrings.h"
#include "Basics/compile-time-strlen.h"
#ifdef USE_DTRACE
#include "Basics/sdt.h"
#endif
#include "Cluster/ServerState.h"
#include "GeneralServer/AsyncJobManager.h"
#include "GeneralServer/AuthenticationFeature.h"
Expand Down Expand Up @@ -150,6 +153,11 @@ bool resolveRequestContext(GeneralRequest& req) {

CommTask::Flow CommTask::prepareExecution(auth::TokenCache::Entry const& authToken,
GeneralRequest& req) {

#ifdef USE_DTRACE
Copy link
Contributor

Choose a reason for hiding this comment

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

why DTRACE_PROBE1 not just a noop, instead of wrapping everything in #ifdef

Copy link
Member Author

Choose a reason for hiding this comment

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

There are 74 #define statements in lib/Basics/sdt.h. Yes, so far I am using only two of them. But I think it is impractical to define them all as empty macros if USE_DTRACE is set to 0. I would prefer to leave it as it is, but it is an easy change to define those that we actually use as empty macros for now, if you strongly prefer this. I have no strong feelings.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would also prefer having just one file to be included wherever tracing is needed:
lib/Basics/dtrace-wrapper.h

And this file could contain:

#ifndef ARANGODB_DTRACE_WRAPPER_H
#define ARANGODB_DTRACE_WRAPPER_H 1

#if USE_DTRACE
#include "Basics/sdt.h"
#else 
#define DTRACE_PROBE1(...) do { } while (0);
#define DTRACE_PROBE2(...) do { } while (0);
#endif 

#endif 

That would allow us to have everywhere managed in a single place, and keep the changes to the code minimal.

Copy link
Member Author

Choose a reason for hiding this comment

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

I like this approach.

DTRACE_PROBE1(arangod, CommTaskPrepareExecution, this);
#endif

// Step 1: In the shutdown phase we simply return 503:
if (_server.server().isStopping()) {
addErrorResponse(ResponseCode::SERVICE_UNAVAILABLE, req.contentTypeResponse(),
Expand Down Expand Up @@ -324,7 +332,11 @@ void CommTask::finishExecution(GeneralResponse& res, std::string const& origin)

void CommTask::executeRequest(std::unique_ptr<GeneralRequest> request,
std::unique_ptr<GeneralResponse> response) {


#ifdef USE_DTRACE
DTRACE_PROBE1(arangod, CommTaskExecuteRequest, this);
#endif

response->setContentTypeRequested(request->contentTypeResponse());
response->setGenerateBody(request->requestType() != RequestType::HEAD);

Expand Down Expand Up @@ -516,6 +528,11 @@ void CommTask::addErrorResponse(rest::ResponseCode code,
// and scheduled later when the number of used threads decreases

bool CommTask::handleRequestSync(std::shared_ptr<RestHandler> handler) {

#ifdef USE_DTRACE
DTRACE_PROBE2(arangod, CommTaskHandleRequestSync, this, handler.get());
#endif

RequestStatistics::SET_QUEUE_START(handler->statistics(), SchedulerFeature::SCHEDULER->queueStatistics()._queued);

RequestLane lane = handler->getRequestLane();
Expand Down
46 changes: 45 additions & 1 deletion arangod/GeneralServer/H2CommTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include "Basics/Exceptions.h"
#include "Basics/ScopeGuard.h"
#include "Basics/asio_ns.h"
#ifdef USE_DTRACE
#include "Basics/sdt.h"
#endif
#include "Cluster/ServerState.h"
#include "GeneralServer/GeneralServer.h"
#include "GeneralServer/GeneralServerFeature.h"
Expand Down Expand Up @@ -389,8 +392,20 @@ bool H2CommTask<T>::readCallback(asio_ns::error_code ec) {
return true; // continue read lopp
}

#ifdef USE_DTRACE
// Moved out to avoid duplication by templates.
static void __attribute__ ((noinline)) DTraceH2CommTaskProcessStream(size_t th) {
DTRACE_PROBE1(arangod, H2CommTaskProcessStream, th);
}
#endif

template <SocketType T>
void H2CommTask<T>::processStream(H2CommTask<T>::Stream* stream) {

#ifdef USE_DTRACE
DTraceH2CommTaskProcessStream((size_t) this);
#endif

TRI_ASSERT(stream);

std::unique_ptr<HttpRequest> req = std::move(stream->request);
Expand Down Expand Up @@ -463,10 +478,21 @@ bool expectResponseBody(int status_code) {
}
} // namespace

#ifdef USE_DTRACE
// Moved out to avoid duplication by templates.
static void __attribute__ ((noinline)) DTraceH2CommTaskSendResponse(size_t th) {
DTRACE_PROBE1(arangod, H2CommTaskSendResponse, th);
}
#endif

template <SocketType T>
void H2CommTask<T>::sendResponse(std::unique_ptr<GeneralResponse> res,
RequestStatistics* stat) {


#ifdef USE_DTRACE
DTraceH2CommTaskSendResponse((size_t) this);
#endif

// TODO the statistics are total bogus here
double const totalTime = RequestStatistics::ELAPSED_SINCE_READ_START(stat);
if (stat) {
Expand Down Expand Up @@ -630,6 +656,16 @@ void H2CommTask<T>::queueHttp2Responses() {
}
}

#ifdef USE_DTRACE
// Moved out to avoid duplication by templates.
static void __attribute__ ((noinline)) DTraceH2CommTaskBeforeAsyncWrite(size_t th) {
DTRACE_PROBE1(arangod, H2CommTaskBeforeAsyncWrite, th);
}
static void __attribute__ ((noinline)) DTraceH2CommTaskAfterAsyncWrite(size_t th) {
DTRACE_PROBE1(arangod, H2CommTaskAfterAsyncWrite, th);
}
#endif

// called on IO context thread
template <SocketType T>
void H2CommTask<T>::doWrite() {
Expand Down Expand Up @@ -685,6 +721,10 @@ void H2CommTask<T>::doWrite() {
return;
}

#ifdef USE_DTRACE
DTraceH2CommTaskBeforeAsyncWrite((size_t) this);
#endif

asio_ns::async_write(this->_protocol->socket, outBuffers,
[self = this->shared_from_this()](const asio_ns::error_code& ec,
std::size_t nwrite) {
Expand All @@ -695,6 +735,10 @@ void H2CommTask<T>::doWrite() {
return;
}

#ifdef USE_DTRACE
DTraceH2CommTaskAfterAsyncWrite((size_t) self.get());
#endif

me.doWrite();
});
}
Expand Down
47 changes: 47 additions & 0 deletions arangod/GeneralServer/HttpCommTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@

#include "Basics/ScopeGuard.h"
#include "Basics/asio_ns.h"
#ifdef USE_DTRACE
#include "Basics/sdt.h"
#endif
#include "Cluster/ServerState.h"
#include "GeneralServer/GeneralServer.h"
#include "GeneralServer/GeneralServerFeature.h"
Expand Down Expand Up @@ -336,8 +339,20 @@ void HttpCommTask<T>::checkVSTPrefix() {
asio_ns::transfer_at_least(11), std::move(cb));
}

#ifdef USE_DTRACE
// Moved here to prevent multiplicity by template
static void __attribute__ ((noinline)) DTraceHttpCommTaskProcessRequest(size_t th) {
DTRACE_PROBE1(arangod, HttpCommTaskProcessRequest, th);
}
#endif

template <SocketType T>
void HttpCommTask<T>::processRequest() {

#ifdef USE_DTRACE
DTraceHttpCommTaskProcessRequest((size_t) this);
#endif

TRI_ASSERT(_request);
this->_protocol->timer.cancel();

Expand Down Expand Up @@ -414,9 +429,21 @@ void HttpCommTask<T>::processRequest() {
this->executeRequest(std::move(_request), std::move(resp));
}

#ifdef USE_DTRACE
// Moved here to prevent multiplicity by template
static void __attribute__ ((noinline)) DTraceHttpCommTaskSendResponse(size_t th) {
DTRACE_PROBE1(arangod, HttpCommTaskSendResponse, th);
}
#endif

template <SocketType T>
void HttpCommTask<T>::sendResponse(std::unique_ptr<GeneralResponse> baseRes,
RequestStatistics* stat) {

#ifdef USE_DTRACE
DTraceHttpCommTaskSendResponse((size_t) this);
#endif

if (this->_stopped.load(std::memory_order_acquire)) {
return;
}
Expand Down Expand Up @@ -534,9 +561,24 @@ void HttpCommTask<T>::sendResponse(std::unique_ptr<GeneralResponse> baseRes,
});
}

#ifdef USE_DTRACE
// Moved here to prevent multiplicity by template
static void __attribute__ ((noinline)) DTraceHttpCommTaskWriteResponse(size_t th) {
DTRACE_PROBE1(arangod, HttpCommTaskWriteResponse, th);
}
static void __attribute__ ((noinline)) DTraceHttpCommTaskResponseWritten(size_t th) {
DTRACE_PROBE1(arangod, HttpCommTaskResponseWritten, th);
}
#endif

// called on IO context thread
template <SocketType T>
void HttpCommTask<T>::writeResponse(RequestStatistics* stat) {

#ifdef USE_DTRACE
DTraceHttpCommTaskWriteResponse((size_t) this);
#endif

TRI_ASSERT(!_header.empty());

RequestStatistics::SET_WRITE_START(stat);
Expand All @@ -551,6 +593,11 @@ void HttpCommTask<T>::writeResponse(RequestStatistics* stat) {
asio_ns::async_write(this->_protocol->socket, buffers,
[self = this->shared_from_this(),
stat](asio_ns::error_code ec, size_t nwrite) {

#ifdef USE_DTRACE
DTraceHttpCommTaskResponseWritten((size_t) self.get());
#endif

auto* thisPtr = static_cast<HttpCommTask<T>*>(self.get());
RequestStatistics::SET_WRITE_END(stat);
RequestStatistics::ADD_SENT_BYTES(stat, nwrite);
Expand Down
8 changes: 8 additions & 0 deletions arangod/GeneralServer/RestHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/RecursiveLocker.h"
#include "Basics/StringUtils.h"
#ifdef USE_DTRACE
#include "Basics/sdt.h"
#endif
#include "Cluster/ClusterFeature.h"
#include "Cluster/ClusterInfo.h"
#include "Cluster/ClusterMethods.h"
Expand Down Expand Up @@ -398,6 +401,11 @@ bool RestHandler::wakeupHandler() {
}

void RestHandler::executeEngine(bool isContinue) {

#ifdef USE_DTRACE
DTRACE_PROBE1(arangod, RestHandlerExecuteEngine, this);
#endif

ExecContext* exec = static_cast<ExecContext*>(_request->requestContext());
ExecContextScope scope(exec);

Expand Down
12 changes: 10 additions & 2 deletions arangod/GeneralServer/SslServerFeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ SslServerFeature::SslServerFeature(application_features::ApplicationServer& serv
_sslProtocol(TLS_GENERIC),
_sslOptions(asio_ns::ssl::context::default_workarounds |
asio_ns::ssl::context::single_dh_use),
_ecdhCurve("prime256v1") {
_ecdhCurve("prime256v1"),
_allowHttpProtocolNegotiation(true) {
setOptional(true);
startsAfter<application_features::AqlFeaturePhase>();
}
Expand Down Expand Up @@ -116,6 +117,11 @@ void SslServerFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
"--ssl.ecdh-curve",
"SSL ECDH Curve, see the output of \"openssl ecparam -list_curves\"",
new StringParameter(&_ecdhCurve));

options->addOption(
"--ssl.allow-http-protocol-negotiation",
"Allows that the TLS handshake negotiates the HTTP protocol version",
new BooleanParameter(&_allowHttpProtocolNegotiation));
}

void SslServerFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
Expand Down Expand Up @@ -344,7 +350,9 @@ asio_ns::ssl::context SslServerFeature::createSslContextInternal(

sslContext.set_verify_mode(SSL_VERIFY_NONE);

SSL_CTX_set_alpn_select_cb(sslContext.native_handle(), alpn_select_proto_cb, NULL);
if (_allowHttpProtocolNegotiation) {
SSL_CTX_set_alpn_select_cb(sslContext.native_handle(), alpn_select_proto_cb, NULL);
}

return sslContext;
} catch (std::exception const& ex) {
Expand Down
1 change: 1 addition & 0 deletions arangod/GeneralServer/SslServerFeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class SslServerFeature : public application_features::ApplicationFeature {
uint64_t _sslProtocol;
uint64_t _sslOptions;
std::string _ecdhCurve;
bool _allowHttpProtocolNegotiation;

private:
asio_ns::ssl::context createSslContextInternal(std::string keyfileName,
Expand Down
Loading