From ac689fc725efc3e6628c5c1d49cd21154f477c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Neunh=C3=B6ffer?= Date: Thu, 24 Oct 2019 12:11:51 +0200 Subject: [PATCH] Allow to ignore superuser traffic with an option. (#10289) * Allow to ignore superuser traffic with an option. Also: Fix some accounting bugs. * CHANGELOG. * Implement separate accounting for superuser and user traffic. * Fix VST case with no authentication. * Add description of new user-only traffic statistics. * Add figures for user traffic. * Simplify forwarding accounting. * Remove brackets in metrics names. * Finalize naming of metrics. --- CHANGELOG | 3 + arangod/GeneralServer/GeneralCommTask.cpp | 5 +- arangod/GeneralServer/HttpCommTask.cpp | 5 + arangod/GeneralServer/VstCommTask.cpp | 19 +++- .../RestAdminStatisticsHandler.cpp | 7 +- arangod/Statistics/Descriptions.cpp | 63 ++++++++++++- arangod/Statistics/Descriptions.h | 6 +- arangod/Statistics/RequestStatistics.cpp | 94 ++++++++++++++----- arangod/Statistics/RequestStatistics.h | 17 +++- arangod/Statistics/StatisticsFeature.cpp | 6 ++ arangod/Statistics/StatisticsFeature.h | 6 ++ arangod/Statistics/StatisticsWorker.cpp | 2 +- arangod/Statistics/figures.h | 13 +++ arangod/V8Server/v8-statistics.cpp | 2 +- lib/Rest/VstMessage.h | 8 ++ 15 files changed, 221 insertions(+), 35 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7bb5fd7589..01f5db65a1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ v3.5.2 (XXXX-XX-XX) ------------------- +* Separately account for superuser and user request traffic. This is + needed for Oasis. + * Fixed issue #10270: Query: Expecting type Array or Object (while executing). * Fix a problem with AQL constrained sort in the cluster, which might abort diff --git a/arangod/GeneralServer/GeneralCommTask.cpp b/arangod/GeneralServer/GeneralCommTask.cpp index be80e70f8b..2ebdfe67c2 100644 --- a/arangod/GeneralServer/GeneralCommTask.cpp +++ b/arangod/GeneralServer/GeneralCommTask.cpp @@ -320,7 +320,10 @@ void GeneralCommTask::executeRequest(std::unique_ptr&& request, // forward to correct server if necessary bool forwarded = handler->forwardRequest(); if (forwarded) { - addResponse(*handler->response(), handler->stealStatistics()); + RequestStatistics::SET_SUPERUSER(statistics(messageId)); + // At this point the handler does not yet have the statistics objects, + // so we have to take it from the CommTask. + addResponse(*handler->response(), stealStatistics(messageId)); return; } diff --git a/arangod/GeneralServer/HttpCommTask.cpp b/arangod/GeneralServer/HttpCommTask.cpp index 18d391ee89..f51078b83b 100644 --- a/arangod/GeneralServer/HttpCommTask.cpp +++ b/arangod/GeneralServer/HttpCommTask.cpp @@ -587,6 +587,11 @@ bool HttpCommTask::processRead(double startTime) { // authenticated if (authResult != rest::ResponseCode::SERVER_ERROR) { + // We want to separate superuser token traffic: + if (_incompleteRequest->authenticated() && + _incompleteRequest->user().empty()) { + RequestStatistics::SET_SUPERUSER(stat); + } // prepare execution will send an error message RequestFlow cont = prepareExecution(*_incompleteRequest.get()); if (cont == RequestFlow::Continue) { diff --git a/arangod/GeneralServer/VstCommTask.cpp b/arangod/GeneralServer/VstCommTask.cpp index 165a6da0ee..8cd4971646 100644 --- a/arangod/GeneralServer/VstCommTask.cpp +++ b/arangod/GeneralServer/VstCommTask.cpp @@ -325,8 +325,6 @@ bool VstCommTask::processRead(double startTime) { RequestStatistics::SET_READ_START(stat, startTime); } - RequestStatistics::SET_READ_END(statistics(chunkHeader._messageID)); - if (chunkHeader._isFirst && chunkHeader._chunk == 1) { // CASE 1: message is in one chunk if (!getMessageFromSingleChunk(chunkHeader, message, doExecute, vpackBegin, chunkEnd)) { @@ -349,6 +347,12 @@ bool VstCommTask::processRead(double startTime) { } if (doExecute) { + // A message is complete! Now we need to do the accounting, first let's + // set the "read-end time": + RequestStatistics* stat = statistics(message.id()); + RequestStatistics::SET_READ_END(stat); + RequestStatistics::ADD_RECEIVED_BYTES(stat, message.totalSize()); + VPackSlice header = message.header(); if (Logger::logRequestParameters()) { @@ -373,6 +377,11 @@ bool VstCommTask::processRead(double startTime) { // handle request types if (type == 1000) { // auth handleAuthHeader(header, chunkHeader._messageID); + // Separate superuser traffic: + if (_authMethod != AuthenticationMethod::NONE && _authorized && + _authToken._username.empty()) { + RequestStatistics::SET_SUPERUSER(stat); + } } else if (type == 1) { // request // the handler will take ownership of this pointer @@ -386,6 +395,12 @@ bool VstCommTask::processRead(double startTime) { _auth->userManager()->refreshUser(_authToken._username); } + // Separate superuser traffic: + if (_authMethod != AuthenticationMethod::NONE && _authorized && + _authToken._username.empty()) { + RequestStatistics::SET_SUPERUSER(stat); + } + RequestFlow cont = prepareExecution(*req.get()); if (cont == RequestFlow::Continue) { diff --git a/arangod/RestHandler/RestAdminStatisticsHandler.cpp b/arangod/RestHandler/RestAdminStatisticsHandler.cpp index 3702de9018..b36d046bf9 100644 --- a/arangod/RestHandler/RestAdminStatisticsHandler.cpp +++ b/arangod/RestHandler/RestAdminStatisticsHandler.cpp @@ -23,6 +23,7 @@ #include "RestAdminStatisticsHandler.h" #include "GeneralServer/ServerSecurityFeature.h" #include "Statistics/Descriptions.h" +#include "Statistics/RequestStatistics.h" #include "Statistics/StatisticsFeature.h" using namespace arangodb; @@ -82,9 +83,13 @@ void RestAdminStatisticsHandler::getStatistics() { tmp.close(); // system tmp.add("client", VPackValue(VPackValueType::Object, true)); - desc->clientStatistics(tmp); + desc->clientStatistics(tmp, RequestStatistics::Source::ALL); tmp.close(); // client + tmp.add("clientUser", VPackValue(VPackValueType::Object, true)); + desc->clientStatistics(tmp, RequestStatistics::Source::USER); + tmp.close(); // clientUser + tmp.add("http", VPackValue(VPackValueType::Object, true)); desc->httpStatistics(tmp); tmp.close(); // http diff --git a/arangod/Statistics/Descriptions.cpp b/arangod/Statistics/Descriptions.cpp index bf9508acec..854b25c1c9 100644 --- a/arangod/Statistics/Descriptions.cpp +++ b/arangod/Statistics/Descriptions.cpp @@ -41,6 +41,8 @@ std::string stats::fromGroupType(stats::GroupType gt) { return "system"; case stats::GroupType::Client: return "client"; + case stats::GroupType::ClientUser: + return "clientUser"; case stats::GroupType::Http: return "http"; case stats::GroupType::Vst: @@ -113,6 +115,9 @@ stats::Descriptions::Descriptions() _groups.emplace_back(Group{stats::GroupType::Client, "Client Connection Statistics", "Statistics about the connections."}); + _groups.emplace_back(Group{stats::GroupType::ClientUser, + "Client User Connection Statistics", + "Statistics about the connections, only user traffic (ignoring superuser JWT traffic)."}); _groups.emplace_back(Group{stats::GroupType::Http, "HTTP Request Statistics", "Statistics about the HTTP requests."}); _groups.emplace_back(Group{stats::GroupType::Server, "Server Statistics", @@ -248,6 +253,60 @@ stats::Descriptions::Descriptions() // cuts: internal.connectionTimeDistribution, stats::Unit::Seconds, _connectionTimeCuts}); + // Only user traffic: + + _figures.emplace_back( + Figure{stats::GroupType::ClientUser, + "httpConnections", + "Client Connections", + "The number of connections that are currently open (only user traffic).", + stats::FigureType::Current, + stats::Unit::Number, + {}}); + + _figures.emplace_back( + Figure{stats::GroupType::ClientUser, "totalTime", "Total Time", + "Total time needed to answer a request (only user traffic).", + stats::FigureType::Distribution, + // cuts: internal.requestTimeDistribution, + stats::Unit::Seconds, _requestTimeCuts}); + + _figures.emplace_back( + Figure{stats::GroupType::ClientUser, "requestTime", "Request Time", + "Request time needed to answer a request (only user traffic).", + stats::FigureType::Distribution, + // cuts: internal.requestTimeDistribution, + stats::Unit::Seconds, _requestTimeCuts}); + + _figures.emplace_back( + Figure{stats::GroupType::ClientUser, "queueTime", "Queue Time", + "Queue time needed to answer a request (only user traffic).", + stats::FigureType::Distribution, + // cuts: internal.requestTimeDistribution, + stats::Unit::Seconds, _requestTimeCuts}); + + _figures.emplace_back(Figure{stats::GroupType::ClientUser, "bytesSent", + "Bytes Sent", + "Bytes sents for a request (only user traffic).", + stats::FigureType::Distribution, + // cuts: internal.bytesSentDistribution, + stats::Unit::Bytes, _bytesSendCuts}); + + _figures.emplace_back(Figure{stats::GroupType::ClientUser, "bytesReceived", + "Bytes Received", + "Bytes received for a request (only user traffic).", + stats::FigureType::Distribution, + // cuts: internal.bytesReceivedDistribution, + stats::Unit::Bytes, _bytesReceivedCuts}); + + _figures.emplace_back( + Figure{stats::GroupType::ClientUser, "connectionTime", + "Connection Time", + "Total connection time of a client (only user traffic).", + stats::FigureType::Distribution, + // cuts: internal.connectionTimeDistribution, + stats::Unit::Seconds, _connectionTimeCuts}); + _figures.emplace_back(Figure{stats::GroupType::Http, "requestsTotal", "Total requests", @@ -412,7 +471,7 @@ static void FillDistribution(VPackBuilder& b, std::string const& name, b.close(); } -void stats::Descriptions::clientStatistics(velocypack::Builder& b) const { +void stats::Descriptions::clientStatistics(velocypack::Builder& b, RequestStatistics::Source source) const { basics::StatisticsCounter httpConnections; basics::StatisticsCounter totalRequests; std::array methodRequests; @@ -433,7 +492,7 @@ void stats::Descriptions::clientStatistics(velocypack::Builder& b) const { basics::StatisticsDistribution bytesSent; basics::StatisticsDistribution bytesReceived; - RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived); + RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived, source); FillDistribution(b, "totalTime", totalTime); FillDistribution(b, "requestTime", requestTime); diff --git a/arangod/Statistics/Descriptions.h b/arangod/Statistics/Descriptions.h index 9739892832..174f13d64e 100644 --- a/arangod/Statistics/Descriptions.h +++ b/arangod/Statistics/Descriptions.h @@ -28,10 +28,12 @@ #include #include +#include "Statistics/RequestStatistics.h" + namespace arangodb { namespace stats { -enum class GroupType { System, Client, Http, Vst, Server }; +enum class GroupType { System, Client, ClientUser, Http, Vst, Server }; std::string fromGroupType(stats::GroupType); @@ -75,7 +77,7 @@ class Descriptions final { std::vector const& figures() const { return _figures; } void serverStatistics(velocypack::Builder&) const; - void clientStatistics(velocypack::Builder&) const; + void clientStatistics(velocypack::Builder&, RequestStatistics::Source source) const; void httpStatistics(velocypack::Builder&) const; void processStatistics(velocypack::Builder&) const; diff --git a/arangod/Statistics/RequestStatistics.cpp b/arangod/Statistics/RequestStatistics.cpp index 66eeb9efe8..f2b7413c5f 100644 --- a/arangod/Statistics/RequestStatistics.cpp +++ b/arangod/Statistics/RequestStatistics.cpp @@ -124,26 +124,50 @@ void RequestStatistics::process(RequestStatistics* statistics) { totalTime = statistics->_writeEnd - statistics->_readStart; } - TRI_TotalTimeDistributionStatistics.addFigure(totalTime); + if (statistics->_superuser) { + TRI_TotalTimeDistributionStatistics.addFigure(totalTime); - double requestTime = statistics->_requestEnd - statistics->_requestStart; - TRI_RequestTimeDistributionStatistics.addFigure(requestTime); + double requestTime = statistics->_requestEnd - statistics->_requestStart; + TRI_RequestTimeDistributionStatistics.addFigure(requestTime); - double queueTime = 0.0; + double queueTime = 0.0; + + if (statistics->_queueStart != 0.0 && statistics->_queueEnd != 0.0) { + queueTime = statistics->_queueEnd - statistics->_queueStart; + TRI_QueueTimeDistributionStatistics.addFigure(queueTime); + } + + double ioTime = totalTime - requestTime - queueTime; + + if (ioTime >= 0.0) { + TRI_IoTimeDistributionStatistics.addFigure(ioTime); + } + + TRI_BytesSentDistributionStatistics.addFigure(statistics->_sentBytes); + TRI_BytesReceivedDistributionStatistics.addFigure(statistics->_receivedBytes); + } else { + TRI_TotalTimeDistributionStatisticsUser.addFigure(totalTime); + + double requestTime = statistics->_requestEnd - statistics->_requestStart; + TRI_RequestTimeDistributionStatisticsUser.addFigure(requestTime); + + double queueTime = 0.0; + + if (statistics->_queueStart != 0.0 && statistics->_queueEnd != 0.0) { + queueTime = statistics->_queueEnd - statistics->_queueStart; + TRI_QueueTimeDistributionStatisticsUser.addFigure(queueTime); + } + + double ioTime = totalTime - requestTime - queueTime; + + if (ioTime >= 0.0) { + TRI_IoTimeDistributionStatisticsUser.addFigure(ioTime); + } + + TRI_BytesSentDistributionStatisticsUser.addFigure(statistics->_sentBytes); + TRI_BytesReceivedDistributionStatisticsUser.addFigure(statistics->_receivedBytes); - if (statistics->_queueStart != 0.0 && statistics->_queueEnd != 0.0) { - queueTime = statistics->_queueEnd - statistics->_queueStart; - TRI_QueueTimeDistributionStatistics.addFigure(queueTime); } - - double ioTime = totalTime - requestTime - queueTime; - - if (ioTime >= 0.0) { - TRI_IoTimeDistributionStatistics.addFigure(ioTime); - } - - TRI_BytesSentDistributionStatistics.addFigure(statistics->_sentBytes); - TRI_BytesReceivedDistributionStatistics.addFigure(statistics->_receivedBytes); } } @@ -188,18 +212,36 @@ void RequestStatistics::fill(StatisticsDistribution& totalTime, StatisticsDistribution& requestTime, StatisticsDistribution& queueTime, StatisticsDistribution& ioTime, StatisticsDistribution& bytesSent, - StatisticsDistribution& bytesReceived) { + StatisticsDistribution& bytesReceived, + Source source) { if (!StatisticsFeature::enabled()) { // all the below objects may be deleted if we don't have statistics enabled return; } - totalTime = TRI_TotalTimeDistributionStatistics; - requestTime = TRI_RequestTimeDistributionStatistics; - queueTime = TRI_QueueTimeDistributionStatistics; - ioTime = TRI_IoTimeDistributionStatistics; - bytesSent = TRI_BytesSentDistributionStatistics; - bytesReceived = TRI_BytesReceivedDistributionStatistics; + if (source == Source::USER) { + totalTime = TRI_TotalTimeDistributionStatisticsUser; + requestTime = TRI_RequestTimeDistributionStatisticsUser; + queueTime = TRI_QueueTimeDistributionStatisticsUser; + ioTime = TRI_IoTimeDistributionStatisticsUser; + bytesSent = TRI_BytesSentDistributionStatisticsUser; + bytesReceived = TRI_BytesReceivedDistributionStatisticsUser; + } else { + totalTime = TRI_TotalTimeDistributionStatistics; + requestTime = TRI_RequestTimeDistributionStatistics; + queueTime = TRI_QueueTimeDistributionStatistics; + ioTime = TRI_IoTimeDistributionStatistics; + bytesSent = TRI_BytesSentDistributionStatistics; + bytesReceived = TRI_BytesReceivedDistributionStatistics; + } + if (source == Source::ALL) { + totalTime.add(TRI_TotalTimeDistributionStatisticsUser); + requestTime.add(TRI_RequestTimeDistributionStatisticsUser); + queueTime.add(TRI_QueueTimeDistributionStatisticsUser); + ioTime.add(TRI_IoTimeDistributionStatisticsUser); + bytesSent.add(TRI_BytesSentDistributionStatisticsUser); + bytesReceived.add(TRI_BytesReceivedDistributionStatisticsUser); + } } std::string RequestStatistics::timingsCsv() { @@ -231,7 +273,8 @@ std::string RequestStatistics::to_string() { << "_async " << _async << std::endl << "_tooLarge " << _tooLarge << std::endl << "_executeError " << _executeError << std::endl - << "_ignore " << _ignore << std::endl; + << "_ignore " << _ignore << std::endl + << "_superuser " << _superuser << std::endl; return ss.str(); } @@ -278,4 +321,7 @@ void RequestStatistics::trace_log() { LOG_TOPIC("31657", TRACE, Logger::REQUESTS) << std::boolalpha << std::setprecision(20) << "_ignore " << _ignore; + + LOG_TOPIC("31658", TRACE, Logger::REQUESTS) << std::boolalpha << std::setprecision(20) + << "_superuser " << _superuser; } diff --git a/arangod/Statistics/RequestStatistics.h b/arangod/Statistics/RequestStatistics.h index b43fdd7436..e76fe65d3d 100644 --- a/arangod/Statistics/RequestStatistics.h +++ b/arangod/Statistics/RequestStatistics.h @@ -144,14 +144,27 @@ class RequestStatistics { } } + static void SET_SUPERUSER(RequestStatistics* stat) { + if (stat != nullptr) { + stat->_superuser = true; + } + } + double requestStart() const { return _requestStart; } + enum Source { + USER, + SUPERUSER, + ALL + }; + static void fill(basics::StatisticsDistribution& totalTime, basics::StatisticsDistribution& requestTime, basics::StatisticsDistribution& queueTime, basics::StatisticsDistribution& ioTime, basics::StatisticsDistribution& bytesSent, - basics::StatisticsDistribution& bytesReceived); + basics::StatisticsDistribution& bytesReceived, + Source source); std::string timingsCsv(); std::string to_string(); @@ -189,6 +202,7 @@ class RequestStatistics { _ignore = false; _released = true; _inQueue = false; + _superuser = false; } double _readStart; // CommTask::processRead - read first byte of message @@ -213,6 +227,7 @@ class RequestStatistics { bool _ignore; bool _released; bool _inQueue; + bool _superuser; }; } // namespace arangodb diff --git a/arangod/Statistics/StatisticsFeature.cpp b/arangod/Statistics/StatisticsFeature.cpp index ebeabd24cf..227553c68c 100644 --- a/arangod/Statistics/StatisticsFeature.cpp +++ b/arangod/Statistics/StatisticsFeature.cpp @@ -70,6 +70,12 @@ StatisticsDistribution TRI_IoTimeDistributionStatistics(TRI_RequestTimeDistribut StatisticsDistribution TRI_QueueTimeDistributionStatistics(TRI_RequestTimeDistributionVectorStatistics); StatisticsDistribution TRI_RequestTimeDistributionStatistics(TRI_RequestTimeDistributionVectorStatistics); StatisticsDistribution TRI_TotalTimeDistributionStatistics(TRI_RequestTimeDistributionVectorStatistics); +StatisticsDistribution TRI_BytesReceivedDistributionStatisticsUser(TRI_BytesReceivedDistributionVectorStatistics); +StatisticsDistribution TRI_BytesSentDistributionStatisticsUser(TRI_BytesSentDistributionVectorStatistics); +StatisticsDistribution TRI_IoTimeDistributionStatisticsUser(TRI_RequestTimeDistributionVectorStatistics); +StatisticsDistribution TRI_QueueTimeDistributionStatisticsUser(TRI_RequestTimeDistributionVectorStatistics); +StatisticsDistribution TRI_RequestTimeDistributionStatisticsUser(TRI_RequestTimeDistributionVectorStatistics); +StatisticsDistribution TRI_TotalTimeDistributionStatisticsUser(TRI_RequestTimeDistributionVectorStatistics); } // namespace basics } // namespace arangodb diff --git a/arangod/Statistics/StatisticsFeature.h b/arangod/Statistics/StatisticsFeature.h index 2993f4a514..d6a4493353 100644 --- a/arangod/Statistics/StatisticsFeature.h +++ b/arangod/Statistics/StatisticsFeature.h @@ -56,6 +56,12 @@ extern StatisticsDistribution TRI_IoTimeDistributionStatistics; extern StatisticsDistribution TRI_QueueTimeDistributionStatistics; extern StatisticsDistribution TRI_RequestTimeDistributionStatistics; extern StatisticsDistribution TRI_TotalTimeDistributionStatistics; +extern StatisticsDistribution TRI_BytesReceivedDistributionStatisticsUser; +extern StatisticsDistribution TRI_BytesSentDistributionStatisticsUser; +extern StatisticsDistribution TRI_IoTimeDistributionStatisticsUser; +extern StatisticsDistribution TRI_QueueTimeDistributionStatisticsUser; +extern StatisticsDistribution TRI_RequestTimeDistributionStatisticsUser; +extern StatisticsDistribution TRI_TotalTimeDistributionStatisticsUser; } // namespace basics namespace stats { class Descriptions; diff --git a/arangod/Statistics/StatisticsWorker.cpp b/arangod/Statistics/StatisticsWorker.cpp index c5280f1493..c299bc799b 100644 --- a/arangod/Statistics/StatisticsWorker.cpp +++ b/arangod/Statistics/StatisticsWorker.cpp @@ -838,7 +838,7 @@ void StatisticsWorker::generateRawStatistics(VPackBuilder& builder, double const StatisticsDistribution bytesSent; StatisticsDistribution bytesReceived; - RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived); + RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived, RequestStatistics::Source::ALL); ServerStatistics const& serverInfo = ServerStatistics::statistics(); diff --git a/arangod/Statistics/figures.h b/arangod/Statistics/figures.h index c75a5fb25b..5d78535141 100644 --- a/arangod/Statistics/figures.h +++ b/arangod/Statistics/figures.h @@ -93,6 +93,19 @@ struct StatisticsDistribution { ++(*j); } + void add(StatisticsDistribution& other) { + MUTEX_LOCKER(lock, _mutex); + MUTEX_LOCKER(lock2, other._mutex); + TRI_ASSERT(_counts.size() == other._counts.size() && + _cuts.size() == _cuts.size()); + _count += other._count; + _total += other._total; + for (size_t i = 0; i < _counts.size(); ++i) { + TRI_ASSERT(i < _cuts.size() ? _cuts[i] == other._cuts[i] : true); + _counts[i] += other._counts[i]; + } + } + uint64_t _count; double _total; std::vector _cuts; diff --git a/arangod/V8Server/v8-statistics.cpp b/arangod/V8Server/v8-statistics.cpp index e93cee7da0..f57aae8e9e 100644 --- a/arangod/V8Server/v8-statistics.cpp +++ b/arangod/V8Server/v8-statistics.cpp @@ -225,7 +225,7 @@ static void JS_ClientStatistics(v8::FunctionCallbackInfo const& args) StatisticsDistribution bytesSent; StatisticsDistribution bytesReceived; - RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived); + RequestStatistics::fill(totalTime, requestTime, queueTime, ioTime, bytesSent, bytesReceived, RequestStatistics::Source::ALL); FillDistribution(isolate, result, TRI_V8_ASCII_STRING(isolate, "totalTime"), totalTime); FillDistribution(isolate, result, TRI_V8_ASCII_STRING(isolate, "requestTime"), requestTime); diff --git a/lib/Rest/VstMessage.h b/lib/Rest/VstMessage.h index 00a759db48..44c35df985 100644 --- a/lib/Rest/VstMessage.h +++ b/lib/Rest/VstMessage.h @@ -73,6 +73,14 @@ struct VstInputMessage { return _buffer.size() - len; } + uint64_t id() const { + return _id; + } + + uint64_t totalSize() const { + return _buffer.size(); + } + private: uint64_t _id; // id zero signals invalid state velocypack::Buffer _buffer;