summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2018-07-13 17:10:01 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2018-07-13 17:10:01 -0400
commit77ab40c05f28c6c0afbc84bb72375a9867f79ecb (patch)
treeacd2fc8198419a2b60bbd50abf781c7c87e11dbd
parent5a7537b07dbf7d8db74531632dc06883042b4234 (diff)
downloadmongo-77ab40c05f28c6c0afbc84bb72375a9867f79ecb.tar.gz
SERVER-35692 Add support to an optional re-registration bool in metrics response
-rw-r--r--jstests/free_mon/free_mon_register.js4
-rw-r--r--jstests/free_mon/free_mon_register_cmd.js4
-rw-r--r--jstests/free_mon/free_mon_register_resend.js28
-rw-r--r--jstests/free_mon/free_mon_rs_register.js3
-rw-r--r--jstests/free_mon/free_mon_rs_resend.js66
-rw-r--r--jstests/free_mon/libs/free_mon.js11
-rw-r--r--jstests/free_mon/libs/mock_http_server.py37
-rw-r--r--src/mongo/db/free_mon/free_mon_controller_test.cpp88
-rw-r--r--src/mongo/db/free_mon/free_mon_processor.cpp60
-rw-r--r--src/mongo/db/free_mon/free_mon_processor.h24
-rw-r--r--src/mongo/db/free_mon/free_mon_protocol.idl9
11 files changed, 300 insertions, 34 deletions
diff --git a/jstests/free_mon/free_mon_register.js b/jstests/free_mon/free_mon_register.js
index d0d29f114de..6d1ae50274a 100644
--- a/jstests/free_mon/free_mon_register.js
+++ b/jstests/free_mon/free_mon_register.js
@@ -31,7 +31,7 @@ load("jstests/free_mon/libs/free_mon.js");
const last_register = mock_web.query("last_register");
print(tojson(last_register));
- assert.eq(last_register.version, 1);
+ assert.eq(last_register.version, 2);
assert.gt(new Date().setTime(last_register.localTime["$date"]), localTime);
assert.eq(last_register.payload.buildInfo.bits, 64);
assert.eq(last_register.payload.buildInfo.ok, 1);
@@ -44,7 +44,7 @@ load("jstests/free_mon/libs/free_mon.js");
const last_metrics = mock_web.query("last_metrics");
print(tojson(last_metrics));
- assert.eq(last_metrics.version, 1);
+ assert.eq(last_metrics.version, 2);
assert.gt(new Date().setTime(last_metrics.localTime["$date"]), localTime);
MongoRunner.stopMongod(conn);
diff --git a/jstests/free_mon/free_mon_register_cmd.js b/jstests/free_mon/free_mon_register_cmd.js
index 6eb0c1f9c69..35fdc9397af 100644
--- a/jstests/free_mon/free_mon_register_cmd.js
+++ b/jstests/free_mon/free_mon_register_cmd.js
@@ -41,7 +41,7 @@ load("jstests/free_mon/libs/free_mon.js");
const last_register = mock_web.query("last_register");
print(tojson(last_register));
- assert.eq(last_register.version, 1);
+ assert.eq(last_register.version, 2);
assert.eq(last_register.payload.buildInfo.bits, 64);
assert.eq(last_register.payload.buildInfo.ok, 1);
assert.eq(last_register.payload.storageEngine.readOnly, false);
@@ -52,7 +52,7 @@ load("jstests/free_mon/libs/free_mon.js");
const last_metrics = mock_web.query("last_metrics");
print(tojson(last_metrics));
- assert.eq(last_metrics.version, 1);
+ assert.eq(last_metrics.version, 2);
assert.commandWorked(conn.adminCommand({setFreeMonitoring: 1, action: "disable"}));
diff --git a/jstests/free_mon/free_mon_register_resend.js b/jstests/free_mon/free_mon_register_resend.js
new file mode 100644
index 00000000000..de98e038ac6
--- /dev/null
+++ b/jstests/free_mon/free_mon_register_resend.js
@@ -0,0 +1,28 @@
+// Validate resend registration works in a replica set
+//
+load("jstests/free_mon/libs/free_mon.js");
+
+(function() {
+ 'use strict';
+
+ let mock_web = new FreeMonWebServer(FAULT_RESEND_REGISTRATION_ONCE);
+
+ mock_web.start();
+
+ let options = {
+ setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
+ enableFreeMonitoring: "on",
+ verbose: 1,
+ };
+
+ const conn = MongoRunner.runMongod(options);
+ assert.neq(null, conn, 'mongod was unable to start up');
+
+ WaitForRegistration(conn);
+
+ mock_web.waitRegisters(2);
+
+ MongoRunner.stopMongod(conn);
+
+ mock_web.stop();
+})();
diff --git a/jstests/free_mon/free_mon_rs_register.js b/jstests/free_mon/free_mon_rs_register.js
index 1c518456a2f..acbdab3301c 100644
--- a/jstests/free_mon/free_mon_rs_register.js
+++ b/jstests/free_mon/free_mon_rs_register.js
@@ -15,6 +15,7 @@ load("jstests/free_mon/libs/free_mon.js");
};
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
+
rst.startSet();
rst.initiate();
rst.awaitReplication();
@@ -33,7 +34,7 @@ load("jstests/free_mon/libs/free_mon.js");
const last_register = mock_web.query("last_register");
print(tojson(last_register));
- assert.eq(last_register.version, 1);
+ assert.eq(last_register.version, 2);
assert.eq(last_register.payload.buildInfo.bits, 64);
assert.eq(last_register.payload.buildInfo.ok, 1);
assert.eq(last_register.payload.storageEngine.readOnly, false);
diff --git a/jstests/free_mon/free_mon_rs_resend.js b/jstests/free_mon/free_mon_rs_resend.js
new file mode 100644
index 00000000000..464caf396e5
--- /dev/null
+++ b/jstests/free_mon/free_mon_rs_resend.js
@@ -0,0 +1,66 @@
+// Validate resend registration works in a replica set
+//
+load("jstests/free_mon/libs/free_mon.js");
+
+(function() {
+ 'use strict';
+
+ let mock_web = new FreeMonWebServer(FAULT_RESEND_REGISTRATION_AT_3);
+ let mock_web_sec = new FreeMonWebServer(FAULT_RESEND_REGISTRATION_ONCE, true);
+
+ mock_web.start();
+ mock_web_sec.start();
+
+ const rst = new ReplSetTest({
+ name: "free_mon_rs_register",
+ nodes: [
+ {
+ setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
+ verbose: 1,
+ },
+ {
+ setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web_sec.getURL(),
+ verbose: 1,
+ }
+ ]
+ });
+
+ rst.startSet();
+ rst.initiate();
+ rst.awaitReplication();
+
+ sleep(10 * 1000);
+ assert.eq(0, mock_web.queryStats().registers, "mongod registered without enabling free_mod");
+ assert.eq(
+ 0, mock_web_sec.queryStats().registers, "mongod registered without enabling free_mod");
+
+ assert.commandWorked(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "enable"}));
+ WaitForRegistration(rst.getPrimary());
+
+ mock_web.waitRegisters(1);
+ mock_web_sec.waitRegisters(1);
+
+ assert.eq(FreeMonGetServerStatus(rst.getPrimary()).state, 'enabled');
+ assert.eq(FreeMonGetServerStatus(rst.getSecondary()).state, 'enabled');
+
+ mock_web.waitRegisters(2);
+ mock_web_sec.waitRegisters(2);
+ mock_web_sec.disableFaults();
+
+ // Trigger resend on the secondary only
+ mock_web_sec.enableFaults();
+ mock_web_sec.waitFaults(1);
+ mock_web_sec.waitRegisters(3);
+
+ // Double check registers were as expected
+ const stats = mock_web.queryStats();
+ assert.eq(stats.registers, 2);
+
+ const stats_sec = mock_web_sec.queryStats();
+ assert.gte(stats_sec.registers, 3);
+
+ rst.stopSet();
+
+ mock_web.stop();
+ mock_web_sec.stop();
+})();
diff --git a/jstests/free_mon/libs/free_mon.js b/jstests/free_mon/libs/free_mon.js
index 3cb9f90e364..74da57b3e6b 100644
--- a/jstests/free_mon/libs/free_mon.js
+++ b/jstests/free_mon/libs/free_mon.js
@@ -9,6 +9,8 @@ const FAULT_FAIL_REGISTER = "fail_register";
const FAULT_INVALID_REGISTER = "invalid_register";
const FAULT_HALT_METRICS_5 = "halt_metrics_5";
const FAULT_PERMANENTLY_DELETE_AFTER_3 = "permanently_delete_after_3";
+const FAULT_RESEND_REGISTRATION_AT_3 = "resend_registration_at_3";
+const FAULT_RESEND_REGISTRATION_ONCE = "resend_registration_once";
const DISABLE_FAULTS = "disable_faults";
const ENABLE_FAULTS = "enable_faults";
@@ -175,10 +177,11 @@ class FreeMonWebServer {
*/
waitRegisters(count) {
const qs = this.queryStats.bind(this);
+ const port = this.port;
// Wait for registration to occur
assert.soon(function() {
const stats = qs();
- print("QS : " + tojson(stats));
+ print("w" + port + "| waiting for registers >= (" + count + ") QS : " + tojson(stats));
return stats.registers >= count;
}, "Failed to web server register", 60 * 1000);
}
@@ -190,10 +193,11 @@ class FreeMonWebServer {
*/
waitMetrics(count) {
const qs = this.queryStats.bind(this);
+ const port = this.port;
// Wait for metrics uploads to occur
assert.soon(function() {
const stats = qs();
- print("QS : " + tojson(stats));
+ print("w" + port + "| waiting for metrics >= (" + count + ") QS : " + tojson(stats));
return stats.metrics >= count;
}, "Failed to web server metrics", 60 * 1000);
}
@@ -205,10 +209,11 @@ class FreeMonWebServer {
*/
waitFaults(count) {
const qs = this.queryStats.bind(this);
+ const port = this.port;
// Wait for faults to be triggered
assert.soon(function() {
const stats = qs();
- print("QS : " + tojson(stats));
+ print("w" + port + "| waiting for faults >= (" + count + ") QS : " + tojson(stats));
return stats.faults >= count;
}, "Failed to web server faults", 60 * 1000);
}
diff --git a/jstests/free_mon/libs/mock_http_server.py b/jstests/free_mon/libs/mock_http_server.py
index 2005575463c..f6ce1a39299 100644
--- a/jstests/free_mon/libs/mock_http_server.py
+++ b/jstests/free_mon/libs/mock_http_server.py
@@ -36,12 +36,20 @@ FAULT_HALT_METRICS_5 = "halt_metrics_5"
"""Fault which causes metrics to return permanentlyDelete = true after 3 uploads."""
FAULT_PERMANENTLY_DELETE_AFTER_3 = "permanently_delete_after_3"
+"""Fault which causes metrics to trigger resentRegistration at 3 uploads."""
+FAULT_RESEND_REGISTRATION_AT_3 = "resend_registration_at_3"
+
+"""Fault which causes metrics to trigger resentRegistration once."""
+FAULT_RESEND_REGISTRATION_ONCE = "resend_registration_once"
+
# List of supported fault types
SUPPORTED_FAULT_TYPES = [
FAULT_FAIL_REGISTER,
FAULT_INVALID_REGISTER,
FAULT_HALT_METRICS_5,
FAULT_PERMANENTLY_DELETE_AFTER_3,
+ FAULT_RESEND_REGISTRATION_AT_3,
+ FAULT_RESEND_REGISTRATION_ONCE,
]
# Supported POST URL types
@@ -117,7 +125,7 @@ class FreeMonHandler(http.server.BaseHTTPRequestHandler):
data = bson.BSON.encode({
'version': bson.int64.Int64(42),
'haltMetricsUploading': False,
- 'id': 'mock123',
+ 'id': '',
'informationalURL': 'http://www.example.com/123',
'message': 'Welcome to the Mock Free Monitoring Endpoint',
'reportingInterval': bson.int64.Int64(1),
@@ -177,12 +185,37 @@ You can disable monitoring at any time by running db.disableFreeMonitoring()."""
'reportingInterval': bson.int64.Int64(1),
'message': 'Thanks for all the metrics',
})
+ elif not disable_faults and \
+ stats.metrics_calls > 3 and \
+ stats.fault_calls < 1 and fault_type == FAULT_RESEND_REGISTRATION_ONCE:
+ stats.fault_calls += 1
+ data = bson.BSON.encode({
+ 'version': bson.int64.Int64(2),
+ 'haltMetricsUploading': False,
+ 'permanentlyDelete': False,
+ 'id': 'mock123',
+ 'reportingInterval': bson.int64.Int64(1),
+ 'message': 'Thanks for all the metrics',
+ 'resendRegistration' : True,
+ })
+ elif not disable_faults and \
+ stats.metrics_calls == 3 and fault_type == FAULT_RESEND_REGISTRATION_AT_3:
+ stats.fault_calls += 1
+ data = bson.BSON.encode({
+ 'version': bson.int64.Int64(2),
+ 'haltMetricsUploading': False,
+ 'permanentlyDelete': False,
+ 'id': 'mock123',
+ 'reportingInterval': bson.int64.Int64(1),
+ 'message': 'Thanks for all the metrics',
+ 'resendRegistration' : True,
+ })
else:
data = bson.BSON.encode({
'version': bson.int64.Int64(1),
'haltMetricsUploading': False,
'permanentlyDelete': False,
- 'id': 'mock123',
+ 'id': '',
'reportingInterval': bson.int64.Int64(1),
'message': 'Thanks for all the metrics',
})
diff --git a/src/mongo/db/free_mon/free_mon_controller_test.cpp b/src/mongo/db/free_mon/free_mon_controller_test.cpp
index 76ba859fdee..43481e870e4 100644
--- a/src/mongo/db/free_mon/free_mon_controller_test.cpp
+++ b/src/mongo/db/free_mon/free_mon_controller_test.cpp
@@ -228,6 +228,8 @@ public:
bool haltMetrics{false};
bool fail2MetricsUploads{false};
bool permanentlyDeleteAfter3{false};
+
+ bool resendRegistrationAfter3{false};
};
explicit FreeMonNetworkInterfaceMock(executor::ThreadPoolTaskExecutor* threadPool,
@@ -333,6 +335,10 @@ public:
resp.setPermanentlyDelete(true);
}
+ if (_options.resendRegistrationAfter3 && _metrics.loadRelaxed() == 3) {
+ resp.setResendRegistration(true);
+ }
+
return resp;
}
@@ -551,6 +557,29 @@ TEST(FreeMonProcessorTest, TestRegistrationResponseValidation) {
<< "reportingInterval"
<< 30 * 60 * 60 * 24LL))));
+ // Positive: version 2
+ ASSERT_OK(FreeMonProcessor::validateRegistrationResponse(FreeMonRegistrationResponse::parse(
+ IDLParserErrorContext("foo"),
+ BSON("version" << 2LL << "haltMetricsUploading" << false << "id"
+ << "mock123"
+ << "informationalURL"
+ << "http://www.example.com/123"
+ << "message"
+ << "msg456"
+ << "reportingInterval"
+ << 1LL))));
+
+ // Positive: empty registration id string
+ ASSERT_OK(FreeMonProcessor::validateRegistrationResponse(FreeMonRegistrationResponse::parse(
+ IDLParserErrorContext("foo"),
+ BSON("version" << 1LL << "haltMetricsUploading" << false << "id"
+ << ""
+ << "informationalURL"
+ << "http://www.example.com/123"
+ << "message"
+ << "msg456"
+ << "reportingInterval"
+ << 1LL))));
// Negative: bad protocol version
ASSERT_NOT_OK(FreeMonProcessor::validateRegistrationResponse(FreeMonRegistrationResponse::parse(
@@ -652,7 +681,38 @@ TEST(FreeMonProcessorTest, TestMetricsResponseValidation) {
<< "reportingInterval"
<< 1LL))));
- // max reporting interval
+ // Positive: Support version 2
+ ASSERT_OK(FreeMonProcessor::validateMetricsResponse(FreeMonMetricsResponse::parse(
+ IDLParserErrorContext("foo"),
+
+ BSON("version" << 2LL << "haltMetricsUploading" << false << "permanentlyDelete" << false
+ << "id"
+ << "mock123"
+ << "informationalURL"
+ << "http://www.example.com/123"
+ << "message"
+ << "msg456"
+ << "reportingInterval"
+ << 1LL))));
+
+ // Positive: Add resendRegistration
+ ASSERT_OK(FreeMonProcessor::validateMetricsResponse(FreeMonMetricsResponse::parse(
+ IDLParserErrorContext("foo"),
+
+ BSON("version" << 2LL << "haltMetricsUploading" << false << "permanentlyDelete" << false
+ << "id"
+ << "mock123"
+ << "informationalURL"
+ << "http://www.example.com/123"
+ << "message"
+ << "msg456"
+ << "reportingInterval"
+ << 1LL
+ << "resendRegistration"
+ << true))));
+
+
+ // Positive: max reporting interval
ASSERT_OK(FreeMonProcessor::validateMetricsResponse(FreeMonMetricsResponse::parse(
IDLParserErrorContext("foo"),
@@ -1192,6 +1252,28 @@ TEST_F(FreeMonControllerTest, TestPreRegistrationMetricBatching) {
ASSERT_EQ(controller.network->getLastMetrics().nFields(), 2);
}
+// Positive: resend registration in metrics response
+TEST_F(FreeMonControllerTest, TestResendRegistration) {
+ FreeMonNetworkInterfaceMock::Options opts;
+ opts.resendRegistrationAfter3 = true;
+
+ ControllerHolder controller(_mockThreadPool.get(), opts);
+
+ controller.start(RegistrationType::RegisterAfterOnTransitionToPrimary);
+
+ ASSERT_OK(controller->registerServerCommand(Milliseconds::min()));
+
+ controller->turnCrankForTest(Turner().registerServer().registerCommand().collect(2));
+
+ ASSERT_TRUE(!FreeMonStorage::read(_opCtx.get()).get().getRegistrationId().empty());
+
+ controller->turnCrankForTest(
+ Turner().metricsSend(3).collect(3).registerCommand().metricsSend(1));
+
+ ASSERT_EQ(controller.registerCollector->count(), 2UL);
+ ASSERT_GTE(controller.metricsCollector->count(), 4UL);
+}
+
#if 0
// Negative: Test metrics buffers on failure, and retries and ensure 2 metrics occurs after a blip
// of an error
@@ -1372,13 +1454,13 @@ TEST_F(FreeMonControllerRSTest, StepdownDuringRegistration) {
// Finish registration
controller->turnCrankForTest(1);
- controller->turnCrankForTest(Turner().metricsSend().collect(1));
+ controller->turnCrankForTest(Turner().metricsSend().collect(2));
// Registration cannot write back to the local store so remain in pending
ASSERT_TRUE(FreeMonStorage::read(_opCtx.get()).get().getState() == StorageStateEnum::pending);
ASSERT_EQ(controller.registerCollector->count(), 1UL);
- ASSERT_EQ(controller.metricsCollector->count(), 2UL);
+ ASSERT_EQ(controller.metricsCollector->count(), 3UL);
}
// Negative: Tricky: Primary becomes secondary during metrics send
diff --git a/src/mongo/db/free_mon/free_mon_processor.cpp b/src/mongo/db/free_mon/free_mon_processor.cpp
index 6e73596b8a1..2c1452a8738 100644
--- a/src/mongo/db/free_mon/free_mon_processor.cpp
+++ b/src/mongo/db/free_mon/free_mon_processor.cpp
@@ -52,7 +52,8 @@ namespace mongo {
namespace {
-constexpr auto kProtocolVersion = 1;
+constexpr auto kMinProtocolVersion = 1;
+constexpr auto kMaxProtocolVersion = 2;
constexpr auto kStorageVersion = 1;
constexpr auto kRegistrationIdMaxLength = 4096;
@@ -269,13 +270,13 @@ void FreeMonProcessor::readState(OperationContext* opCtx) {
_lastReadState = state;
if (state.is_initialized()) {
- invariant(state.get().getVersion() == kProtocolVersion);
+ invariant(state.get().getVersion() == kStorageVersion);
_state = state.get();
} else if (!state.is_initialized()) {
// Default the state
auto state = _state.synchronize();
- state->setVersion(kProtocolVersion);
+ state->setVersion(kStorageVersion);
state->setState(StorageStateEnum::disabled);
state->setRegistrationId("");
state->setInformationalURL("");
@@ -411,7 +412,7 @@ void FreeMonProcessor::doCommandRegister(Client* client,
req.setId(regid);
}
- req.setVersion(kProtocolVersion);
+ req.setVersion(kMaxProtocolVersion);
req.setLocalTime(client->getServiceContext()->getPreciseClockSource()->now());
@@ -431,6 +432,7 @@ void FreeMonProcessor::doCommandRegister(Client* client,
// Record that the registration is pending
_state->setState(StorageStateEnum::pending);
+ _registrationStatus = FreeMonRegistrationStatus::kPending;
writeState(client);
@@ -451,12 +453,14 @@ void FreeMonProcessor::doCommandRegister(Client* client,
Status FreeMonProcessor::validateRegistrationResponse(const FreeMonRegistrationResponse& resp) {
// Any validation failure stops registration from proceeding to upload
- if (resp.getVersion() != kProtocolVersion) {
+ if (!(resp.getVersion() >= kMinProtocolVersion && resp.getVersion() <= kMaxProtocolVersion)) {
return Status(ErrorCodes::FreeMonHttpPermanentFailure,
str::stream()
- << "Unexpected registration response protocol version, expected '"
- << kProtocolVersion
- << "', received '"
+ << "Unexpected registration response protocol version, expected ("
+ << kMinProtocolVersion
+ << ", "
+ << kMaxProtocolVersion
+ << "), received '"
<< resp.getVersion()
<< "'");
}
@@ -525,11 +529,13 @@ void FreeMonProcessor::notifyPendingRegisters(const Status s) {
Status FreeMonProcessor::validateMetricsResponse(const FreeMonMetricsResponse& resp) {
// Any validation failure stops registration from proceeding to upload
- if (resp.getVersion() != kProtocolVersion) {
+ if (!(resp.getVersion() >= kMinProtocolVersion && resp.getVersion() <= kMaxProtocolVersion)) {
return Status(ErrorCodes::FreeMonHttpPermanentFailure,
- str::stream() << "Unexpected metrics response protocol version, expected '"
- << kProtocolVersion
- << "', received '"
+ str::stream() << "Unexpected metrics response protocol version, expected ("
+ << kMinProtocolVersion
+ << ", "
+ << kMaxProtocolVersion
+ << "), received '"
<< resp.getVersion()
<< "'");
}
@@ -598,7 +604,7 @@ void FreeMonProcessor::doAsyncRegisterComplete(
// Our request is no longer in-progress so delete it
_futureRegistrationResponse.reset();
- if (_state->getState() != StorageStateEnum::pending) {
+ if (_registrationStatus != FreeMonRegistrationStatus::kPending) {
notifyPendingRegisters(Status(ErrorCodes::BadValue, "Registration was canceled"));
return;
@@ -612,6 +618,7 @@ void FreeMonProcessor::doAsyncRegisterComplete(
// Disable on any error
_state->setState(StorageStateEnum::disabled);
+ _registrationStatus = FreeMonRegistrationStatus::kDisabled;
// Persist state
writeState(client);
@@ -642,6 +649,8 @@ void FreeMonProcessor::doAsyncRegisterComplete(
state->setState(StorageStateEnum::enabled);
}
+ _registrationStatus = FreeMonRegistrationStatus::kEnabled;
+
// Persist state
writeState(client);
@@ -663,7 +672,7 @@ void FreeMonProcessor::doAsyncRegisterFail(
// Our request is no longer in-progress so delete it
_futureRegistrationResponse.reset();
- if (_state->getState() != StorageStateEnum::pending) {
+ if (_registrationStatus != FreeMonRegistrationStatus::kPending) {
notifyPendingRegisters(Status(ErrorCodes::BadValue, "Registration was canceled"));
return;
@@ -689,6 +698,7 @@ void FreeMonProcessor::doCommandUnregister(
readState(client);
_state->setState(StorageStateEnum::disabled);
+ _registrationStatus = FreeMonRegistrationStatus::kDisabled;
writeState(client);
@@ -733,16 +743,18 @@ std::string compressMetrics(MetricsBuffer& buffer) {
void FreeMonProcessor::doMetricsSend(Client* client) {
readState(client);
- if (_state->getState() != StorageStateEnum::enabled) {
+ // Only continue metrics send if the local disk state (in-case user deleted local document)
+ // and in-memory status both say to continue.
+ if (_registrationStatus != FreeMonRegistrationStatus::kEnabled ||
+ _state->getState() != StorageStateEnum::enabled) {
// If we are recently disabled, then stop sending metrics
return;
}
// Build outbound request
FreeMonMetricsRequest req;
- invariant(!_state->getRegistrationId().empty());
- req.setVersion(kProtocolVersion);
+ req.setVersion(kMaxProtocolVersion);
req.setLocalTime(client->getServiceContext()->getPreciseClockSource()->now());
req.setEncoding(MetricsEncodingEnum::snappy);
@@ -781,6 +793,8 @@ void FreeMonProcessor::doAsyncMetricsComplete(
// Disable free monitoring on validation errors
_state->setState(StorageStateEnum::disabled);
+ _registrationStatus = FreeMonRegistrationStatus::kDisabled;
+
writeState(client);
// If validation fails, we do not retry
@@ -793,6 +807,7 @@ void FreeMonProcessor::doAsyncMetricsComplete(
FreeMonStorage::deleteState(opCtxUnique.get());
_state->setState(StorageStateEnum::pending);
+ _registrationStatus = FreeMonRegistrationStatus::kDisabled;
// Clear out the in-memory state
_lastReadState = boost::none;
@@ -833,9 +848,13 @@ void FreeMonProcessor::doAsyncMetricsComplete(
_metricsRetry->setMin(Seconds(resp.getReportingInterval()));
_metricsRetry->reset();
- // Enqueue next metrics upload
- enqueue(FreeMonMessage::createWithDeadline(FreeMonMessageType::MetricsSend,
- _metricsRetry->getNextDeadline(client)));
+ if (resp.getResendRegistration().is_initialized() && resp.getResendRegistration()) {
+ enqueue(FreeMonRegisterCommandMessage::createNow(_tags));
+ } else {
+ // Enqueue next metrics upload
+ enqueue(FreeMonMessage::createWithDeadline(FreeMonMessageType::MetricsSend,
+ _metricsRetry->getNextDeadline(client)));
+ }
}
void FreeMonProcessor::doAsyncMetricsFail(
@@ -952,6 +971,7 @@ void FreeMonProcessor::doNotifyOnDelete(Client* client) {
// So we mark the internal state as disabled which stop registration and metrics send
_state->setState(StorageStateEnum::pending);
+ _registrationStatus = FreeMonRegistrationStatus::kDisabled;
// Clear out the in-memory state
_lastReadState = boost::none;
diff --git a/src/mongo/db/free_mon/free_mon_processor.h b/src/mongo/db/free_mon/free_mon_processor.h
index cfaf1b504ad..f16a810f5b7 100644
--- a/src/mongo/db/free_mon/free_mon_processor.h
+++ b/src/mongo/db/free_mon/free_mon_processor.h
@@ -272,6 +272,27 @@ private:
size_t _count;
};
+/**
+ * In-memory registration status
+ *
+ * Ensures primaries and secondaries register separately
+ */
+enum class FreeMonRegistrationStatus {
+ /**
+ * Free monitoring is not enabled - default state.
+ */
+ kDisabled,
+
+ /**
+ * Registration in progress.
+ */
+ kPending,
+
+ /**
+ * Free Monitoring is enabled.
+ */
+ kEnabled,
+};
/**
* Process in an Agent in a Agent/Message Passing model.
@@ -479,6 +500,9 @@ private:
// Pending update to disk
boost::synchronized_value<FreeMonStorageState> _state;
+ // In-memory registration status
+ FreeMonRegistrationStatus _registrationStatus{FreeMonRegistrationStatus::kDisabled};
+
// Countdown launch to support manual cranking
FreeMonCountdownLatch _countdown;
diff --git a/src/mongo/db/free_mon/free_mon_protocol.idl b/src/mongo/db/free_mon/free_mon_protocol.idl
index b08e0638a0f..30fd9081ad3 100644
--- a/src/mongo/db/free_mon/free_mon_protocol.idl
+++ b/src/mongo/db/free_mon/free_mon_protocol.idl
@@ -95,7 +95,10 @@ structs:
description: "Metrics Blob"
type: bindata_generic
-
+ # History
+ # -------
+ # Version 2 - added resendRegistration bool
+ #
FreeMonMetricsResponse:
description: "Metrics Response from Cloud Server"
fields:
@@ -127,3 +130,7 @@ structs:
description: "Message to display to user to remind them about service"
type: string
optional: true
+ resendRegistration:
+ description: "If true, resend registration to server"
+ type: bool
+ optional: true