Last active
August 18, 2025 20:54
-
-
Save alexbevi/fc4f59621aee4efbae2c04187dcbf2c6 to your computer and use it in GitHub Desktop.
MongoDB 5.0+ Initial Sync Progress Monitoring
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * measureInitialSyncProgress | |
| * @author Alex Bevilacqua <[email protected]> | |
| * @updated 2021-02-23 | |
| * | |
| * Can be run against a MongoDB 4.2.12+ mongod that is in STARTUP2 (intitial sync) state to gain some | |
| * insight into how the sync is progressing based on the improvements introduced with SERVER-47863. | |
| * For versions of MongoDB < 4.2.12, see https://www.alexbevi.com/blog/2020/02/13/mongodb-initial-sync-progress-monitoring | |
| * | |
| * usage: | |
| * mongo --quiet --eval "load('measureInitialSyncProgress.js'); measureInitialSyncProgress();" | |
| * // pass a value in milliseconds to measureInitialSyncProgress to override the refresh interval | |
| * // default: 5000 (5 seconds) | |
| * mongo --quiet --eval "load('measureInitialSyncProgress.js'); measureInitialSyncProgress(1000);" | |
| */ | |
| function msToTime(duration) { | |
| var milliseconds = parseInt((duration % 1000) / 100), | |
| seconds = Math.floor((duration / 1000) % 60), | |
| minutes = Math.floor((duration / (1000 * 60)) % 60), | |
| hours = Math.floor((duration / (1000 * 60 * 60)) % 24); | |
| hours = (hours < 10) ? "0" + hours : hours; | |
| minutes = (minutes < 10) ? "0" + minutes : minutes; | |
| seconds = (seconds < 10) ? "0" + seconds : seconds; | |
| return hours + ":" + minutes + ":" + seconds + "." + milliseconds; | |
| } | |
| var getReadableFileSizeString = function (fileSizeInBytes) { | |
| var i = -1; | |
| var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB']; | |
| do { | |
| fileSizeInBytes = fileSizeInBytes / 1024; | |
| i++; | |
| } while (fileSizeInBytes > 1024); | |
| return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]; | |
| }; | |
| function measureSyncProgress(previousResults) { | |
| var cmd = db.adminCommand({ replSetGetStatus: 1, initialSync: 1 }); | |
| if (!cmd.hasOwnProperty("initialSyncStatus")) { | |
| print("Node not currently performing an initial sync"); | |
| return { exit: true }; | |
| } | |
| var status = cmd.initialSyncStatus; | |
| db.adminCommand({ replSetGetStatus: 1, initialSync: 1 }).initialSyncStatus.approxTotalBytesCopied | |
| var now = new Date(); | |
| var started = status.initialSyncStart; | |
| var approxTotal = status.approxTotalDataSize; | |
| var approxCopied = status.approxTotalBytesCopied; | |
| var message = "Cloned " + getReadableFileSizeString(approxCopied) + " of " + getReadableFileSizeString(approxTotal) + " in " + msToTime(now - started); | |
| if (previousResults !== undefined && previousResults.hasOwnProperty("refreshIntervalMS") !== null && previousResults.hasOwnProperty("copied")) { | |
| var refreshInterval = previousResults.refreshIntervalMS / 1000; | |
| var intervalProgress = approxCopied - previousResults.copied; | |
| if (intervalProgress == 0) { | |
| message += " (No progress in past " + refreshInterval + " second(s))"; | |
| } else { | |
| var rate = intervalProgress / refreshInterval; | |
| // We no longer have to calculate remaining ourselves as SERVER-53017 has fixed remainingInitialSyncEstimatedMillis | |
| // var remaining = msToTime(((approxTotal - approxCopied) / rate) * 1000); | |
| message += " (" + getReadableFileSizeString(intervalProgress) + " in past " + refreshInterval; | |
| message += " second(s)) at a rate of " + getReadableFileSizeString(rate) + "/second - "; | |
| message += msToTime(status.remainingInitialSyncEstimatedMillis) + " to go!"; | |
| } | |
| } | |
| print(message); | |
| return { copied: approxCopied }; | |
| } | |
| function measureInitialSyncProgress(refreshIntervalMS) { | |
| var dbver = db.version().split('-')[0]; | |
| if (dbver < "4.2.12") { | |
| print("MongoDB 4.2.12 or greater required but found MongoDB " + dbver); | |
| print("For previous versions see https://www.alexbevi.com/blog/2020/02/13/mongodb-initial-sync-progress-monitoring/"); | |
| return; | |
| } | |
| if (refreshIntervalMS === undefined || refreshIntervalMS === null) { | |
| refreshIntervalMS = 5000; | |
| } | |
| var result = measureSyncProgress(result); | |
| result["refreshIntervalMS"] = refreshIntervalMS; | |
| while (!result.exit) { | |
| sleep(refreshIntervalMS); | |
| result = measureSyncProgress(result); | |
| result["refreshIntervalMS"] = refreshIntervalMS; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment