2727 * it in the license file.
2828 */
2929
30+ #define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kTest
31+
3032#include < fmt/format.h>
3133
3234#include " mongo/bson/bsonobjbuilder.h"
3335#include " mongo/bson/json.h"
3436#include " mongo/db/s/resharding/resharding_metrics.h"
3537#include " mongo/db/service_context_test_fixture.h"
38+ #include " mongo/logv2/log.h"
3639#include " mongo/unittest/death_test.h"
3740#include " mongo/unittest/unittest.h"
3841#include " mongo/util/clock_source_mock.h"
3942#include " mongo/util/uuid.h"
4043
4144namespace mongo {
45+ namespace {
46+
47+ using namespace fmt ::literals;
48+
49+ constexpr auto kOpTimeRemaining = " remainingOperationTimeEstimatedMillis" _sd;
4250
4351class ReshardingMetricsTest : public ServiceContextTest {
4452public:
45- void setUp () {
53+ void setUp () override {
4654 auto clockSource = std::make_unique<ClockSourceMock>();
4755 _clockSource = clockSource.get ();
4856 getGlobalServiceContext ()->setFastClockSource (std::move (clockSource));
@@ -55,8 +63,8 @@ class ReshardingMetricsTest : public ServiceContextTest {
5563 // Timer step in milliseconds
5664 static constexpr auto kTimerStep = 100 ;
5765
58- void advanceTime (Milliseconds interval = Milliseconds( kTimerStep ) ) {
59- _clockSource->advance (interval );
66+ void advanceTime (Milliseconds step = Milliseconds{ kTimerStep } ) {
67+ _clockSource->advance (step );
6068 }
6169
6270 auto getReport () {
@@ -371,4 +379,68 @@ TEST_F(ReshardingMetricsTest, CurrentOpReportForCoordinator) {
371379 ASSERT_BSONOBJ_EQ (expected, report);
372380}
373381
382+ TEST_F (ReshardingMetricsTest, EstimatedRemainingOperationTimeCloning) {
383+ // Copy N docs @ timePerDoc. Check the progression of the estimated time remaining.
384+ auto m = getMetrics ();
385+ m->onStart ();
386+ m->setRecipientState (RecipientStateEnum::kCloning );
387+ auto timePerDocument = Milliseconds{123 };
388+ int64_t bytesPerDocument = 1024 ;
389+ int64_t documentsToCopy = 409 ;
390+ int64_t bytesToCopy = bytesPerDocument * documentsToCopy;
391+ m->setDocumentsToCopy (documentsToCopy, bytesToCopy);
392+ auto remainingTime = 2 * timePerDocument * documentsToCopy;
393+ double maxAbsRelErr = 0 ;
394+ for (int64_t copied = 0 ; copied < documentsToCopy; ++copied) {
395+ double output = getReport ()[kOpTimeRemaining ].Number ();
396+ if (copied == 0 ) {
397+ ASSERT_EQ (output, -1 );
398+ } else {
399+ ASSERT_GTE (output, 0 );
400+ auto expected = durationCount<Milliseconds>(remainingTime);
401+ // Check that error is pretty small (it should get better as the operation progresses)
402+ double absRelErr = std::abs ((output - expected) / expected);
403+ ASSERT_LT (absRelErr, 0.05 )
404+ << " output={}, expected={}, copied={}" _format (output, expected, copied);
405+ maxAbsRelErr = std::max (maxAbsRelErr, absRelErr);
406+ }
407+ m->onDocumentsCopied (1 , bytesPerDocument);
408+ advanceTime (timePerDocument);
409+ remainingTime -= timePerDocument;
410+ }
411+ LOGV2_DEBUG (
412+ 5422700 , 3 , " Max absolute relative error observed" , " maxAbsRelErr" _attr = maxAbsRelErr);
413+ }
414+
415+ TEST_F (ReshardingMetricsTest, EstimatedRemainingOperationTimeApplying) {
416+ // Perform N ops @ timePerOp. Check the progression of the estimated time remaining.
417+ auto m = getMetrics ();
418+ m->onStart ();
419+ m->setRecipientState (RecipientStateEnum::kApplying );
420+ auto timePerOp = Milliseconds{123 };
421+ int64_t fetched = 10000 ;
422+ m->onOplogEntriesFetched (fetched);
423+ auto remainingTime = timePerOp * fetched;
424+ double maxAbsRelErr = 0 ;
425+ for (int64_t applied = 0 ; applied < fetched; ++applied) {
426+ double output = getReport ()[kOpTimeRemaining ].Number ();
427+ if (applied == 0 ) {
428+ ASSERT_EQ (output, -1 );
429+ } else {
430+ auto expected = durationCount<Milliseconds>(remainingTime);
431+ // Check that error is pretty small (it should get better as the operation progresses)
432+ double absRelErr = std::abs ((output - expected) / expected);
433+ ASSERT_LT (absRelErr, 0.05 )
434+ << " output={}, expected={}, applied={}" _format (output, expected, applied);
435+ maxAbsRelErr = std::max (maxAbsRelErr, absRelErr);
436+ }
437+ advanceTime (timePerOp);
438+ m->onOplogEntriesApplied (1 );
439+ remainingTime -= timePerOp;
440+ }
441+ LOGV2_DEBUG (
442+ 5422701 , 3 , " Max absolute relative error observed" , " maxAbsRelErr" _attr = maxAbsRelErr);
443+ }
444+
445+ } // namespace
374446} // namespace mongo
0 commit comments