diff options
author | Eric Milkie <milkie@10gen.com> | 2021-05-03 14:22:15 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-05-03 20:30:23 +0000 |
commit | 960f5deb14520af3076c9164fbf8b3cbcca0560f (patch) | |
tree | c36a300cc4060449974eab032d197813034defb5 /src/mongo/db/stats | |
parent | 20b86d14a58f5862fa0eeec1f2bfac3161797730 (diff) | |
download | mongo-960f5deb14520af3076c9164fbf8b3cbcca0560f.tar.gz |
SERVER-55556 add new totalUnitsWritten metric; add new localTime field to operationMetrics output
totalUnitsWritten is a metric that represents the number of bytes written to a document plus any index entries that follow, prior to writing another document; these bytes are then translated into Units as per the totalUnitWriteSizeBytes parameter.
Additionally, a new field localTime will now appear in every BSONArray (per database) included in the $operationMetrics aggregation stage
Diffstat (limited to 'src/mongo/db/stats')
4 files changed, 145 insertions, 2 deletions
diff --git a/src/mongo/db/stats/operation_resource_consumption.idl b/src/mongo/db/stats/operation_resource_consumption.idl index 051b0fbcaed..4eaf36c549a 100644 --- a/src/mongo/db/stats/operation_resource_consumption.idl +++ b/src/mongo/db/stats/operation_resource_consumption.idl @@ -65,3 +65,13 @@ server_parameters: default: 16 validator: gte: 1 + + totalUnitWriteSizeBytes: + description: "The size of a (doc + index) unit in written bytes for resource consumption metrics collection" + set_at: + - startup + cpp_varname: gTotalUnitWriteSizeBytes + cpp_vartype: int32_t + default: 128 + validator: + gte: 1 diff --git a/src/mongo/db/stats/resource_consumption_metrics.cpp b/src/mongo/db/stats/resource_consumption_metrics.cpp index fbc53138f3c..f5735150cd3 100644 --- a/src/mongo/db/stats/resource_consumption_metrics.cpp +++ b/src/mongo/db/stats/resource_consumption_metrics.cpp @@ -56,6 +56,7 @@ static const char kIdxEntryBytesRead[] = "idxEntryBytesRead"; static const char kIdxEntryBytesWritten[] = "idxEntryBytesWritten"; static const char kIdxEntryUnitsRead[] = "idxEntryUnitsRead"; static const char kIdxEntryUnitsWritten[] = "idxEntryUnitsWritten"; +static const char kTotalUnitsWritten[] = "totalUnitsWritten"; static const char kKeysSorted[] = "keysSorted"; static const char kMemUsage[] = "memUsage"; static const char kNumMetrics[] = "numMetrics"; @@ -125,6 +126,33 @@ void ResourceConsumption::UnitCounter::observeOne(size_t datumBytes) { _bytes += datumBytes; } +void ResourceConsumption::TotalUnitWriteCounter::observeOneDocument(size_t datumBytes) { + // If we have accumulated document bytes, calculate units along with any past index bytes. + // Accumulate the current document bytes for use in a later unit calculation. + if (_accumulatedDocumentBytes > 0) { + _units += std::ceil((_accumulatedIndexBytes + _accumulatedDocumentBytes) / + static_cast<float>(unitSize())); + _accumulatedIndexBytes = 0; + _accumulatedDocumentBytes = datumBytes; + return; + } + + // If we have accumulated index bytes, associate them with the current document and calculate + // units. + if (_accumulatedIndexBytes > 0) { + _units += std::ceil((_accumulatedIndexBytes + datumBytes) / static_cast<float>(unitSize())); + _accumulatedIndexBytes = 0; + return; + } + + // Nothing has yet accumulated; accumulate this document for use in a later unit calculation. + _accumulatedDocumentBytes = datumBytes; +} + +void ResourceConsumption::TotalUnitWriteCounter::observeOneIndexEntry(size_t datumBytes) { + _accumulatedIndexBytes += datumBytes; +} + int ResourceConsumption::DocumentUnitCounter::unitSize() const { return gDocumentUnitSizeBytes; } @@ -133,6 +161,10 @@ int ResourceConsumption::IdxEntryUnitCounter::unitSize() const { return gIndexEntryUnitSizeBytes; } +int ResourceConsumption::TotalUnitWriteCounter::unitSize() const { + return gTotalUnitWriteSizeBytes; +} + void ResourceConsumption::ReadMetrics::toBson(BSONObjBuilder* builder) const { builder->appendNumber(kDocBytesRead, docsRead.bytes()); builder->appendNumber(kDocUnitsRead, docsRead.units()); @@ -149,6 +181,7 @@ void ResourceConsumption::WriteMetrics::toBson(BSONObjBuilder* builder) const { builder->appendNumber(kDocUnitsWritten, docsWritten.units()); builder->appendNumber(kIdxEntryBytesWritten, idxEntriesWritten.bytes()); builder->appendNumber(kIdxEntryUnitsWritten, idxEntriesWritten.units()); + builder->appendNumber(kTotalUnitsWritten, totalWritten.units()); } void ResourceConsumption::AggregatedMetrics::toBson(BSONObjBuilder* builder) const { @@ -193,6 +226,7 @@ void ResourceConsumption::OperationMetrics::toBsonNonZeroFields(BSONObjBuilder* appendNonZeroMetric(builder, kDocUnitsWritten, writeMetrics.docsWritten.units()); appendNonZeroMetric(builder, kIdxEntryBytesWritten, writeMetrics.idxEntriesWritten.bytes()); appendNonZeroMetric(builder, kIdxEntryUnitsWritten, writeMetrics.idxEntriesWritten.units()); + appendNonZeroMetric(builder, kTotalUnitsWritten, writeMetrics.totalWritten.units()); } template <typename Func> @@ -225,11 +259,17 @@ void ResourceConsumption::MetricsCollector::incrementDocUnitsReturned( } void ResourceConsumption::MetricsCollector::incrementOneDocWritten(size_t bytesWritten) { - _doIfCollecting([&] { _metrics.writeMetrics.docsWritten.observeOne(bytesWritten); }); + _doIfCollecting([&] { + _metrics.writeMetrics.docsWritten.observeOne(bytesWritten); + _metrics.writeMetrics.totalWritten.observeOneDocument(bytesWritten); + }); } void ResourceConsumption::MetricsCollector::incrementOneIdxEntryWritten(size_t bytesWritten) { - _doIfCollecting([&] { _metrics.writeMetrics.idxEntriesWritten.observeOne(bytesWritten); }); + _doIfCollecting([&] { + _metrics.writeMetrics.idxEntriesWritten.observeOne(bytesWritten); + _metrics.writeMetrics.totalWritten.observeOneIndexEntry(bytesWritten); + }); } void ResourceConsumption::MetricsCollector::beginScopedCollecting(OperationContext* opCtx, diff --git a/src/mongo/db/stats/resource_consumption_metrics.h b/src/mongo/db/stats/resource_consumption_metrics.h index 5e098b5c730..4aef396e6b6 100644 --- a/src/mongo/db/stats/resource_consumption_metrics.h +++ b/src/mongo/db/stats/resource_consumption_metrics.h @@ -113,6 +113,35 @@ public: int unitSize() const final; }; + /** TotalUnitWriteCounter records the number of units of document plus associated indexes + * observed. */ + class TotalUnitWriteCounter { + public: + void observeOneDocument(size_t datumBytes); + void observeOneIndexEntry(size_t datumBytes); + + TotalUnitWriteCounter& operator+=(TotalUnitWriteCounter other) { + // Flush the accumulators, in case there is anything still pending. + other.observeOneDocument(0); + observeOneDocument(0); + _units += other._units; + return *this; + } + + long long units() const { + // Flush the accumulators, in case there is anything still pending. + TotalUnitWriteCounter copy(*this); + copy.observeOneDocument(0); + return copy._units; + } + + private: + int unitSize() const; + long long _accumulatedDocumentBytes = 0; + long long _accumulatedIndexBytes = 0; + long long _units = 0; + }; + /** ReadMetrics maintains metrics for read operations. */ class ReadMetrics { public: @@ -158,6 +187,7 @@ public: void add(const WriteMetrics& other) { docsWritten += other.docsWritten; idxEntriesWritten += other.idxEntriesWritten; + totalWritten += other.totalWritten; } WriteMetrics& operator+=(const WriteMetrics& other) { @@ -174,6 +204,8 @@ public: DocumentUnitCounter docsWritten; // Number of index entries written IdxEntryUnitCounter idxEntriesWritten; + // Number of total units written + TotalUnitWriteCounter totalWritten; }; /** diff --git a/src/mongo/db/stats/resource_consumption_metrics_test.cpp b/src/mongo/db/stats/resource_consumption_metrics_test.cpp index 4598e411b71..8c7d8a756ef 100644 --- a/src/mongo/db/stats/resource_consumption_metrics_test.cpp +++ b/src/mongo/db/stats/resource_consumption_metrics_test.cpp @@ -492,6 +492,67 @@ TEST_F(ResourceConsumptionMetricsTest, DocumentUnitsWritten) { ASSERT_EQ(metricsCopy["db1"].writeMetrics.docsWritten.units(), expectedUnits); } +TEST_F(ResourceConsumptionMetricsTest, TotalUnitsWritten) { + auto& globalResourceConsumption = ResourceConsumption::get(getServiceContext()); + auto& operationMetrics = ResourceConsumption::MetricsCollector::get(_opCtx.get()); + + int expectedUnits = 0; + + { + ResourceConsumption::ScopedMetricsCollector scope(_opCtx.get(), "db1"); + + // Each of these should be counted as 1 total unit (unit size = 128). + operationMetrics.incrementOneDocWritten(2); + operationMetrics.incrementOneDocWritten(4); + operationMetrics.incrementOneDocWritten(8); + operationMetrics.incrementOneDocWritten(16); + operationMetrics.incrementOneDocWritten(32); + operationMetrics.incrementOneDocWritten(64); + operationMetrics.incrementOneDocWritten(128); + expectedUnits += 7; + + // Each of these should be counted as 2 total units (unit size = 128). + operationMetrics.incrementOneDocWritten(129); + operationMetrics.incrementOneDocWritten(200); + operationMetrics.incrementOneDocWritten(255); + operationMetrics.incrementOneDocWritten(256); + expectedUnits += 8; + + // Each of these groups should be counted as 1 total unit, combining documents with index + // bytes written. + + // Index writes prior to document write. + operationMetrics.incrementOneDocWritten(0); + operationMetrics.incrementOneIdxEntryWritten(2); + operationMetrics.incrementOneDocWritten(5); + expectedUnits += 1; + + // Index writes after document write. + operationMetrics.incrementOneDocWritten(2); + operationMetrics.incrementOneIdxEntryWritten(126); + expectedUnits += 1; + + // No index writes. + operationMetrics.incrementOneDocWritten(129); + expectedUnits += 2; + + operationMetrics.incrementOneDocWritten(127); + operationMetrics.incrementOneIdxEntryWritten(1); + expectedUnits += 1; + + // Exceeds unit size and thus counts as 2 units. + operationMetrics.incrementOneDocWritten(1); + operationMetrics.incrementOneIdxEntryWritten(1); + operationMetrics.incrementOneIdxEntryWritten(1); + operationMetrics.incrementOneIdxEntryWritten(1); + operationMetrics.incrementOneIdxEntryWritten(128); + expectedUnits += 2; + } + + auto metricsCopy = globalResourceConsumption.getDbMetrics(); + ASSERT_EQ(metricsCopy["db1"].writeMetrics.totalWritten.units(), expectedUnits); +} + TEST_F(ResourceConsumptionMetricsTest, IdxEntryUnitsRead) { auto& globalResourceConsumption = ResourceConsumption::get(getServiceContext()); auto& operationMetrics = ResourceConsumption::MetricsCollector::get(_opCtx.get()); |