mirror of https://github.com/mongodb/mongo
SERVER-78987 Remove the free monitoring code from mongodb/mongo repo
(cherry picked from commit 00c97452ae)
This commit is contained in:
parent
6928142d06
commit
c0152efc86
26
SConstruct
26
SConstruct
|
|
@ -359,13 +359,6 @@ add_option('gcov',
|
||||||
nargs=0,
|
nargs=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
add_option('enable-free-mon',
|
|
||||||
choices=["auto", "on", "off"],
|
|
||||||
default="auto",
|
|
||||||
help='Disable support for Free Monitoring to avoid HTTP client library dependencies',
|
|
||||||
type='choice',
|
|
||||||
)
|
|
||||||
|
|
||||||
add_option('enable-http-client',
|
add_option('enable-http-client',
|
||||||
choices=["auto", "on", "off"],
|
choices=["auto", "on", "off"],
|
||||||
default="auto",
|
default="auto",
|
||||||
|
|
@ -2694,7 +2687,6 @@ if has_ninja_module:
|
||||||
|
|
||||||
# --- check system ---
|
# --- check system ---
|
||||||
ssl_provider = None
|
ssl_provider = None
|
||||||
free_monitoring = get_option("enable-free-mon")
|
|
||||||
http_client = get_option("enable-http-client")
|
http_client = get_option("enable-http-client")
|
||||||
|
|
||||||
def isSanitizerEnabled(self, sanitizerName):
|
def isSanitizerEnabled(self, sanitizerName):
|
||||||
|
|
@ -2709,7 +2701,6 @@ env.AddMethod(isSanitizerEnabled, 'IsSanitizerEnabled')
|
||||||
def doConfigure(myenv):
|
def doConfigure(myenv):
|
||||||
global wiredtiger
|
global wiredtiger
|
||||||
global ssl_provider
|
global ssl_provider
|
||||||
global free_monitoring
|
|
||||||
global http_client
|
global http_client
|
||||||
|
|
||||||
# Check that the compilers work.
|
# Check that the compilers work.
|
||||||
|
|
@ -4413,16 +4404,6 @@ def doConfigure(myenv):
|
||||||
# ask each module to configure itself and the build environment.
|
# ask each module to configure itself and the build environment.
|
||||||
moduleconfig.configure_modules(mongo_modules, conf)
|
moduleconfig.configure_modules(mongo_modules, conf)
|
||||||
|
|
||||||
# Resolve --enable-free-mon
|
|
||||||
if free_monitoring == "auto":
|
|
||||||
if 'enterprise' not in conf.env['MONGO_MODULES']:
|
|
||||||
free_monitoring = "on"
|
|
||||||
else:
|
|
||||||
free_monitoring = "off"
|
|
||||||
|
|
||||||
if free_monitoring == "on":
|
|
||||||
checkHTTPLib(required=True)
|
|
||||||
|
|
||||||
# Resolve --enable-http-client
|
# Resolve --enable-http-client
|
||||||
if http_client == "auto":
|
if http_client == "auto":
|
||||||
if checkHTTPLib():
|
if checkHTTPLib():
|
||||||
|
|
@ -4433,12 +4414,6 @@ def doConfigure(myenv):
|
||||||
elif http_client == "on":
|
elif http_client == "on":
|
||||||
checkHTTPLib(required=True)
|
checkHTTPLib(required=True)
|
||||||
|
|
||||||
# Sanity check.
|
|
||||||
# We know that http_client was explicitly disabled here,
|
|
||||||
# because the free_monitoring check would have failed if no http lib were available.
|
|
||||||
if (free_monitoring == "on") and (http_client == "off"):
|
|
||||||
env.ConfError("FreeMonitoring requires an HTTP client which has been explicitly disabled")
|
|
||||||
|
|
||||||
if env['TARGET_ARCH'] == "ppc64le":
|
if env['TARGET_ARCH'] == "ppc64le":
|
||||||
# This checks for an altivec optimization we use in full text search.
|
# This checks for an altivec optimization we use in full text search.
|
||||||
# Different versions of gcc appear to put output bytes in different
|
# Different versions of gcc appear to put output bytes in different
|
||||||
|
|
@ -5247,7 +5222,6 @@ module_sconscripts = moduleconfig.get_module_sconscripts(mongo_modules)
|
||||||
Export([
|
Export([
|
||||||
'debugBuild',
|
'debugBuild',
|
||||||
'endian',
|
'endian',
|
||||||
'free_monitoring',
|
|
||||||
'get_option',
|
'get_option',
|
||||||
'has_option',
|
'has_option',
|
||||||
'http_client',
|
'http_client',
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
test_kind: js_test
|
|
||||||
|
|
||||||
selector:
|
|
||||||
roots:
|
|
||||||
- jstests/free_mon/*.js
|
|
||||||
|
|
||||||
executor:
|
|
||||||
config:
|
|
||||||
shell_options:
|
|
||||||
nodb: ''
|
|
||||||
readMode: commands
|
|
||||||
|
|
@ -857,79 +857,6 @@ For usage examples, see:
|
||||||
\fBConvert Command\-Line Options to YAML\f1
|
\fBConvert Command\-Line Options to YAML\f1
|
||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.SS FREE MONITORING
|
|
||||||
.PP
|
|
||||||
\fBmongod \-\-enableFreeMonitoring\f1
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Available for MongoDB Community Edition.
|
|
||||||
.PP
|
|
||||||
Enables or disables \fBfree MongoDB Cloud monitoring\f1\&. \fB\-\-enableFreeMonitoring\f1\f1 accepts the following
|
|
||||||
values:
|
|
||||||
.RS
|
|
||||||
.IP \(bu 2
|
|
||||||
.RS
|
|
||||||
.IP \(bu 4
|
|
||||||
Value
|
|
||||||
.IP \(bu 4
|
|
||||||
Description
|
|
||||||
.RE
|
|
||||||
.IP \(bu 2
|
|
||||||
.RS
|
|
||||||
.IP \(bu 4
|
|
||||||
\fBruntime\f1
|
|
||||||
.IP \(bu 4
|
|
||||||
Default. You can enable or disable free monitoring during
|
|
||||||
runtime.
|
|
||||||
.IP
|
|
||||||
To enable or disable free monitoring during runtime, see
|
|
||||||
\fBdb.enableFreeMonitoring()\f1\f1 and
|
|
||||||
\fBdb.disableFreeMonitoring()\f1\f1\&.
|
|
||||||
.IP
|
|
||||||
To enable or disable free monitoring during runtime when
|
|
||||||
running with access control, users must have required
|
|
||||||
privileges. See \fBdb.enableFreeMonitoring()\f1\f1 and
|
|
||||||
\fBdb.disableFreeMonitoring()\f1\f1 for details.
|
|
||||||
.RE
|
|
||||||
.IP \(bu 2
|
|
||||||
.RS
|
|
||||||
.IP \(bu 4
|
|
||||||
\fBon\f1
|
|
||||||
.IP \(bu 4
|
|
||||||
Enables free monitoring at startup; i.e. registers for free
|
|
||||||
monitoring. When enabled at startup, you cannot disable free
|
|
||||||
monitoring during runtime.
|
|
||||||
.RE
|
|
||||||
.IP \(bu 2
|
|
||||||
.RS
|
|
||||||
.IP \(bu 4
|
|
||||||
\fBoff\f1
|
|
||||||
.IP \(bu 4
|
|
||||||
Disables free monitoring at startup, regardless of whether
|
|
||||||
you have previously registered for free monitoring. When disabled at startup,
|
|
||||||
you cannot enable free monitoring during runtime.
|
|
||||||
.RE
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
Once enabled, the free monitoring state remains enabled until
|
|
||||||
explicitly disabled. That is, you do not need to re\-enable each time
|
|
||||||
you start the server.
|
|
||||||
.PP
|
|
||||||
For the corresponding configuration file setting, see
|
|
||||||
\fBcloud.monitoring.free.state\f1\f1\&.
|
|
||||||
.RE
|
|
||||||
.PP
|
|
||||||
\fBmongod \-\-freeMonitoringTag\f1
|
|
||||||
.RS
|
|
||||||
.PP
|
|
||||||
Available for MongoDB Community Edition.
|
|
||||||
.PP
|
|
||||||
Optional tag to describe environment context. The tag can be sent as
|
|
||||||
part of the \fBfree MongoDB Cloud monitoring\f1 registration at start up.
|
|
||||||
.PP
|
|
||||||
For the corresponding configuration file setting, see
|
|
||||||
\fBcloud.monitoring.free.tags\f1\f1\&.
|
|
||||||
.RE
|
|
||||||
.SS LDAP AUTHENTICATION OR AUTHORIZATION OPTIONS
|
.SS LDAP AUTHENTICATION OR AUTHORIZATION OPTIONS
|
||||||
.PP
|
.PP
|
||||||
\fBmongod \-\-ldapServers\f1
|
\fBmongod \-\-ldapServers\f1
|
||||||
|
|
@ -1324,9 +1251,9 @@ anything preceeding the suffix into a regex capture group.
|
||||||
{
|
{
|
||||||
match: "(.+)@DBA.EXAMPLE.COM",
|
match: "(.+)@DBA.EXAMPLE.COM",
|
||||||
ldapQuery: "ou=dba,dc=example,dc=com??one?(user={0})"
|
ldapQuery: "ou=dba,dc=example,dc=com??one?(user={0})"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
]"
|
]"
|
||||||
.EE
|
.EE
|
||||||
.PP
|
.PP
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,3 @@
|
||||||
- [Identity and Access Management](https://github.com/mongodb/mongo/blob/master/src/mongo/db/auth/README.md)
|
- [Identity and Access Management](https://github.com/mongodb/mongo/blob/master/src/mongo/db/auth/README.md)
|
||||||
- [TLS](https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/README.md)
|
- [TLS](https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/README.md)
|
||||||
- [FTDC](https://github.com/mongodb/mongo/blob/master/src/mongo/db/ftdc/README.md)
|
- [FTDC](https://github.com/mongodb/mongo/blob/master/src/mongo/db/ftdc/README.md)
|
||||||
- [Free Monitoring](https://github.com/mongodb/mongo/blob/master/src/mongo/db/free_mon/README.md)
|
|
||||||
|
|
|
||||||
|
|
@ -2347,7 +2347,6 @@ tasks:
|
||||||
task_compile_flags: &embedded_sdk_compile_flags >-
|
task_compile_flags: &embedded_sdk_compile_flags >-
|
||||||
--allocator=system
|
--allocator=system
|
||||||
--dbg=off
|
--dbg=off
|
||||||
--enable-free-mon=off
|
|
||||||
--enable-http-client=off
|
--enable-http-client=off
|
||||||
--js-engine=none
|
--js-engine=none
|
||||||
--opt=size
|
--opt=size
|
||||||
|
|
@ -2487,7 +2486,6 @@ tasks:
|
||||||
task_compile_flags: >-
|
task_compile_flags: >-
|
||||||
--dbg=off
|
--dbg=off
|
||||||
--link-model=dynamic-sdk
|
--link-model=dynamic-sdk
|
||||||
--enable-free-mon=off
|
|
||||||
--ssl=off
|
--ssl=off
|
||||||
--enable-http-client=off
|
--enable-http-client=off
|
||||||
--modules=
|
--modules=
|
||||||
|
|
@ -2520,7 +2518,6 @@ tasks:
|
||||||
compiling_for_test: true
|
compiling_for_test: true
|
||||||
task_compile_flags: >-
|
task_compile_flags: >-
|
||||||
--dbg=off
|
--dbg=off
|
||||||
--enable-free-mon=off
|
|
||||||
--ssl=off
|
--ssl=off
|
||||||
--enable-http-client=off
|
--enable-http-client=off
|
||||||
--modules=
|
--modules=
|
||||||
|
|
@ -5814,15 +5811,6 @@ tasks:
|
||||||
resmoke_args: --suites=watchdog --storageEngine=inMemory
|
resmoke_args: --suites=watchdog --storageEngine=inMemory
|
||||||
resmoke_jobs_max: 1
|
resmoke_jobs_max: 1
|
||||||
|
|
||||||
- <<: *task_template
|
|
||||||
name: free_monitoring
|
|
||||||
commands:
|
|
||||||
- func: "do setup"
|
|
||||||
- func: "run tests"
|
|
||||||
vars:
|
|
||||||
resmoke_args: --suites=free_monitoring --storageEngine=wiredTiger
|
|
||||||
resmoke_jobs_max: 1
|
|
||||||
|
|
||||||
- <<: *task_template
|
- <<: *task_template
|
||||||
name: client_encrypt
|
name: client_encrypt
|
||||||
tags: ["ssl", "encrypt"]
|
tags: ["ssl", "encrypt"]
|
||||||
|
|
@ -7230,7 +7218,7 @@ buildvariants:
|
||||||
run_on:
|
run_on:
|
||||||
- rhel80-small
|
- rhel80-small
|
||||||
expansions:
|
expansions:
|
||||||
compile_flags: -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --enable-free-mon=off --enable-http-client=off
|
compile_flags: -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --enable-http-client=off
|
||||||
test_flags: >-
|
test_flags: >-
|
||||||
--excludeWithAnyTags=requires_http_client
|
--excludeWithAnyTags=requires_http_client
|
||||||
--repeatSuites=10
|
--repeatSuites=10
|
||||||
|
|
@ -7269,7 +7257,7 @@ buildvariants:
|
||||||
- rhel80-medium
|
- rhel80-medium
|
||||||
expansions:
|
expansions:
|
||||||
resmoke_jobs_factor: 0.5 # Avoid starting too many mongod's
|
resmoke_jobs_factor: 0.5 # Avoid starting too many mongod's
|
||||||
compile_flags: --dbg=on --opt=on -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --enable-free-mon=on --enable-http-client=on --link-model=dynamic
|
compile_flags: --dbg=on --opt=on -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --enable-http-client=on --link-model=dynamic
|
||||||
scons_cache_scope: shared
|
scons_cache_scope: shared
|
||||||
scons_cache_mode: all
|
scons_cache_mode: all
|
||||||
test_flags: --excludeWithAnyTags=requires_http_client
|
test_flags: --excludeWithAnyTags=requires_http_client
|
||||||
|
|
@ -7298,7 +7286,6 @@ buildvariants:
|
||||||
- name: .change_streams !.secondary_reads
|
- name: .change_streams !.secondary_reads
|
||||||
- name: .misc_js
|
- name: .misc_js
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: jsCore_txns_large_txns_format
|
- name: jsCore_txns_large_txns_format
|
||||||
- name: jsonSchema
|
- name: jsonSchema
|
||||||
|
|
@ -7333,7 +7320,7 @@ buildvariants:
|
||||||
run_on:
|
run_on:
|
||||||
- rhel80-small
|
- rhel80-small
|
||||||
expansions: &linux-64-required-duroff-expansions
|
expansions: &linux-64-required-duroff-expansions
|
||||||
compile_flags: -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --enable-free-mon=off --enable-http-client=off
|
compile_flags: -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --enable-http-client=off
|
||||||
multiversion_platform: rhel80
|
multiversion_platform: rhel80
|
||||||
multiversion_edition: targeted
|
multiversion_edition: targeted
|
||||||
# Running WiredTiger with --nojournal in a replica set is no longer supported, so this variant
|
# Running WiredTiger with --nojournal in a replica set is no longer supported, so this variant
|
||||||
|
|
@ -7393,7 +7380,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jepsen
|
- name: .jepsen
|
||||||
distros:
|
distros:
|
||||||
- ubuntu1804-build
|
- ubuntu1804-build
|
||||||
|
|
@ -7441,7 +7427,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: libunwind_tests
|
- name: libunwind_tests
|
||||||
|
|
@ -7702,7 +7687,6 @@ buildvariants:
|
||||||
tasks:
|
tasks:
|
||||||
- name: compile_test_and_package_serial_TG
|
- name: compile_test_and_package_serial_TG
|
||||||
- name: build_variant_gen
|
- name: build_variant_gen
|
||||||
- name: free_monitoring
|
|
||||||
- name: jsCore
|
- name: jsCore
|
||||||
- name: replica_sets_jscore_passthrough
|
- name: replica_sets_jscore_passthrough
|
||||||
- name: .publish
|
- name: .publish
|
||||||
|
|
@ -7729,7 +7713,6 @@ buildvariants:
|
||||||
tasks:
|
tasks:
|
||||||
- name: compile_test_and_package_serial_TG
|
- name: compile_test_and_package_serial_TG
|
||||||
- name: build_variant_gen
|
- name: build_variant_gen
|
||||||
- name: free_monitoring
|
|
||||||
- name: jsCore
|
- name: jsCore
|
||||||
- name: replica_sets_jscore_passthrough
|
- name: replica_sets_jscore_passthrough
|
||||||
- name: generate_buildid_to_debug_symbols_mapping
|
- name: generate_buildid_to_debug_symbols_mapping
|
||||||
|
|
@ -7765,7 +7748,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: libunwind_tests
|
- name: libunwind_tests
|
||||||
|
|
@ -7901,7 +7883,6 @@ buildvariants:
|
||||||
tasks:
|
tasks:
|
||||||
- name: compile_test_and_package_serial_TG
|
- name: compile_test_and_package_serial_TG
|
||||||
- name: build_variant_gen
|
- name: build_variant_gen
|
||||||
- name: free_monitoring
|
|
||||||
- name: jsCore
|
- name: jsCore
|
||||||
- name: replica_sets_jscore_passthrough
|
- name: replica_sets_jscore_passthrough
|
||||||
- name: .publish
|
- name: .publish
|
||||||
|
|
@ -7994,7 +7975,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: libunwind_tests
|
- name: libunwind_tests
|
||||||
|
|
@ -8096,7 +8076,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: libunwind_tests
|
- name: libunwind_tests
|
||||||
|
|
@ -8195,7 +8174,6 @@ buildvariants:
|
||||||
- amazon2-arm64-large
|
- amazon2-arm64-large
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -8277,7 +8255,6 @@ buildvariants:
|
||||||
distros:
|
distros:
|
||||||
- windows-vsCurrent-large
|
- windows-vsCurrent-large
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: initial_sync_fuzzer_gen
|
- name: initial_sync_fuzzer_gen
|
||||||
- name: .jscore .common !.auth !.sharding
|
- name: .jscore .common !.auth !.sharding
|
||||||
- name: jsCore_txns_large_txns_format
|
- name: jsCore_txns_large_txns_format
|
||||||
|
|
@ -8517,7 +8494,6 @@ buildvariants:
|
||||||
- windows-vsCurrent-large
|
- windows-vsCurrent-large
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common !.auth
|
- name: .jscore .common !.auth
|
||||||
- name: jsonSchema
|
- name: jsonSchema
|
||||||
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns
|
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns
|
||||||
|
|
@ -8659,7 +8635,6 @@ buildvariants:
|
||||||
- name: .misc_js
|
- name: .misc_js
|
||||||
- name: .concurrency !.ubsan !.no_txns !.debug_only !.kill_terminate
|
- name: .concurrency !.ubsan !.no_txns !.debug_only !.kill_terminate
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: initial_sync_fuzzer_gen
|
- name: initial_sync_fuzzer_gen
|
||||||
- name: .jscore .common !.auth
|
- name: .jscore .common !.auth
|
||||||
- name: jsCore_txns_large_txns_format
|
- name: jsCore_txns_large_txns_format
|
||||||
|
|
@ -9813,7 +9788,6 @@ buildvariants:
|
||||||
- rhel70
|
- rhel70
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -9860,7 +9834,6 @@ buildvariants:
|
||||||
- rhel80-build
|
- rhel80-build
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -9906,7 +9879,6 @@ buildvariants:
|
||||||
- rhel82-arm64-large
|
- rhel82-arm64-large
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -10306,7 +10278,6 @@ buildvariants:
|
||||||
- suse12-sp5-large
|
- suse12-sp5-large
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common !.decimal
|
- name: .jscore .common !.decimal
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: multiversion_gen
|
- name: multiversion_gen
|
||||||
|
|
@ -10393,7 +10364,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common !.decimal
|
- name: .jscore .common !.decimal
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -10489,7 +10459,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common !.decimal
|
- name: .jscore .common !.decimal
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -10579,7 +10548,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common !.decimal
|
- name: .jscore .common !.decimal
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -10669,7 +10637,6 @@ buildvariants:
|
||||||
- name: .concurrency .common
|
- name: .concurrency .common
|
||||||
- name: concurrency_replication_causal_consistency_gen
|
- name: concurrency_replication_causal_consistency_gen
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jscore .common !.decimal
|
- name: .jscore .common !.decimal
|
||||||
- name: .jstestfuzz .common
|
- name: .jstestfuzz .common
|
||||||
- name: .logical_session_cache .one_sec
|
- name: .logical_session_cache .one_sec
|
||||||
|
|
@ -10865,7 +10832,7 @@ buildvariants:
|
||||||
# If you add anything to san_options, make sure the appropriate changes are
|
# If you add anything to san_options, make sure the appropriate changes are
|
||||||
# also made to SConstruct.
|
# also made to SConstruct.
|
||||||
san_options: LSAN_OPTIONS="suppressions=etc/lsan.suppressions:report_objects=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer" ASAN_OPTIONS="detect_leaks=1:check_initialization_order=true:strict_init_order=true:abort_on_error=1:disable_coredump=0:handle_abort=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
|
san_options: LSAN_OPTIONS="suppressions=etc/lsan.suppressions:report_objects=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer" ASAN_OPTIONS="detect_leaks=1:check_initialization_order=true:strict_init_order=true:abort_on_error=1:disable_coredump=0:handle_abort=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
|
||||||
compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --allocator=system --sanitize=address --ssl --ocsp-stapling=off --enable-free-mon=on -j$(grep -c ^processor /proc/cpuinfo)
|
compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --allocator=system --sanitize=address --ssl --ocsp-stapling=off -j$(grep -c ^processor /proc/cpuinfo)
|
||||||
test_flags: --excludeWithAnyTags=requires_fast_memory,requires_ocsp_stapling,requires_increased_memlock_limits
|
test_flags: --excludeWithAnyTags=requires_fast_memory,requires_ocsp_stapling,requires_increased_memlock_limits
|
||||||
multiversion_platform: ubuntu1804
|
multiversion_platform: ubuntu1804
|
||||||
multiversion_edition: enterprise
|
multiversion_edition: enterprise
|
||||||
|
|
@ -10887,7 +10854,6 @@ buildvariants:
|
||||||
- name: .misc_js
|
- name: .misc_js
|
||||||
- name: .concurrency !.ubsan !.no_txns !.kill_terminate
|
- name: .concurrency !.ubsan !.no_txns !.kill_terminate
|
||||||
- name: .encrypt
|
- name: .encrypt
|
||||||
- name: free_monitoring
|
|
||||||
- name: external_auth
|
- name: external_auth
|
||||||
- name: external_auth_aws
|
- name: external_auth_aws
|
||||||
- name: initial_sync_fuzzer_gen
|
- name: initial_sync_fuzzer_gen
|
||||||
|
|
@ -10944,7 +10910,6 @@ buildvariants:
|
||||||
- name: compile_test_and_package_serial_TG
|
- name: compile_test_and_package_serial_TG
|
||||||
- name: build_variant_gen
|
- name: build_variant_gen
|
||||||
- name: .aggfuzzer .common
|
- name: .aggfuzzer .common
|
||||||
- name: free_monitoring
|
|
||||||
- name: .jstestfuzz !.initsync
|
- name: .jstestfuzz !.initsync
|
||||||
|
|
||||||
- &ubuntu1804-debug-ubsan-template
|
- &ubuntu1804-debug-ubsan-template
|
||||||
|
|
@ -10961,7 +10926,7 @@ buildvariants:
|
||||||
# If you add anything to san_options, make sure the appropriate changes are
|
# If you add anything to san_options, make sure the appropriate changes are
|
||||||
# also made to SConstruct.
|
# also made to SConstruct.
|
||||||
san_options: UBSAN_OPTIONS="print_stacktrace=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
|
san_options: UBSAN_OPTIONS="print_stacktrace=1:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
|
||||||
compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --sanitize=undefined --ssl --ocsp-stapling=off --enable-free-mon=on -j$(grep -c ^processor /proc/cpuinfo)
|
compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --sanitize=undefined --ssl --ocsp-stapling=off -j$(grep -c ^processor /proc/cpuinfo)
|
||||||
test_flags: --excludeWithAnyTags=requires_ocsp_stapling,requires_increased_memlock_limits
|
test_flags: --excludeWithAnyTags=requires_ocsp_stapling,requires_increased_memlock_limits
|
||||||
multiversion_platform: ubuntu1804
|
multiversion_platform: ubuntu1804
|
||||||
multiversion_edition: enterprise
|
multiversion_edition: enterprise
|
||||||
|
|
@ -10982,7 +10947,6 @@ buildvariants:
|
||||||
- name: .concurrency !.no_txns !.repl !.kill_terminate
|
- name: .concurrency !.no_txns !.repl !.kill_terminate
|
||||||
- name: disk_wiredtiger
|
- name: disk_wiredtiger
|
||||||
- name: .encrypt
|
- name: .encrypt
|
||||||
- name: free_monitoring
|
|
||||||
- name: initial_sync_fuzzer_gen
|
- name: initial_sync_fuzzer_gen
|
||||||
- name: .jscore .common
|
- name: .jscore .common
|
||||||
- name: jsCore_minimum_batch_size
|
- name: jsCore_minimum_batch_size
|
||||||
|
|
@ -11096,12 +11060,8 @@ buildvariants:
|
||||||
# TODO SERVER-48490: report_thread_leaks=0 suppresses reporting
|
# TODO SERVER-48490: report_thread_leaks=0 suppresses reporting
|
||||||
# thread leaks, which we have because we don't do a clean shutdown
|
# thread leaks, which we have because we don't do a clean shutdown
|
||||||
# of the ServiceContext.
|
# of the ServiceContext.
|
||||||
#
|
|
||||||
san_options: TSAN_OPTIONS="halt_on_error=1:report_thread_leaks=0:die_after_fork=0:suppressions=etc/tsan.suppressions:external_symbolizer_path=/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
|
|
||||||
# TODO: Remove some of the excluded tags when the ephemeralForTest storage engine is
|
|
||||||
# further along in development: https://jira.mongodb.org/browse/SERVER-48325
|
|
||||||
test_flags: --storageEngine=ephemeralForTest --excludeWithAnyTags=requires_persistence,requires_journaling,uses_transactions,requires_wiredtiger,requires_snapshot_read,requires_majority_read_concern
|
test_flags: --storageEngine=ephemeralForTest --excludeWithAnyTags=requires_persistence,requires_journaling,uses_transactions,requires_wiredtiger,requires_snapshot_read,requires_majority_read_concern
|
||||||
compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --allocator=system --sanitize=thread --ssl --enable-free-mon=on --use-libunwind=off -j$(grep -c ^processor /proc/cpuinfo)
|
compile_flags: --variables-files=etc/scons/mongodbtoolchain_v3_clang.vars --dbg=on --opt=on --allocator=system --sanitize=thread --ssl --use-libunwind=off -j$(grep -c ^processor /proc/cpuinfo)
|
||||||
# Avoid starting too many mongod's under TSAN build.
|
# Avoid starting too many mongod's under TSAN build.
|
||||||
resmoke_jobs_factor: 0.3
|
resmoke_jobs_factor: 0.3
|
||||||
scons_cache_scope: shared
|
scons_cache_scope: shared
|
||||||
|
|
|
||||||
|
|
@ -4159,16 +4159,6 @@ var authCommandsLib = {
|
||||||
{runOnDb: secondDbName, roles: {}}
|
{runOnDb: secondDbName, roles: {}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
testname: "getFreeMonitoringStatus",
|
|
||||||
skipSharded: true,
|
|
||||||
command: {getFreeMonitoringStatus: 1},
|
|
||||||
testcases: [{
|
|
||||||
runOnDb: adminDbName,
|
|
||||||
roles: {clusterMonitor: 1, clusterAdmin: 1, root: 1, __system: 1},
|
|
||||||
privileges: [{resource: {cluster: true}, actions: ["checkFreeMonitoringStatus"]}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
testname: "getLastError",
|
testname: "getLastError",
|
||||||
command: {getLastError: 1},
|
command: {getLastError: 1},
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,6 @@ let viewsCommandTests = {
|
||||||
getCmdLineOpts: {skip: isUnrelated},
|
getCmdLineOpts: {skip: isUnrelated},
|
||||||
getDefaultRWConcern: {skip: isUnrelated},
|
getDefaultRWConcern: {skip: isUnrelated},
|
||||||
getDiagnosticData: {skip: isUnrelated},
|
getDiagnosticData: {skip: isUnrelated},
|
||||||
getFreeMonitoringStatus: {skip: isUnrelated},
|
|
||||||
getLastError: {skip: isUnrelated},
|
getLastError: {skip: isUnrelated},
|
||||||
getLog: {skip: isUnrelated},
|
getLog: {skip: isUnrelated},
|
||||||
getMore: {
|
getMore: {
|
||||||
|
|
@ -566,7 +565,6 @@ let viewsCommandTests = {
|
||||||
setCommittedSnapshot: {skip: isAnInternalCommand},
|
setCommittedSnapshot: {skip: isAnInternalCommand},
|
||||||
setDefaultRWConcern: {skip: isUnrelated},
|
setDefaultRWConcern: {skip: isUnrelated},
|
||||||
setFeatureCompatibilityVersion: {skip: isUnrelated},
|
setFeatureCompatibilityVersion: {skip: isUnrelated},
|
||||||
setFreeMonitoring: {skip: isUnrelated},
|
|
||||||
setProfilingFilterGlobally: {skip: isUnrelated},
|
setProfilingFilterGlobally: {skip: isUnrelated},
|
||||||
setParameter: {skip: isUnrelated},
|
setParameter: {skip: isUnrelated},
|
||||||
setShardVersion: {skip: isUnrelated},
|
setShardVersion: {skip: isUnrelated},
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
// Validate connect message display.
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const mock_web = new FreeMonWebServer();
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
const mongod = MongoRunner.runMongod({
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
});
|
|
||||||
assert.neq(mongod, null, 'mongod not running');
|
|
||||||
const admin = mongod.getDB('admin');
|
|
||||||
|
|
||||||
// state === 'enabled'.
|
|
||||||
admin.enableFreeMonitoring();
|
|
||||||
WaitForRegistration(mongod);
|
|
||||||
const reminder = "To see your monitoring data";
|
|
||||||
assert(FreeMonGetStatus(mongod).userReminder.includes(reminder), 'userReminder not found');
|
|
||||||
|
|
||||||
// Cleanup.
|
|
||||||
MongoRunner.stopMongod(mongod);
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// Validate disable works
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
freeMonitoringTag: "foo",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const conn = MongoRunner.runMongod(options);
|
|
||||||
assert.neq(null, conn, 'mongod was unable to start up');
|
|
||||||
|
|
||||||
assert.commandWorked(conn.adminCommand({setFreeMonitoring: 1, action: "disable"}));
|
|
||||||
|
|
||||||
const stats = mock_web.queryStats();
|
|
||||||
print(tojson(stats));
|
|
||||||
|
|
||||||
assert.eq(stats.registers, 0);
|
|
||||||
|
|
||||||
assert.eq(FreeMonGetStatus(conn).state, "disabled");
|
|
||||||
|
|
||||||
assert.eq(FreeMonGetServerStatus(conn).state, "disabled");
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
// Validate registration retries if the web server is down.
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer(FAULT_FAIL_REGISTER);
|
|
||||||
|
|
||||||
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');
|
|
||||||
const admin = conn.getDB('admin');
|
|
||||||
|
|
||||||
mock_web.waitRegisters(3);
|
|
||||||
|
|
||||||
assert.soon(function() {
|
|
||||||
const freeMonStats = FreeMonGetServerStatus(conn);
|
|
||||||
return freeMonStats.registerErrors >= 3;
|
|
||||||
}, "Failed to wait for 3 register errors: " + FreeMonGetServerStatus(conn), 20 * 1000);
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// Ensure free monitoring gives up if registration fails
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer(FAULT_INVALID_REGISTER);
|
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
mock_web.waitRegisters(1);
|
|
||||||
|
|
||||||
// Sleep for some more time in case free monitoring would still try to register
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
// Ensure it only tried to register once since we gave it a bad response.
|
|
||||||
const stats = mock_web.queryStats();
|
|
||||||
print(tojson(stats));
|
|
||||||
|
|
||||||
assert.eq(stats.registers, 1);
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
// Ensure free monitoring gives up if metrics returns halt
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer(FAULT_HALT_METRICS_5);
|
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
mock_web.waitMetrics(6);
|
|
||||||
|
|
||||||
// It gets marked as disabled on halt
|
|
||||||
WaitForUnRegistration(conn);
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// Ensure free monitoring gives up if metrics returns permanently delete
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer(FAULT_PERMANENTLY_DELETE_AFTER_3);
|
|
||||||
|
|
||||||
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');
|
|
||||||
|
|
||||||
mock_web.waitMetrics(4);
|
|
||||||
|
|
||||||
// Make sure the registration document gets removed
|
|
||||||
assert.soon(
|
|
||||||
function() {
|
|
||||||
const reg = FreeMonGetRegistration(conn);
|
|
||||||
return reg === undefined;
|
|
||||||
},
|
|
||||||
"Failed to wait for free mon document to be removed: " + FreeMonGetRegistration(conn),
|
|
||||||
20 * 1000);
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
// Validate registration works
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const localTime = Date.now();
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "on",
|
|
||||||
freeMonitoringTag: "foo",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const conn = MongoRunner.runMongod(options);
|
|
||||||
assert.neq(null, conn, 'mongod was unable to start up');
|
|
||||||
|
|
||||||
WaitForRegistration(conn);
|
|
||||||
|
|
||||||
const stats = mock_web.queryStats();
|
|
||||||
print(tojson(stats));
|
|
||||||
|
|
||||||
assert.eq(stats.registers, 1);
|
|
||||||
|
|
||||||
const last_register = mock_web.query("last_register");
|
|
||||||
print(tojson(last_register));
|
|
||||||
|
|
||||||
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);
|
|
||||||
assert.eq(last_register.payload.storageEngine.readOnly, false);
|
|
||||||
assert.eq(last_register.payload.isMaster.ok, 1);
|
|
||||||
assert.eq(last_register.tags, ["foo"]);
|
|
||||||
|
|
||||||
mock_web.waitMetrics(2);
|
|
||||||
|
|
||||||
const last_metrics = mock_web.query("last_metrics");
|
|
||||||
print(tojson(last_metrics));
|
|
||||||
|
|
||||||
assert.eq(last_metrics.version, 2);
|
|
||||||
assert.gt(new Date().setTime(last_metrics.localTime["$date"]), localTime);
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
// Validate registration works via a command. Validate it can be registered and unregistered
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const conn = MongoRunner.runMongod(options);
|
|
||||||
assert.neq(null, conn, 'mongod was unable to start up');
|
|
||||||
|
|
||||||
// Wait an arbitrary amount of time to allow the processor loop to start.
|
|
||||||
sleep(10 * 1000);
|
|
||||||
|
|
||||||
// Then verify that no registrations happened since we haven't runtime enabled yed.
|
|
||||||
assert.eq('undecided', FreeMonGetStatus(conn).state, "Initial state should be 'undecided'");
|
|
||||||
assert.eq(0, mock_web.queryStats().registers, "mongod registered without enabling free_mod");
|
|
||||||
|
|
||||||
assert.commandWorked(conn.adminCommand({setFreeMonitoring: 1, action: "enable"}));
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(conn, 'enabled');
|
|
||||||
|
|
||||||
// The command should either timeout or suceed after registration is complete
|
|
||||||
const retStatus1 = FreeMonGetStatus(conn);
|
|
||||||
assert.eq(retStatus1.state, "enabled", tojson(retStatus1));
|
|
||||||
|
|
||||||
const stats = mock_web.queryStats();
|
|
||||||
print(tojson(stats));
|
|
||||||
|
|
||||||
assert.eq(stats.registers, 1);
|
|
||||||
|
|
||||||
const last_register = mock_web.query("last_register");
|
|
||||||
print(tojson(last_register));
|
|
||||||
|
|
||||||
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);
|
|
||||||
assert.eq(last_register.payload.isMaster.ok, 1);
|
|
||||||
|
|
||||||
mock_web.waitMetrics(2);
|
|
||||||
|
|
||||||
const last_metrics = mock_web.query("last_metrics");
|
|
||||||
print(tojson(last_metrics));
|
|
||||||
|
|
||||||
assert.eq(last_metrics.version, 2);
|
|
||||||
|
|
||||||
assert.commandWorked(conn.adminCommand({setFreeMonitoring: 1, action: "disable"}));
|
|
||||||
|
|
||||||
// Wait for unregistration to occur
|
|
||||||
assert.soon(function() {
|
|
||||||
const regDoc = FreeMonGetRegistration(conn);
|
|
||||||
return regDoc.state == "disabled";
|
|
||||||
}, "Failed to unregister", 60 * 1000);
|
|
||||||
|
|
||||||
const retStatus2 = FreeMonGetStatus(conn);
|
|
||||||
assert.eq(retStatus2.state, "disabled", tojson(retStatus1));
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
// Validate registration does work if free monitoring is disabled.
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "off",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const conn = MongoRunner.runMongod(options);
|
|
||||||
assert.neq(null, conn, 'mongod was unable to start up');
|
|
||||||
|
|
||||||
assert.commandFailed(conn.adminCommand({setFreeMonitoring: 1, action: "enable"}));
|
|
||||||
|
|
||||||
// If it some time in case it actually started to process something.
|
|
||||||
sleep(10 * 1000);
|
|
||||||
|
|
||||||
const retStatus1 = conn.adminCommand({getFreeMonitoringStatus: 1});
|
|
||||||
assert.commandWorked(retStatus1);
|
|
||||||
assert.eq(retStatus1.state, "disabled", tojson(retStatus1));
|
|
||||||
|
|
||||||
const stats = mock_web.queryStats();
|
|
||||||
print(tojson(stats));
|
|
||||||
|
|
||||||
assert.eq(stats.registers, 0);
|
|
||||||
|
|
||||||
assert.commandFailed(conn.adminCommand({setFreeMonitoring: 1, action: "disable"}));
|
|
||||||
|
|
||||||
MongoRunner.stopMongod(conn);
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// 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();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
// Validate a user manipulating system.version for free monitoring does
|
|
||||||
// not crash mongod
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "on",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
|
|
||||||
rst.startSet();
|
|
||||||
rst.initiate();
|
|
||||||
rst.awaitReplication();
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
|
|
||||||
mock_web.waitRegisters(2);
|
|
||||||
|
|
||||||
// For kicks, corrupt the free monitoring storage state to knock free mon offline
|
|
||||||
// and make sure the node does not crash
|
|
||||||
rst.getPrimary().getDB("admin").system.version.update({_id: "free_monitoring"},
|
|
||||||
{$set: {version: 2}});
|
|
||||||
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
rst.stopSet();
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
// Validate a user deleting free monitoring in system.version does
|
|
||||||
// not crash mongod
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "on",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
|
|
||||||
rst.startSet();
|
|
||||||
rst.initiate();
|
|
||||||
rst.awaitReplication();
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
|
|
||||||
mock_web.waitRegisters(2);
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
const qs1 = mock_web.queryStats();
|
|
||||||
|
|
||||||
jsTestLog("Breaking Free Monitoring");
|
|
||||||
|
|
||||||
// For kicks, delete the free monitoring storage state to knock free mon offline
|
|
||||||
// and make sure the node does not crash
|
|
||||||
rst.getPrimary().getDB("admin").system.version.remove({_id: "free_monitoring"});
|
|
||||||
|
|
||||||
jsTestLog("Sleeping for 20s");
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
const qs2 = mock_web.queryStats();
|
|
||||||
|
|
||||||
// Make sure we are back to the initial state.
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'undecided');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'undecided');
|
|
||||||
|
|
||||||
// Verify free monitoring stops but tolerate one additional collection
|
|
||||||
assert.gte(qs1.metrics + 2, qs2.metrics);
|
|
||||||
// Tolerate an additional registration on the secondary side. We may delete the record on the
|
|
||||||
// primary before the secondary processes all pending registrations requests.
|
|
||||||
assert.lte(qs1.registers, qs2.registers);
|
|
||||||
|
|
||||||
// Enable it again to be sure we can resume
|
|
||||||
assert.commandWorked(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "enable"}));
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
rst.stopSet();
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
// Validate that if the endpoint returns halt = true that free monitoring halts
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer(FAULT_HALT_METRICS_5, true);
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "on",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
|
|
||||||
rst.startSet();
|
|
||||||
rst.initiate();
|
|
||||||
rst.awaitReplication();
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
|
|
||||||
mock_web.waitRegisters(2);
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'enabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'enabled');
|
|
||||||
|
|
||||||
mock_web.enableFaults();
|
|
||||||
mock_web.waitFaults(1);
|
|
||||||
|
|
||||||
const qs1 = mock_web.queryStats();
|
|
||||||
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
const qs2 = mock_web.queryStats();
|
|
||||||
|
|
||||||
// Verify free monitoring stops but tolerate one additional collection
|
|
||||||
assert.gte(qs1.metrics + 1, qs2.metrics);
|
|
||||||
assert.eq(qs1.registers, qs2.registers);
|
|
||||||
|
|
||||||
// Halt causes us to disable free monitoring, not return it to initial state.
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'disabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'disabled');
|
|
||||||
|
|
||||||
// Disable the fault so we can re-enable again
|
|
||||||
mock_web.disableFaults();
|
|
||||||
|
|
||||||
// Enable it again to be sure we can resume
|
|
||||||
assert.commandWorked(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "enable"}));
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'enabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'enabled');
|
|
||||||
|
|
||||||
rst.stopSet();
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
// Validate replica set starts up with free monitoring disabled
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "off",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
|
|
||||||
|
|
||||||
rst.startSet();
|
|
||||||
rst.initiate();
|
|
||||||
rst.awaitReplication();
|
|
||||||
|
|
||||||
const retStatus1 = rst.getPrimary().adminCommand({getFreeMonitoringStatus: 1});
|
|
||||||
assert.commandWorked(retStatus1);
|
|
||||||
assert.eq(retStatus1.state, "disabled", tojson(retStatus1));
|
|
||||||
|
|
||||||
const stats = mock_web.queryStats();
|
|
||||||
print(tojson(stats));
|
|
||||||
|
|
||||||
assert.eq(stats.registers, 0);
|
|
||||||
|
|
||||||
assert.commandFailed(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "disable"}));
|
|
||||||
|
|
||||||
rst.stopSet();
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
// Validate that if the endpoint says permanently delete that the state
|
|
||||||
// document is deleted and replicated properly
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer(FAULT_PERMANENTLY_DELETE_AFTER_3, true);
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
enableFreeMonitoring: "on",
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
|
|
||||||
rst.startSet();
|
|
||||||
rst.initiate();
|
|
||||||
rst.awaitReplication();
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
|
|
||||||
mock_web.waitRegisters(2);
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
mock_web.enableFaults();
|
|
||||||
mock_web.waitFaults(1);
|
|
||||||
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
// Make sure we are back to the initial state.
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'undecided');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'undecided');
|
|
||||||
|
|
||||||
// Disable the fault so we can re-enable again
|
|
||||||
mock_web.disableFaults();
|
|
||||||
|
|
||||||
// Enable it again to be sure we can resume
|
|
||||||
assert.commandWorked(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "enable"}));
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
sleep(20 * 1000);
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'enabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'enabled');
|
|
||||||
|
|
||||||
rst.stopSet();
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
// Validate registration works in a replica set
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let mock_web = new FreeMonWebServer();
|
|
||||||
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
verbose: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
const rst = new ReplSetTest({nodes: 2, nodeOptions: options});
|
|
||||||
|
|
||||||
rst.startSet();
|
|
||||||
rst.initiate();
|
|
||||||
rst.awaitReplication();
|
|
||||||
|
|
||||||
sleep(10 * 1000);
|
|
||||||
assert.eq(0, mock_web.queryStats().registers, "mongod registered without enabling free_mod");
|
|
||||||
|
|
||||||
assert.commandWorked(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "enable"}));
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
|
|
||||||
mock_web.waitRegisters(2);
|
|
||||||
|
|
||||||
WaitForRegistration(rst.getPrimary());
|
|
||||||
WaitForRegistration(rst.getSecondary());
|
|
||||||
ValidateFreeMonReplicaSet(rst);
|
|
||||||
|
|
||||||
const last_register = mock_web.query("last_register");
|
|
||||||
print(tojson(last_register));
|
|
||||||
|
|
||||||
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);
|
|
||||||
assert.eq(last_register.payload.isMaster.ok, 1);
|
|
||||||
assert.gte(last_register.payload.replSetGetConfig.config.version, 2);
|
|
||||||
|
|
||||||
function isUUID(val) {
|
|
||||||
// Mock webserver gives us back unpacked BinData/UUID in the form:
|
|
||||||
// { '$uuid': '0123456789abcdef0123456789abcdef' }.
|
|
||||||
if ((typeof val) !== 'object') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const uuid = val['$uuid'];
|
|
||||||
if ((typeof uuid) !== 'string') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return uuid.match(/^[0-9a-fA-F]{32}$/) !== null;
|
|
||||||
}
|
|
||||||
assert.eq(isUUID(last_register.payload.uuid['local.oplog.rs']), true);
|
|
||||||
|
|
||||||
// Restart the secondary
|
|
||||||
var s1 = rst.getSecondary();
|
|
||||||
var s1Id = rst.getNodeId(s1);
|
|
||||||
|
|
||||||
rst.stop(s1Id);
|
|
||||||
rst.waitForState(s1, ReplSetTest.State.DOWN);
|
|
||||||
|
|
||||||
rst.restart(s1Id);
|
|
||||||
|
|
||||||
mock_web.waitRegisters(3);
|
|
||||||
|
|
||||||
// Now disable it
|
|
||||||
assert.commandWorked(rst.getPrimary().adminCommand({setFreeMonitoring: 1, action: "disable"}));
|
|
||||||
|
|
||||||
WaitForUnRegistration(rst.getPrimary());
|
|
||||||
WaitForUnRegistration(rst.getSecondary());
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'disabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'disabled');
|
|
||||||
|
|
||||||
// Restart the secondary with it disabled
|
|
||||||
var s1 = rst.getSecondary();
|
|
||||||
var s1Id = rst.getNodeId(s1);
|
|
||||||
|
|
||||||
rst.stop(s1Id);
|
|
||||||
rst.waitForState(s1, ReplSetTest.State.DOWN);
|
|
||||||
|
|
||||||
rst.restart(s1Id);
|
|
||||||
|
|
||||||
// Make sure it is disabled
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'disabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'disabled');
|
|
||||||
|
|
||||||
rst.stopSet();
|
|
||||||
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
// 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);
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(rst.getPrimary(), 'enabled');
|
|
||||||
WaitForFreeMonServerStatusState(rst.getSecondary(), 'enabled');
|
|
||||||
ValidateFreeMonReplicaSet(rst);
|
|
||||||
|
|
||||||
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();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
// Validate serverStatus output.
|
|
||||||
//
|
|
||||||
load("jstests/free_mon/libs/free_mon.js");
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const mock_web = new FreeMonWebServer();
|
|
||||||
mock_web.start();
|
|
||||||
|
|
||||||
const mongod = MongoRunner.runMongod({
|
|
||||||
setParameter: "cloudFreeMonitoringEndpointURL=" + mock_web.getURL(),
|
|
||||||
});
|
|
||||||
assert.neq(mongod, null, 'mongod not running');
|
|
||||||
const admin = mongod.getDB('admin');
|
|
||||||
|
|
||||||
const kRetryIntervalSecs = 1;
|
|
||||||
function freeMonStats() {
|
|
||||||
return assert.commandWorked(admin.runCommand({serverStatus: 1})).freeMonitoring;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initial state.
|
|
||||||
assert.eq(freeMonStats().state, 'undecided');
|
|
||||||
|
|
||||||
admin.enableFreeMonitoring();
|
|
||||||
WaitForRegistration(mongod);
|
|
||||||
|
|
||||||
// Enabled.
|
|
||||||
const enabled = freeMonStats();
|
|
||||||
assert.eq(enabled.state, 'enabled');
|
|
||||||
assert.eq(enabled.retryIntervalSecs, kRetryIntervalSecs);
|
|
||||||
assert.eq(enabled.registerErrors, 0);
|
|
||||||
assert.eq(enabled.metricsErrors, 0);
|
|
||||||
|
|
||||||
// Explicitly disabled.
|
|
||||||
admin.disableFreeMonitoring();
|
|
||||||
|
|
||||||
WaitForFreeMonServerStatusState(mongod, "disabled");
|
|
||||||
|
|
||||||
const disabled = freeMonStats();
|
|
||||||
assert.eq(disabled.state, 'disabled');
|
|
||||||
assert.eq(disabled.retryIntervalSecs, kRetryIntervalSecs);
|
|
||||||
assert.eq(disabled.registerErrors, 0);
|
|
||||||
assert.eq(disabled.metricsErrors, 0);
|
|
||||||
|
|
||||||
// Cleanup.
|
|
||||||
MongoRunner.stopMongod(mongod);
|
|
||||||
mock_web.stop();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,336 +0,0 @@
|
||||||
|
|
||||||
/**
|
|
||||||
* Control the Free Monitoring Mock Webserver.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// These faults must match the list of faults in mock_http_server.py, see the
|
|
||||||
// SUPPORTED_FAULT_TYPES list in mock_http_server.py
|
|
||||||
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";
|
|
||||||
|
|
||||||
class FreeMonWebServer {
|
|
||||||
/**
|
|
||||||
* Create a new webserver.
|
|
||||||
*
|
|
||||||
* @param {string} fault_type
|
|
||||||
* @param {bool} disableFaultsOnStartup optionally disable fault on startup
|
|
||||||
*/
|
|
||||||
constructor(fault_type, disableFaultsOnStartup) {
|
|
||||||
this.python = "python3";
|
|
||||||
this.disableFaultsOnStartup = disableFaultsOnStartup || false;
|
|
||||||
this.fault_type = fault_type;
|
|
||||||
|
|
||||||
if (_isWindows()) {
|
|
||||||
this.python = "python.exe";
|
|
||||||
}
|
|
||||||
|
|
||||||
print("Using python interpreter: " + this.python);
|
|
||||||
this.web_server_py = "jstests/free_mon/libs/mock_http_server.py";
|
|
||||||
this.control_py = "jstests/free_mon/libs/mock_http_control.py";
|
|
||||||
|
|
||||||
this.pid = undefined;
|
|
||||||
this.port = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Port.
|
|
||||||
*
|
|
||||||
* @return {number} port number of http server
|
|
||||||
*/
|
|
||||||
getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the URL.
|
|
||||||
*
|
|
||||||
* @return {string} url of http server
|
|
||||||
*/
|
|
||||||
getURL() {
|
|
||||||
return "http://localhost:" + this.port;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the Mock HTTP Server.
|
|
||||||
*/
|
|
||||||
start() {
|
|
||||||
this.port = allocatePort();
|
|
||||||
print("Mock Web server is listening on port: " + this.port);
|
|
||||||
|
|
||||||
let args = [this.python, "-u", this.web_server_py, "--port=" + this.port];
|
|
||||||
if (this.fault_type) {
|
|
||||||
args.push("--fault=" + this.fault_type);
|
|
||||||
if (this.disableFaultsOnStartup) {
|
|
||||||
args.push("--disable-faults");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clearRawMongoProgramOutput();
|
|
||||||
|
|
||||||
this.pid = _startMongoProgram({args: args});
|
|
||||||
|
|
||||||
assert(checkProgram(this.pid));
|
|
||||||
|
|
||||||
// Wait for the web server to start
|
|
||||||
assert.soon(function() {
|
|
||||||
return rawMongoProgramOutput().search("Mock Web Server Listening") !== -1;
|
|
||||||
});
|
|
||||||
|
|
||||||
print("Mock HTTP Server sucessfully started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the Mock HTTP Server.
|
|
||||||
*/
|
|
||||||
stop() {
|
|
||||||
stopMongoProgramByPid(this.pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query the HTTP server.
|
|
||||||
*
|
|
||||||
* @param {string} query type
|
|
||||||
*
|
|
||||||
* @return {object} Object representation of JSON from the server.
|
|
||||||
*/
|
|
||||||
query(query) {
|
|
||||||
const out_file = "out_" + this.port + ".txt";
|
|
||||||
const python_command = this.python + " -u " + this.control_py + " --port=" + this.port +
|
|
||||||
" --query=" + query + " > " + out_file;
|
|
||||||
|
|
||||||
let ret = 0;
|
|
||||||
if (_isWindows()) {
|
|
||||||
ret = runProgram('cmd.exe', '/c', python_command);
|
|
||||||
} else {
|
|
||||||
ret = runProgram('/bin/sh', '-c', python_command);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.eq(ret, 0);
|
|
||||||
|
|
||||||
const result = cat(out_file);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return JSON.parse(result);
|
|
||||||
} catch (e) {
|
|
||||||
jsTestLog("Failed to parse: " + result + "\n" + result);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Control the HTTP server.
|
|
||||||
*
|
|
||||||
* @param {string} query type
|
|
||||||
*/
|
|
||||||
control(query) {
|
|
||||||
const out_file = "out_" + this.port + ".txt";
|
|
||||||
const python_command = this.python + " -u " + this.control_py + " --port=" + this.port +
|
|
||||||
" --query=" + query + " > " + out_file;
|
|
||||||
|
|
||||||
let ret = 0;
|
|
||||||
if (_isWindows()) {
|
|
||||||
ret = runProgram('cmd.exe', '/c', python_command);
|
|
||||||
} else {
|
|
||||||
ret = runProgram('/bin/sh', '-c', python_command);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.eq(ret, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable Faults
|
|
||||||
*/
|
|
||||||
disableFaults() {
|
|
||||||
this.control(DISABLE_FAULTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable Faults
|
|
||||||
*/
|
|
||||||
enableFaults() {
|
|
||||||
this.control(ENABLE_FAULTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query the stats page for the HTTP server.
|
|
||||||
*
|
|
||||||
* @return {object} Object representation of JSON from the server.
|
|
||||||
*/
|
|
||||||
queryStats() {
|
|
||||||
return this.query("stats");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for N register calls to be received by web server.
|
|
||||||
*
|
|
||||||
* @throws assert.soon() exception
|
|
||||||
*/
|
|
||||||
waitRegisters(count) {
|
|
||||||
const qs = this.queryStats.bind(this);
|
|
||||||
const port = this.port;
|
|
||||||
// Wait for registration to occur
|
|
||||||
assert.soon(function() {
|
|
||||||
const stats = qs();
|
|
||||||
print("w" + port + "| waiting for registers >= (" + count + ") QS : " + tojson(stats));
|
|
||||||
return stats.registers >= count;
|
|
||||||
}, "Failed to web server register", 60 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for N metrics calls to be received by web server.
|
|
||||||
*
|
|
||||||
* @throws assert.soon() exception
|
|
||||||
*/
|
|
||||||
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("w" + port + "| waiting for metrics >= (" + count + ") QS : " + tojson(stats));
|
|
||||||
return stats.metrics >= count;
|
|
||||||
}, "Failed to web server metrics", 60 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for N fault calls to e received by web server.
|
|
||||||
*
|
|
||||||
* @throws assert.soon() exception
|
|
||||||
*/
|
|
||||||
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("w" + port + "| waiting for faults >= (" + count + ") QS : " + tojson(stats));
|
|
||||||
return stats.faults >= count;
|
|
||||||
}, "Failed to web server faults", 60 * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for registration information to be populated in the database.
|
|
||||||
*
|
|
||||||
* @param {object} conn
|
|
||||||
* @param {string} state
|
|
||||||
*/
|
|
||||||
function WaitForDiskState(conn, state) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const admin = conn.getDB("admin");
|
|
||||||
|
|
||||||
// Wait for registration to occur
|
|
||||||
assert.soon(function() {
|
|
||||||
const docs = admin.system.version.find({_id: "free_monitoring"});
|
|
||||||
const da = docs.toArray();
|
|
||||||
return da.length === 1 && da[0].state === state;
|
|
||||||
}, "Failed to disk state", 60 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for registration information to be populated in the database.
|
|
||||||
*
|
|
||||||
* @param {object} conn
|
|
||||||
*/
|
|
||||||
function WaitForRegistration(conn) {
|
|
||||||
WaitForDiskState(conn, 'enabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for unregistration information to be populated in the database.
|
|
||||||
*
|
|
||||||
* @param {object} conn
|
|
||||||
*/
|
|
||||||
function WaitForUnRegistration(conn) {
|
|
||||||
WaitForDiskState(conn, 'disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get registration document.
|
|
||||||
*
|
|
||||||
* @param {object} registration document
|
|
||||||
*/
|
|
||||||
function FreeMonGetRegistration(conn) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const admin = conn.getDB("admin");
|
|
||||||
const docs = admin.system.version.find({_id: "free_monitoring"});
|
|
||||||
const da = docs.toArray();
|
|
||||||
return da[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current Free Monitoring Status via serverStatus.
|
|
||||||
*
|
|
||||||
* @param {object} serverStatus.freeMonitoring section
|
|
||||||
*/
|
|
||||||
function FreeMonGetServerStatus(conn) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const admin = conn.getDB("admin");
|
|
||||||
return assert.commandWorked(admin.runCommand({serverStatus: 1})).freeMonitoring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current Free Monitoring Status via getFreeMonitoringStatus.
|
|
||||||
*
|
|
||||||
* @param {object} getFreeMonitoringStatus document
|
|
||||||
*/
|
|
||||||
function FreeMonGetStatus(conn) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const admin = conn.getDB("admin");
|
|
||||||
const reply = assert.commandWorked(admin.runCommand({getFreeMonitoringStatus: 1}));
|
|
||||||
// FreeMonitoring has been deprecated and reports 'disabled' regardless of status.
|
|
||||||
assert.eq(reply.state, 'disabled', 'FreeMonitoring has been deprecated');
|
|
||||||
|
|
||||||
// Use the "true" state tucked into the 'debug' field if its available.
|
|
||||||
return reply.debug || reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for server status state
|
|
||||||
*
|
|
||||||
* @param {object} conn
|
|
||||||
* @param {string} state
|
|
||||||
*/
|
|
||||||
function WaitForFreeMonServerStatusState(conn, state) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Wait for registration to occur
|
|
||||||
assert.soon(
|
|
||||||
function() {
|
|
||||||
let status = FreeMonGetServerStatus(conn).state;
|
|
||||||
return status === state;
|
|
||||||
},
|
|
||||||
"Failed to find expected server status state: expected: '" + state +
|
|
||||||
"', actual: " + tojson(FreeMonGetServerStatus(conn)),
|
|
||||||
20 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate Free Monitoring Replica Set consistency
|
|
||||||
* WARNING: Not valid if secondary is started with enableFreeMonitoring since it registers before it
|
|
||||||
* joins the replica set.
|
|
||||||
*
|
|
||||||
* @param {object} rst
|
|
||||||
*/
|
|
||||||
function ValidateFreeMonReplicaSet(rst) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const primary_status = FreeMonGetStatus(rst.getPrimary());
|
|
||||||
const primary_url = primary_status.url;
|
|
||||||
const secondary_status = FreeMonGetStatus(rst.getSecondary());
|
|
||||||
const secondary_url = secondary_status.url;
|
|
||||||
assert.eq(primary_url,
|
|
||||||
secondary_url,
|
|
||||||
`DUMP ${tojson(primary_status)} == ${tojson(secondary_status)}`);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
"""Common code for mock free monitoring http endpoint."""
|
|
||||||
import json
|
|
||||||
|
|
||||||
URL_PATH_STATS = "/stats"
|
|
||||||
URL_PATH_LAST_REGISTER = "/last_register"
|
|
||||||
URL_PATH_LAST_METRICS = "/last_metrics"
|
|
||||||
URL_DISABLE_FAULTS = "/disable_faults"
|
|
||||||
URL_ENABLE_FAULTS = "/enable_faults"
|
|
||||||
|
|
||||||
|
|
||||||
class Stats:
|
|
||||||
"""Stats class shared between client and server."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.register_calls = 0
|
|
||||||
self.metrics_calls = 0
|
|
||||||
self.fault_calls = 0
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return json.dumps({
|
|
||||||
'metrics': self.metrics_calls,
|
|
||||||
'registers': self.register_calls,
|
|
||||||
'faults': self.fault_calls,
|
|
||||||
})
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Python script to interact with mock free monitoring HTTP server.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
import mock_http_common
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main entry point."""
|
|
||||||
parser = argparse.ArgumentParser(description='MongoDB Mock Free Monitoring Endpoint.')
|
|
||||||
|
|
||||||
parser.add_argument('-p', '--port', type=int, default=8000, help="Port to listen on")
|
|
||||||
|
|
||||||
parser.add_argument('-v', '--verbose', action='count', help="Enable verbose tracing")
|
|
||||||
|
|
||||||
parser.add_argument('--query', type=str, help="Query endpoint <name>")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
if args.verbose:
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
url_str = "http://localhost:" + str(args.port)
|
|
||||||
if args.query == "stats":
|
|
||||||
url_str += mock_http_common.URL_PATH_STATS
|
|
||||||
elif args.query == "last_register":
|
|
||||||
url_str += mock_http_common.URL_PATH_LAST_REGISTER
|
|
||||||
elif args.query == "last_metrics":
|
|
||||||
url_str += mock_http_common.URL_PATH_LAST_METRICS
|
|
||||||
elif args.query == "disable_faults":
|
|
||||||
url_str += mock_http_common.URL_DISABLE_FAULTS
|
|
||||||
elif args.query == "enable_faults":
|
|
||||||
url_str += mock_http_common.URL_ENABLE_FAULTS
|
|
||||||
else:
|
|
||||||
print("Unknown query type")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
with urllib.request.urlopen(url_str) as f:
|
|
||||||
print(f.read().decode('utf-8'))
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
@ -1,306 +0,0 @@
|
||||||
#! /usr/bin/env python3
|
|
||||||
"""Mock Free Monitoring Endpoint."""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import collections
|
|
||||||
import http.server
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import socketserver
|
|
||||||
import sys
|
|
||||||
import urllib.parse
|
|
||||||
|
|
||||||
import bson
|
|
||||||
from bson.codec_options import CodecOptions
|
|
||||||
from bson.json_util import dumps
|
|
||||||
import mock_http_common
|
|
||||||
|
|
||||||
# Pass this data out of band instead of storing it in FreeMonHandler since the
|
|
||||||
# BaseHTTPRequestHandler does not call the methods as object methods but as class methods. This
|
|
||||||
# means there is not self.
|
|
||||||
stats = mock_http_common.Stats()
|
|
||||||
last_metrics = None
|
|
||||||
last_register = None
|
|
||||||
disable_faults = False
|
|
||||||
fault_type = None
|
|
||||||
"""Fault which causes the server to return an HTTP failure on register."""
|
|
||||||
FAULT_FAIL_REGISTER = "fail_register"
|
|
||||||
"""Fault which causes the server to return a response with a document with a bad version."""
|
|
||||||
FAULT_INVALID_REGISTER = "invalid_register"
|
|
||||||
"""Fault which causes metrics to return halt after 5 metric uploads have occurred."""
|
|
||||||
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
|
|
||||||
URL_POST_REGISTER = '/register'
|
|
||||||
URL_POST_METRICS = '/metrics'
|
|
||||||
|
|
||||||
|
|
||||||
class FreeMonHandler(http.server.BaseHTTPRequestHandler):
|
|
||||||
"""
|
|
||||||
Handle requests from Free Monitoring and test commands
|
|
||||||
"""
|
|
||||||
|
|
||||||
def do_GET(self):
|
|
||||||
"""Serve a Test GET request."""
|
|
||||||
parts = urllib.parse.urlsplit(self.path)
|
|
||||||
path = parts[2]
|
|
||||||
|
|
||||||
if path == mock_http_common.URL_PATH_STATS:
|
|
||||||
self._do_stats()
|
|
||||||
elif path == mock_http_common.URL_PATH_LAST_REGISTER:
|
|
||||||
self._do_last_register()
|
|
||||||
elif path == mock_http_common.URL_PATH_LAST_METRICS:
|
|
||||||
self._do_last_metrics()
|
|
||||||
elif path == mock_http_common.URL_DISABLE_FAULTS:
|
|
||||||
self._do_disable_faults()
|
|
||||||
elif path == mock_http_common.URL_ENABLE_FAULTS:
|
|
||||||
self._do_enable_faults()
|
|
||||||
else:
|
|
||||||
self.send_response(http.HTTPStatus.NOT_FOUND)
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write("Unknown URL".encode())
|
|
||||||
|
|
||||||
def do_POST(self):
|
|
||||||
"""Serve a Free Monitoring POST request."""
|
|
||||||
parts = urllib.parse.urlsplit(self.path)
|
|
||||||
path = parts[2]
|
|
||||||
|
|
||||||
if path == URL_POST_REGISTER:
|
|
||||||
self._do_registration()
|
|
||||||
elif path == URL_POST_METRICS:
|
|
||||||
self._do_metrics()
|
|
||||||
else:
|
|
||||||
self.send_response(http.HTTPStatus.NOT_FOUND)
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write("Unknown URL".encode())
|
|
||||||
|
|
||||||
def _send_header(self):
|
|
||||||
self.send_response(http.HTTPStatus.OK)
|
|
||||||
self.send_header("content-type", "application/octet-stream")
|
|
||||||
self.end_headers()
|
|
||||||
|
|
||||||
def _do_registration(self):
|
|
||||||
global stats
|
|
||||||
global last_register
|
|
||||||
clen = int(self.headers.get('content-length'))
|
|
||||||
|
|
||||||
stats.register_calls += 1
|
|
||||||
|
|
||||||
raw_input = self.rfile.read(clen)
|
|
||||||
decoded_doc = bson.BSON.decode(raw_input)
|
|
||||||
last_register = dumps(decoded_doc)
|
|
||||||
|
|
||||||
if not disable_faults and fault_type == FAULT_FAIL_REGISTER:
|
|
||||||
stats.fault_calls += 1
|
|
||||||
self.send_response(http.HTTPStatus.INTERNAL_SERVER_ERROR)
|
|
||||||
self.send_header("content-type", "application/octet-stream")
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write("Internal Error of some sort.".encode())
|
|
||||||
return
|
|
||||||
|
|
||||||
if not disable_faults and fault_type == FAULT_INVALID_REGISTER:
|
|
||||||
stats.fault_calls += 1
|
|
||||||
data = bson.BSON.encode({
|
|
||||||
'version': bson.int64.Int64(42),
|
|
||||||
'haltMetricsUploading': False,
|
|
||||||
'id': '',
|
|
||||||
'informationalURL': 'http://www.example.com/123',
|
|
||||||
'message': 'Welcome to the Mock Free Monitoring Endpoint',
|
|
||||||
'reportingInterval': bson.int64.Int64(1),
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
reg_id = 'mock123_' + str(stats.register_calls)
|
|
||||||
if 'id' in decoded_doc:
|
|
||||||
reg_id = decoded_doc['id']
|
|
||||||
|
|
||||||
data = bson.BSON.encode({
|
|
||||||
'version':
|
|
||||||
bson.int64.Int64(1),
|
|
||||||
'haltMetricsUploading':
|
|
||||||
False,
|
|
||||||
'id':
|
|
||||||
reg_id,
|
|
||||||
'informationalURL':
|
|
||||||
'http://www.example.com/' + reg_id,
|
|
||||||
'message':
|
|
||||||
'Welcome to the Mock Free Monitoring Endpoint',
|
|
||||||
'reportingInterval':
|
|
||||||
bson.int64.Int64(1),
|
|
||||||
'userReminder':
|
|
||||||
"""To see your monitoring data, navigate to the unique URL below.
|
|
||||||
Anyone you share the URL with will also be able to view this page.
|
|
||||||
|
|
||||||
https://localhost:8080/someUUID6v5jLKTIZZklDvN5L8sZ
|
|
||||||
|
|
||||||
You can disable monitoring at any time by running db.disableFreeMonitoring().""",
|
|
||||||
})
|
|
||||||
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
self.wfile.write(data)
|
|
||||||
|
|
||||||
def _do_metrics(self):
|
|
||||||
global stats
|
|
||||||
global last_metrics
|
|
||||||
clen = int(self.headers.get('content-length'))
|
|
||||||
|
|
||||||
stats.metrics_calls += 1
|
|
||||||
|
|
||||||
raw_input = self.rfile.read(clen)
|
|
||||||
decoded_doc = bson.BSON.decode(raw_input)
|
|
||||||
last_metrics = dumps(decoded_doc)
|
|
||||||
|
|
||||||
if not disable_faults and \
|
|
||||||
stats.metrics_calls > 5 and \
|
|
||||||
fault_type == FAULT_HALT_METRICS_5:
|
|
||||||
stats.fault_calls += 1
|
|
||||||
data = bson.BSON.encode({
|
|
||||||
'version': bson.int64.Int64(1),
|
|
||||||
'haltMetricsUploading': True,
|
|
||||||
'permanentlyDelete': False,
|
|
||||||
'id': 'mock123',
|
|
||||||
'reportingInterval': bson.int64.Int64(1),
|
|
||||||
'message': 'Thanks for all the metrics',
|
|
||||||
})
|
|
||||||
elif not disable_faults and \
|
|
||||||
stats.metrics_calls > 3 and fault_type == FAULT_PERMANENTLY_DELETE_AFTER_3:
|
|
||||||
stats.fault_calls += 1
|
|
||||||
data = bson.BSON.encode({
|
|
||||||
'version': bson.int64.Int64(1),
|
|
||||||
'haltMetricsUploading': False,
|
|
||||||
'permanentlyDelete': True,
|
|
||||||
'id': 'mock123',
|
|
||||||
'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': decoded_doc['id'],
|
|
||||||
'reportingInterval': bson.int64.Int64(1),
|
|
||||||
'message': 'Thanks for all the metrics',
|
|
||||||
})
|
|
||||||
|
|
||||||
# TODO: test what if header is sent first?
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
self.wfile.write(data)
|
|
||||||
|
|
||||||
def _do_stats(self):
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
self.wfile.write(str(stats).encode('utf-8'))
|
|
||||||
|
|
||||||
def _do_last_register(self):
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
self.wfile.write(str(last_register).encode('utf-8'))
|
|
||||||
|
|
||||||
def _do_last_metrics(self):
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
self.wfile.write(str(last_metrics).encode('utf-8'))
|
|
||||||
|
|
||||||
def _do_disable_faults(self):
|
|
||||||
global disable_faults
|
|
||||||
disable_faults = True
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
def _do_enable_faults(self):
|
|
||||||
global disable_faults
|
|
||||||
disable_faults = False
|
|
||||||
self._send_header()
|
|
||||||
|
|
||||||
|
|
||||||
def run(port, server_class=http.server.HTTPServer, handler_class=FreeMonHandler):
|
|
||||||
"""Run web server."""
|
|
||||||
server_address = ('', port)
|
|
||||||
|
|
||||||
http.server.HTTPServer.protocol_version = "HTTP/1.1"
|
|
||||||
|
|
||||||
httpd = server_class(server_address, handler_class)
|
|
||||||
|
|
||||||
print("Mock Web Server Listening on %s" % (str(server_address)))
|
|
||||||
|
|
||||||
httpd.serve_forever()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""Main Method."""
|
|
||||||
global fault_type
|
|
||||||
global disable_faults
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='MongoDB Mock Free Monitoring Endpoint.')
|
|
||||||
|
|
||||||
parser.add_argument('-p', '--port', type=int, default=8000, help="Port to listen on")
|
|
||||||
|
|
||||||
parser.add_argument('-v', '--verbose', action='count', help="Enable verbose tracing")
|
|
||||||
|
|
||||||
parser.add_argument('--fault', type=str, help="Type of fault to inject")
|
|
||||||
|
|
||||||
parser.add_argument('--disable-faults', action='store_true', help="Disable faults on startup")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
if args.verbose:
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
if args.fault:
|
|
||||||
if args.fault not in SUPPORTED_FAULT_TYPES:
|
|
||||||
print("Unsupported fault type %s, supports types are %s" % (args.fault,
|
|
||||||
SUPPORTED_FAULT_TYPES))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
fault_type = args.fault
|
|
||||||
|
|
||||||
if args.disable_faults:
|
|
||||||
disable_faults = True
|
|
||||||
|
|
||||||
run(args.port)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
main()
|
|
||||||
|
|
@ -199,7 +199,6 @@ const allCommands = {
|
||||||
getDatabaseVersion: {skip: isNotAUserDataRead},
|
getDatabaseVersion: {skip: isNotAUserDataRead},
|
||||||
getDefaultRWConcern: {skip: isNotAUserDataRead},
|
getDefaultRWConcern: {skip: isNotAUserDataRead},
|
||||||
getDiagnosticData: {skip: isNotAUserDataRead},
|
getDiagnosticData: {skip: isNotAUserDataRead},
|
||||||
getFreeMonitoringStatus: {skip: isNotAUserDataRead},
|
|
||||||
getLastError: {skip: isPrimaryOnly},
|
getLastError: {skip: isPrimaryOnly},
|
||||||
getLog: {skip: isNotAUserDataRead},
|
getLog: {skip: isNotAUserDataRead},
|
||||||
getMore: {
|
getMore: {
|
||||||
|
|
@ -311,7 +310,6 @@ const allCommands = {
|
||||||
setDefaultRWConcern: {skip: isPrimaryOnly},
|
setDefaultRWConcern: {skip: isPrimaryOnly},
|
||||||
setIndexCommitQuorum: {skip: isPrimaryOnly},
|
setIndexCommitQuorum: {skip: isPrimaryOnly},
|
||||||
setFeatureCompatibilityVersion: {skip: isPrimaryOnly},
|
setFeatureCompatibilityVersion: {skip: isPrimaryOnly},
|
||||||
setFreeMonitoring: {skip: isPrimaryOnly},
|
|
||||||
setProfilingFilterGlobally: {skip: isNotAUserDataRead},
|
setProfilingFilterGlobally: {skip: isNotAUserDataRead},
|
||||||
setParameter: {skip: isNotAUserDataRead},
|
setParameter: {skip: isNotAUserDataRead},
|
||||||
setShardVersion: {skip: isNotAUserDataRead},
|
setShardVersion: {skip: isNotAUserDataRead},
|
||||||
|
|
|
||||||
|
|
@ -633,8 +633,6 @@ let testCases = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setFeatureCompatibilityVersion: {skip: "not on a user database"},
|
setFeatureCompatibilityVersion: {skip: "not on a user database"},
|
||||||
setFreeMonitoring:
|
|
||||||
{skip: "explicitly fails for mongos, primary mongod only", conditional: true},
|
|
||||||
setProfilingFilterGlobally: {skip: "executes locally on mongos (not sent to any remote node)"},
|
setProfilingFilterGlobally: {skip: "executes locally on mongos (not sent to any remote node)"},
|
||||||
setParameter: {skip: "executes locally on mongos (not sent to any remote node)"},
|
setParameter: {skip: "executes locally on mongos (not sent to any remote node)"},
|
||||||
shardCollection: {skip: "does not forward command to primary shard"},
|
shardCollection: {skip: "does not forward command to primary shard"},
|
||||||
|
|
|
||||||
|
|
@ -1209,11 +1209,6 @@ let MongosAPIParametersUtil = (function() {
|
||||||
command: () => ({setFeatureCompatibilityVersion: latestFCV})
|
command: () => ({setFeatureCompatibilityVersion: latestFCV})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
commandName: "setFreeMonitoring",
|
|
||||||
skip: "explicitly fails for mongos, primary mongod only",
|
|
||||||
conditional: true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
commandName: "setProfilingFilterGlobally",
|
commandName: "setProfilingFilterGlobally",
|
||||||
skip: "executes locally on mongos (not sent to any remote node)",
|
skip: "executes locally on mongos (not sent to any remote node)",
|
||||||
|
|
|
||||||
|
|
@ -430,7 +430,6 @@ let testCases = {
|
||||||
getDatabaseVersion: {skip: "does not accept read or write concern"},
|
getDatabaseVersion: {skip: "does not accept read or write concern"},
|
||||||
getDefaultRWConcern: {skip: "does not accept read or write concern"},
|
getDefaultRWConcern: {skip: "does not accept read or write concern"},
|
||||||
getDiagnosticData: {skip: "does not accept read or write concern"},
|
getDiagnosticData: {skip: "does not accept read or write concern"},
|
||||||
getFreeMonitoringStatus: {skip: "does not accept read or write concern"},
|
|
||||||
getLastError: {skip: "does not accept read or write concern"},
|
getLastError: {skip: "does not accept read or write concern"},
|
||||||
getLog: {skip: "does not accept read or write concern"},
|
getLog: {skip: "does not accept read or write concern"},
|
||||||
getMore: {skip: "does not accept read or write concern"},
|
getMore: {skip: "does not accept read or write concern"},
|
||||||
|
|
@ -633,7 +632,6 @@ let testCases = {
|
||||||
setCommittedSnapshot: {skip: "internal command"},
|
setCommittedSnapshot: {skip: "internal command"},
|
||||||
setDefaultRWConcern: {skip: "special case (must run after all other commands)"},
|
setDefaultRWConcern: {skip: "special case (must run after all other commands)"},
|
||||||
setFeatureCompatibilityVersion: {skip: "does not accept read or write concern"},
|
setFeatureCompatibilityVersion: {skip: "does not accept read or write concern"},
|
||||||
setFreeMonitoring: {skip: "does not accept read or write concern"},
|
|
||||||
setProfilingFilterGlobally: {skip: "does not accept read or write concern"},
|
setProfilingFilterGlobally: {skip: "does not accept read or write concern"},
|
||||||
setIndexCommitQuorum: {skip: "does not accept read or write concern"},
|
setIndexCommitQuorum: {skip: "does not accept read or write concern"},
|
||||||
setParameter: {skip: "does not accept read or write concern"},
|
setParameter: {skip: "does not accept read or write concern"},
|
||||||
|
|
|
||||||
|
|
@ -298,7 +298,6 @@ let testCases = {
|
||||||
setDefaultRWConcern: {skip: "primary only"},
|
setDefaultRWConcern: {skip: "primary only"},
|
||||||
setIndexCommitQuorum: {skip: "primary only"},
|
setIndexCommitQuorum: {skip: "primary only"},
|
||||||
setFeatureCompatibilityVersion: {skip: "primary only"},
|
setFeatureCompatibilityVersion: {skip: "primary only"},
|
||||||
setFreeMonitoring: {skip: "primary only"},
|
|
||||||
setProfilingFilterGlobally: {skip: "does not return user data"},
|
setProfilingFilterGlobally: {skip: "does not return user data"},
|
||||||
setParameter: {skip: "does not return user data"},
|
setParameter: {skip: "does not return user data"},
|
||||||
setShardVersion: {skip: "does not return user data"},
|
setShardVersion: {skip: "does not return user data"},
|
||||||
|
|
|
||||||
|
|
@ -369,7 +369,6 @@ let testCases = {
|
||||||
setDefaultRWConcern: {skip: "primary only"},
|
setDefaultRWConcern: {skip: "primary only"},
|
||||||
setIndexCommitQuorum: {skip: "primary only"},
|
setIndexCommitQuorum: {skip: "primary only"},
|
||||||
setFeatureCompatibilityVersion: {skip: "primary only"},
|
setFeatureCompatibilityVersion: {skip: "primary only"},
|
||||||
setFreeMonitoring: {skip: "primary only"},
|
|
||||||
setProfilingFilterGlobally: {skip: "does not return user data"},
|
setProfilingFilterGlobally: {skip: "does not return user data"},
|
||||||
setParameter: {skip: "does not return user data"},
|
setParameter: {skip: "does not return user data"},
|
||||||
setShardVersion: {skip: "does not return user data"},
|
setShardVersion: {skip: "does not return user data"},
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,6 @@ let testCases = {
|
||||||
setDefaultRWConcern: {skip: "primary only"},
|
setDefaultRWConcern: {skip: "primary only"},
|
||||||
setIndexCommitQuorum: {skip: "primary only"},
|
setIndexCommitQuorum: {skip: "primary only"},
|
||||||
setFeatureCompatibilityVersion: {skip: "primary only"},
|
setFeatureCompatibilityVersion: {skip: "primary only"},
|
||||||
setFreeMonitoring: {skip: "primary only"},
|
|
||||||
setProfilingFilterGlobally: {skip: "does not return user data"},
|
setProfilingFilterGlobally: {skip: "does not return user data"},
|
||||||
setParameter: {skip: "does not return user data"},
|
setParameter: {skip: "does not return user data"},
|
||||||
setShardVersion: {skip: "does not return user data"},
|
setShardVersion: {skip: "does not return user data"},
|
||||||
|
|
|
||||||
|
|
@ -298,9 +298,9 @@ error_codes:
|
||||||
- {code: 250,name: StaleChunkHistory,categories: [SnapshotError]}
|
- {code: 250,name: StaleChunkHistory,categories: [SnapshotError]}
|
||||||
- {code: 251,name: NoSuchTransaction,categories: [VoteAbortError]}
|
- {code: 251,name: NoSuchTransaction,categories: [VoteAbortError]}
|
||||||
- {code: 252,name: ReentrancyNotAllowed}
|
- {code: 252,name: ReentrancyNotAllowed}
|
||||||
- {code: 253,name: FreeMonHttpInFlight}
|
# - {code: 253,name: FreeMonHttpInFlight} # Removed in 7.1
|
||||||
- {code: 254,name: FreeMonHttpTemporaryFailure}
|
# - {code: 254,name: FreeMonHttpTemporaryFailure} # Removed in 7.1
|
||||||
- {code: 255,name: FreeMonHttpPermanentFailure}
|
# - {code: 255,name: FreeMonHttpPermanentFailure} # Removed in 7.1
|
||||||
- {code: 256,name: TransactionCommitted}
|
- {code: 256,name: TransactionCommitted}
|
||||||
- {code: 257,name: TransactionTooLarge}
|
- {code: 257,name: TransactionTooLarge}
|
||||||
- {code: 258,name: UnknownFeatureCompatibilityVersion}
|
- {code: 258,name: UnknownFeatureCompatibilityVersion}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ env.SConscript(
|
||||||
'concurrency',
|
'concurrency',
|
||||||
'cst',
|
'cst',
|
||||||
'exec',
|
'exec',
|
||||||
'free_mon',
|
|
||||||
'fts',
|
'fts',
|
||||||
'ftdc',
|
'ftdc',
|
||||||
'geo',
|
'geo',
|
||||||
|
|
@ -2108,7 +2107,6 @@ env.Library(
|
||||||
'dbdirectclient',
|
'dbdirectclient',
|
||||||
'dbhelpers',
|
'dbhelpers',
|
||||||
'exec/working_set',
|
'exec/working_set',
|
||||||
'free_mon/free_mon_mongod',
|
|
||||||
'ftdc/ftdc_mongod',
|
'ftdc/ftdc_mongod',
|
||||||
'fts/ftsmongod',
|
'fts/ftsmongod',
|
||||||
'index/index_access_method',
|
'index/index_access_method',
|
||||||
|
|
@ -2210,7 +2208,6 @@ env.Library(
|
||||||
'concurrency/flow_control_ticketholder',
|
'concurrency/flow_control_ticketholder',
|
||||||
'concurrency/lock_manager',
|
'concurrency/lock_manager',
|
||||||
'fcv_op_observer',
|
'fcv_op_observer',
|
||||||
'free_mon/free_mon_mongod',
|
|
||||||
'ftdc/ftdc_mongod',
|
'ftdc/ftdc_mongod',
|
||||||
'index/index_access_method',
|
'index/index_access_method',
|
||||||
'index_builds_coordinator_mongod',
|
'index_builds_coordinator_mongod',
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ enums:
|
||||||
changeOwnPassword : "changeOwnPassword"
|
changeOwnPassword : "changeOwnPassword"
|
||||||
changeOwnCustomData : "changeOwnCustomData"
|
changeOwnCustomData : "changeOwnCustomData"
|
||||||
changeStream : "changeStream"
|
changeStream : "changeStream"
|
||||||
checkFreeMonitoringStatus : "checkFreeMonitoringStatus"
|
checkFreeMonitoringStatus : "checkFreeMonitoringStatus" # Removed (backwards compatibility)
|
||||||
cleanupOrphaned : "cleanupOrphaned"
|
cleanupOrphaned : "cleanupOrphaned"
|
||||||
clearJumboFlag : "clearJumboFlag"
|
clearJumboFlag : "clearJumboFlag"
|
||||||
closeAllDatabases : "closeAllDatabases" # Deprecated (backwards compatibility)
|
closeAllDatabases : "closeAllDatabases" # Deprecated (backwards compatibility)
|
||||||
|
|
@ -156,7 +156,7 @@ enums:
|
||||||
setAuthenticationRestriction : "setAuthenticationRestriction"
|
setAuthenticationRestriction : "setAuthenticationRestriction"
|
||||||
setDefaultRWConcern : "setDefaultRWConcern"
|
setDefaultRWConcern : "setDefaultRWConcern"
|
||||||
setFeatureCompatibilityVersion : "setFeatureCompatibilityVersion"
|
setFeatureCompatibilityVersion : "setFeatureCompatibilityVersion"
|
||||||
setFreeMonitoring : "setFreeMonitoring"
|
setFreeMonitoring : "setFreeMonitoring" # Removed (backwards compatibility)
|
||||||
setParameter : "setParameter"
|
setParameter : "setParameter"
|
||||||
shardCollection : "shardCollection" # ID only
|
shardCollection : "shardCollection" # ID only
|
||||||
shardingState : "shardingState"
|
shardingState : "shardingState"
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,6 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
|
||||||
|
|
||||||
// clusterMonitor role actions that target the cluster resource
|
// clusterMonitor role actions that target the cluster resource
|
||||||
clusterMonitorRoleClusterActions
|
clusterMonitorRoleClusterActions
|
||||||
<< ActionType::checkFreeMonitoringStatus
|
|
||||||
<< ActionType::connPoolStats
|
<< ActionType::connPoolStats
|
||||||
<< ActionType::getCmdLineOpts
|
<< ActionType::getCmdLineOpts
|
||||||
<< ActionType::getDefaultRWConcern // clusterManager gets this also
|
<< ActionType::getDefaultRWConcern // clusterManager gets this also
|
||||||
|
|
@ -251,8 +250,7 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
|
||||||
<< ActionType::getDefaultRWConcern // clusterMonitor gets this also
|
<< ActionType::getDefaultRWConcern // clusterMonitor gets this also
|
||||||
<< ActionType::runTenantMigration
|
<< ActionType::runTenantMigration
|
||||||
<< ActionType::setDefaultRWConcern
|
<< ActionType::setDefaultRWConcern
|
||||||
<< ActionType::setFeatureCompatibilityVersion
|
<< ActionType::setFeatureCompatibilityVersion;
|
||||||
<< ActionType::setFreeMonitoring;
|
|
||||||
|
|
||||||
clusterManagerRoleDatabaseActions
|
clusterManagerRoleDatabaseActions
|
||||||
<< ActionType::clearJumboFlag
|
<< ActionType::clearJumboFlag
|
||||||
|
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
# Free Monitoring
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Free Monitoring](#free-monitoring)
|
|
||||||
- [Table of Contents](#table-of-contents)
|
|
||||||
- [High Level Overview](#high-level-overview)
|
|
||||||
|
|
||||||
## High Level Overview
|
|
||||||
|
|
||||||
Free Monitoring is a way for MongoDB Community users to enable Cloud Monitoring on their database.
|
|
||||||
To use Free Monitoring, a customer must first register by issuing the command
|
|
||||||
`db.enableFreeMonitoring()`.
|
|
||||||
|
|
||||||
The entire Free Monitoring subsystem is controlled by an object of type
|
|
||||||
[`FreeMonController`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.h#L53).
|
|
||||||
The `FreeMonController` lives as a decoration on the `ServiceContext`. The `FreeMonController` has a
|
|
||||||
two collections of collectors - the
|
|
||||||
[`_registrationCollectors`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.h#L197)
|
|
||||||
which collect data at registration time, and the
|
|
||||||
[`_metricCollectors`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.h#L200)
|
|
||||||
which collect data periodically. It also owns a
|
|
||||||
[`FreeMonProcessor`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.h#L304)
|
|
||||||
which under the hood contains a multi-producer priority queue, and a
|
|
||||||
[`FreeMonNetworkInterface`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_network.h#L40)
|
|
||||||
which is a way for the subsystem to send and recieve packets to the cloud endpoint.
|
|
||||||
|
|
||||||
When the server first starts, if Free Monitoring is enabled (using a command line parameter
|
|
||||||
`enableFreeMonitoring`), the FreeMonController is initialized on server startup through the mongod
|
|
||||||
main function which calls
|
|
||||||
[`startFreeMonitoring`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_mongod.cpp#L310).
|
|
||||||
This function creates the
|
|
||||||
[`FreeMonNetworkInterface`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_mongod.cpp#L322),
|
|
||||||
initializes the controller, determines the Registration type, and calls
|
|
||||||
[`start`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_mongod.cpp#L346-L348)
|
|
||||||
on the controller. The
|
|
||||||
[`start`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.h#L59-L65)
|
|
||||||
function initializes the processor, creates a thread for it to run on, and performs registration if
|
|
||||||
the user has performed registration.
|
|
||||||
|
|
||||||
If the user has not performed registration, the metrics collector begins collecting data. It stores
|
|
||||||
this data in a MetricsBuffer, capable of holding up to 10 data points. When the user performs
|
|
||||||
registration, a call to
|
|
||||||
[`registerServerStartup`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.cpp#L79-L84)
|
|
||||||
is made, placing a
|
|
||||||
[`FreeMonMessageWithPayload`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_message.h#L255)
|
|
||||||
object in the processor's queue. A `FreeMonMessageWithPayload` is an expanded subclass of
|
|
||||||
[`FreeMonMessage`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_message.h#L146),
|
|
||||||
which represents a message sent to the
|
|
||||||
[`FreeMonProcessor`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.h#L304)
|
|
||||||
actor to process and make a decision. For more reading on the actor model that the Free Monitoring
|
|
||||||
system is based on, see [here](https://en.wikipedia.org/wiki/Actor_model). A `FreeMonMessage` has
|
|
||||||
two significant properties, a type and a deadline. The type determines how the queue responds when
|
|
||||||
processing the message. The code for how the queue processes messages can be found
|
|
||||||
[here](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L156-L269).
|
|
||||||
The deadline determines the priority of the message in the queue. The deadline represents both the
|
|
||||||
waiting period the queue must take to process a message and a priority the queue uses to determine
|
|
||||||
the order in which messages are processed. For example, a message with a deadline of now can be
|
|
||||||
processed before something with a deadline of an hour from now.
|
|
||||||
|
|
||||||
In the call to
|
|
||||||
[`registerServerStartup`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.cpp#L79-L84),
|
|
||||||
a message of type `RegisterServer` is sent to the queue. Included with the message is a payload of
|
|
||||||
the registration type that the server should perform. The queue processes this message and calls
|
|
||||||
[`doServerRegister`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L324)
|
|
||||||
with the message object. The function processes the `RegistrationType` and if it is
|
|
||||||
`RegisterOnStart`, sends a `RegisterCommand` message to the queue. If the `RegistrationType` is
|
|
||||||
something else, we try to determine whether we are a primary or secondary in a replica set and send
|
|
||||||
a message depending on the state of free monitoring in the set. The full logic with comments is
|
|
||||||
[here](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L330-L367),
|
|
||||||
but know that it may create a `RegisterCommand` message to the queue in certain cases. The function
|
|
||||||
[`doServerRegister`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L328)
|
|
||||||
also creates a message of type `MetricsCollect` in the queue.
|
|
||||||
|
|
||||||
When the queue processes the
|
|
||||||
[`RegisterCommand`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L173-L175)
|
|
||||||
message, it calls
|
|
||||||
[`doCommandRegister`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L406)
|
|
||||||
which uses the
|
|
||||||
[`FreeMonNetworkInterface`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_mongod.cpp#L322)
|
|
||||||
to send a message over the wire to the cloud endpoint. It also writes the registration state
|
|
||||||
(`FreeMonRegistrationStatus::kPending`) and registration information out to disk, calling
|
|
||||||
[`writeState`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L299),
|
|
||||||
which invokes functions on the
|
|
||||||
[`FreeMonStorage`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_storage.h#L43)
|
|
||||||
class. The job of the `FreeMonStorage` class is to provide an interface for different functions to
|
|
||||||
interact with the storage subsystem. Whenever a change is made to the registration state -
|
|
||||||
registration completes or registration is cancelled because of an endpoint error - the processor
|
|
||||||
writes this information out to disk.
|
|
||||||
|
|
||||||
The queue also processes the first `MetricsCollect` command around this time. The queue reads the
|
|
||||||
Metrics collect method and calls
|
|
||||||
[`doMetricsCollect`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L714-L726)
|
|
||||||
which fires the `_metrics` collectors to collect and stores the data in a
|
|
||||||
[`MetricsBuffer`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.h#L185-L225).
|
|
||||||
The buffer can hold 10 data points at a time, so if the data has not been synced to the cloud
|
|
||||||
endpoint by the time the 11th data point is collected, then the buffer will remove the last item
|
|
||||||
from the queue. The function
|
|
||||||
[`doMetricsCollect`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L724-L725)
|
|
||||||
creates another message of type `MetricsCollect` with a deadline of the specified
|
|
||||||
`_metricsGatherInterval` for collection.
|
|
||||||
|
|
||||||
The way for a queue to trigger sending new metrics to the server is by sending a message of type
|
|
||||||
`MetricsSend`. This occurs on a few occasions - when registration information has been successfully
|
|
||||||
[sent to the cloud
|
|
||||||
endpoint](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L666),
|
|
||||||
when metrics information has [successfully been sent to the cloud
|
|
||||||
endpoint](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L865-L866),
|
|
||||||
and when metrics information has [failed to send to the
|
|
||||||
endpoint](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.cpp#L886-L888).
|
|
||||||
In the first case, a message is created with a deadline of now. In the second case the message is
|
|
||||||
sent with a deadline that is tracked by the
|
|
||||||
[`MetricsRetryCounter`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_processor.h#L153-L183)
|
|
||||||
object. The retry object is used to track any failures the processor encountered when sending
|
|
||||||
metrics; if enough failures have occured in a row, then the processor stops sending the metrics. In
|
|
||||||
the third case, the `MetricsRetryCounter` object is incremented to indicate failure. If it has not
|
|
||||||
exceeded the retry limit, then the message is again sent with a deadline tracked by the retry
|
|
||||||
object.
|
|
||||||
|
|
||||||
The last notable part of `FreeMonitoring` is the
|
|
||||||
[`FreeMonOpObserver`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_op_observer.h#L40).
|
|
||||||
This `OpObserver` watches the namespace where the free monitoring registration information is stored
|
|
||||||
(the `admin` database and the `system.version` collection) and sends a message to the processor if
|
|
||||||
there is a change to the document for the registration information. For example, if someone updates
|
|
||||||
the document, the OpObserver calls
|
|
||||||
[`notifyOnUpsert`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.h#L133-L138)
|
|
||||||
in the controller, the controller queues a
|
|
||||||
[`NotifyOnUpsert`](https://github.com/mongodb/mongo/blob/r4.4.0/src/mongo/db/free_mon/free_mon_controller.cpp#L111)
|
|
||||||
command in the processor. When the processor reads that message, it reads the updated registration
|
|
||||||
state from disk and updates the free monitoring subsystem based on the new information.
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
# -*- mode: python -*-
|
|
||||||
Import("env")
|
|
||||||
Import("free_monitoring")
|
|
||||||
|
|
||||||
env = env.Clone()
|
|
||||||
|
|
||||||
fmEnv = env.Clone()
|
|
||||||
fmEnv.InjectThirdParty(libraries=['snappy'])
|
|
||||||
|
|
||||||
fmEnv.Library(
|
|
||||||
target='free_mon',
|
|
||||||
source=[
|
|
||||||
'free_mon_processor.cpp',
|
|
||||||
'free_mon_queue.cpp',
|
|
||||||
'free_mon_op_observer.cpp',
|
|
||||||
'free_mon_storage.cpp',
|
|
||||||
'free_mon_controller.cpp',
|
|
||||||
'free_mon_protocol.idl',
|
|
||||||
'free_mon_commands.idl',
|
|
||||||
'free_mon_storage.idl',
|
|
||||||
],
|
|
||||||
LIBDEPS=[
|
|
||||||
'$BUILD_DIR/mongo/base',
|
|
||||||
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
|
|
||||||
'$BUILD_DIR/mongo/db/dbhelpers',
|
|
||||||
'$BUILD_DIR/mongo/db/ftdc/ftdc',
|
|
||||||
'$BUILD_DIR/mongo/idl/idl_parser',
|
|
||||||
'$BUILD_DIR/third_party/shim_snappy',
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
if free_monitoring == "on":
|
|
||||||
fmEnv.Library(
|
|
||||||
target='free_mon_mongod',
|
|
||||||
source=[
|
|
||||||
'free_mon_commands.cpp',
|
|
||||||
'free_mon_mongod.cpp',
|
|
||||||
'free_mon_mongod.idl',
|
|
||||||
'free_mon_options.cpp',
|
|
||||||
'free_mon_options.idl',
|
|
||||||
'free_mon_status.cpp',
|
|
||||||
],
|
|
||||||
LIBDEPS=[
|
|
||||||
'$BUILD_DIR/mongo/db/commands/server_status',
|
|
||||||
'$BUILD_DIR/mongo/db/ftdc/ftdc_server',
|
|
||||||
'$BUILD_DIR/mongo/util/options_parser/options_parser',
|
|
||||||
'free_mon',
|
|
||||||
],
|
|
||||||
LIBDEPS_PRIVATE=[
|
|
||||||
'$BUILD_DIR/mongo/client/clientdriver_network',
|
|
||||||
'$BUILD_DIR/mongo/util/concurrency/thread_pool',
|
|
||||||
'$BUILD_DIR/mongo/util/net/http_client',
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
fmEnv.Library(
|
|
||||||
target='free_mon_mongod',
|
|
||||||
source=[
|
|
||||||
'free_mon_commands_stub.cpp',
|
|
||||||
'free_mon_stub.cpp',
|
|
||||||
],
|
|
||||||
LIBDEPS_PRIVATE=[
|
|
||||||
'$BUILD_DIR/mongo/base',
|
|
||||||
'$BUILD_DIR/mongo/db/auth/auth',
|
|
||||||
'$BUILD_DIR/mongo/db/auth/authprivilege',
|
|
||||||
'$BUILD_DIR/mongo/db/commands',
|
|
||||||
'free_mon',
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
fmEnv.CppUnitTest(
|
|
||||||
target='db_free_mon_test',
|
|
||||||
source=[
|
|
||||||
'free_mon_controller_test.cpp',
|
|
||||||
'free_mon_queue_test.cpp',
|
|
||||||
'free_mon_storage_test.cpp',
|
|
||||||
],
|
|
||||||
LIBDEPS=[
|
|
||||||
'$BUILD_DIR/mongo/db/auth/authmocks',
|
|
||||||
'$BUILD_DIR/mongo/db/repl/replmocks',
|
|
||||||
'$BUILD_DIR/mongo/db/repl/storage_interface_impl',
|
|
||||||
'$BUILD_DIR/mongo/db/service_context_d_test_fixture',
|
|
||||||
'$BUILD_DIR/mongo/executor/thread_pool_task_executor_test_fixture',
|
|
||||||
'$BUILD_DIR/mongo/util/clock_source_mock',
|
|
||||||
'free_mon',
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/auth/authorization_session.h"
|
|
||||||
#include "mongo/db/commands.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_commands_gen.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_controller.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_options.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const auto kRegisterSyncTimeout = Milliseconds{5000};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the current status of Free Monitoring.
|
|
||||||
*/
|
|
||||||
class GetFreeMonitoringStatusCommand : public BasicCommand {
|
|
||||||
public:
|
|
||||||
GetFreeMonitoringStatusCommand() : BasicCommand("getFreeMonitoringStatus") {}
|
|
||||||
|
|
||||||
bool adminOnly() const override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
|
|
||||||
return AllowedOnSecondary::kAlways;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool supportsWriteConcern(const BSONObj& cmd) const final {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string help() const final {
|
|
||||||
return "Indicates free monitoring status";
|
|
||||||
}
|
|
||||||
|
|
||||||
Status checkAuthForCommand(Client* client,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj) const final {
|
|
||||||
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
|
|
||||||
ResourcePattern::forClusterResource(), ActionType::checkFreeMonitoringStatus)) {
|
|
||||||
return Status(ErrorCodes::Unauthorized, "Unauthorized");
|
|
||||||
}
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run(OperationContext* opCtx,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj,
|
|
||||||
BSONObjBuilder& result) final {
|
|
||||||
// Command has no members, invoke the parser to confirm that.
|
|
||||||
IDLParserErrorContext ctx("getFreeMonitoringStatus");
|
|
||||||
GetFreeMonitoringStatus::parse(ctx, cmdObj);
|
|
||||||
|
|
||||||
// FreeMonitoring has been deprecated and will be decomissioned.
|
|
||||||
// Report that FreeMon is disabled even if it's running to draw attention
|
|
||||||
// to the deprecation notice returned from the service.
|
|
||||||
result.append("state"_sd, "disabled"_sd);
|
|
||||||
|
|
||||||
if (globalFreeMonParams.freeMonitoringState != EnableCloudStateEnum::kOff) {
|
|
||||||
// To aid discovery during deprecation period, add true state as context.
|
|
||||||
auto* controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
if (controller) {
|
|
||||||
result.append(
|
|
||||||
"message"_sd,
|
|
||||||
"Free monitoring is deprecated, refer to 'debug' field for actual status"_sd);
|
|
||||||
BSONObjBuilder debug(result.subobjStart("debug"_sd));
|
|
||||||
controller->getStatus(opCtx, &debug);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} getFreeMonitoringStatusCommand;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables or disables Free Monitoring service.
|
|
||||||
*/
|
|
||||||
class SetFreeMonitoringCommand : public BasicCommand {
|
|
||||||
public:
|
|
||||||
SetFreeMonitoringCommand() : BasicCommand("setFreeMonitoring") {}
|
|
||||||
|
|
||||||
bool adminOnly() const override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
|
|
||||||
return AllowedOnSecondary::kNever;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool supportsWriteConcern(const BSONObj& cmd) const final {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string help() const final {
|
|
||||||
return "enable or disable Free Monitoring";
|
|
||||||
}
|
|
||||||
|
|
||||||
Status checkAuthForCommand(Client* client,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj) const final {
|
|
||||||
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
|
|
||||||
ResourcePattern::forClusterResource(), ActionType::setFreeMonitoring)) {
|
|
||||||
return Status(ErrorCodes::Unauthorized, "Unauthorized");
|
|
||||||
}
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run(OperationContext* opCtx,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj,
|
|
||||||
BSONObjBuilder& result) final {
|
|
||||||
IDLParserErrorContext ctx("setFreeMonitoring");
|
|
||||||
auto cmd = SetFreeMonitoring::parse(ctx, cmdObj);
|
|
||||||
|
|
||||||
auto* controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
if (!controller) {
|
|
||||||
// Pending operation.
|
|
||||||
uasserted(50840,
|
|
||||||
"Free Monitoring has been disabled via the command-line and/or config file");
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<Status> optStatus = boost::none;
|
|
||||||
if (cmd.getAction() == SetFreeMonActionEnum::enable) {
|
|
||||||
optStatus = controller->registerServerCommand(kRegisterSyncTimeout);
|
|
||||||
} else {
|
|
||||||
optStatus = controller->unregisterServerCommand(kRegisterSyncTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optStatus) {
|
|
||||||
// Completed within timeout.
|
|
||||||
uassertStatusOK(*optStatus);
|
|
||||||
} else {
|
|
||||||
// Pending operation.
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} setFreeMonitoringCmd;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
# Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the Server Side Public License, version 1,
|
|
||||||
# as published by MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# Server Side Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the Server Side Public License
|
|
||||||
# along with this program. If not, see
|
|
||||||
# <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
#
|
|
||||||
# As a special exception, the copyright holders give permission to link the
|
|
||||||
# code of portions of this program with the OpenSSL library under certain
|
|
||||||
# conditions as described in each individual source file and distribute
|
|
||||||
# linked combinations including the program with the OpenSSL library. You
|
|
||||||
# must comply with the Server Side Public License in all respects for
|
|
||||||
# all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
# with this exception, you may extend this exception to your version of the
|
|
||||||
# file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
# delete this exception statement from your version. If you delete this
|
|
||||||
# exception statement from all source files in the program, then also delete
|
|
||||||
# it in the license file.
|
|
||||||
#
|
|
||||||
global:
|
|
||||||
cpp_namespace: "mongo"
|
|
||||||
|
|
||||||
|
|
||||||
imports:
|
|
||||||
- "mongo/idl/basic_types.idl"
|
|
||||||
|
|
||||||
|
|
||||||
enums:
|
|
||||||
SetFreeMonAction:
|
|
||||||
description: "Action types"
|
|
||||||
type: string
|
|
||||||
values:
|
|
||||||
enable: "enable"
|
|
||||||
disable: "disable"
|
|
||||||
|
|
||||||
|
|
||||||
commands:
|
|
||||||
setFreeMonitoring:
|
|
||||||
description: "setFreeMonitoring Command"
|
|
||||||
command_name: setFreeMonitoring
|
|
||||||
namespace: ignored
|
|
||||||
api_version: ""
|
|
||||||
fields:
|
|
||||||
action:
|
|
||||||
description: "Action to take"
|
|
||||||
type: SetFreeMonAction
|
|
||||||
|
|
||||||
getFreeMonitoringStatus:
|
|
||||||
description: "getFreeMonitoringStatus Command"
|
|
||||||
command_name: getFreeMonitoringStatus
|
|
||||||
namespace: ignored
|
|
||||||
api_version: ""
|
|
||||||
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/auth/authorization_session.h"
|
|
||||||
#include "mongo/db/commands.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_commands_gen.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates the current status of Free Monitoring.
|
|
||||||
*
|
|
||||||
* Note that this file is only built when --enable-free-mon=off
|
|
||||||
* and it will return a static result of {status:"disabled"}.
|
|
||||||
*/
|
|
||||||
class GetFreeMonitoringStatusCommandStub : public BasicCommand {
|
|
||||||
public:
|
|
||||||
GetFreeMonitoringStatusCommandStub() : BasicCommand("getFreeMonitoringStatus") {}
|
|
||||||
|
|
||||||
bool adminOnly() const override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
|
|
||||||
return AllowedOnSecondary::kAlways;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool supportsWriteConcern(const BSONObj& cmd) const final {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string help() const final {
|
|
||||||
return "Indicates free monitoring status";
|
|
||||||
}
|
|
||||||
|
|
||||||
Status checkAuthForCommand(Client* client,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj) const final {
|
|
||||||
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
|
|
||||||
ResourcePattern::forClusterResource(), ActionType::checkFreeMonitoringStatus)) {
|
|
||||||
return Status(ErrorCodes::Unauthorized, "Unauthorized");
|
|
||||||
}
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run(OperationContext* opCtx,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj,
|
|
||||||
BSONObjBuilder& result) final {
|
|
||||||
// Command has no members, invoke the parser to confirm that.
|
|
||||||
IDLParserErrorContext ctx("getFreeMonitoringStatus");
|
|
||||||
GetFreeMonitoringStatus::parse(ctx, cmdObj);
|
|
||||||
|
|
||||||
result.append("state", "disabled");
|
|
||||||
result.append("message",
|
|
||||||
"Free Monitoring support is not available in this build of MongoDB");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} getFreeMonitoringStatusCommand;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,249 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_controller.h"
|
|
||||||
|
|
||||||
#include "mongo/logv2/log.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const auto getFreeMonController =
|
|
||||||
ServiceContext::declareDecoration<synchronized_value<std::unique_ptr<FreeMonController>>>();
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
FreeMonController* FreeMonController::get(ServiceContext* serviceContext) {
|
|
||||||
return getFreeMonController(serviceContext)->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::init(ServiceContext* serviceContext,
|
|
||||||
std::unique_ptr<FreeMonController> controller) {
|
|
||||||
auto fmcContainer = getFreeMonController(serviceContext).synchronize();
|
|
||||||
// Since FreeMonController::get() provides raw pointers, the FreeMonController can only be
|
|
||||||
// set once without producing memory leaks.
|
|
||||||
invariant(!fmcContainer->get());
|
|
||||||
fmcContainer = std::move(controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FreeMonNetworkInterface::~FreeMonNetworkInterface() = default;
|
|
||||||
|
|
||||||
void FreeMonController::addRegistrationCollector(
|
|
||||||
std::unique_ptr<FreeMonCollectorInterface> collector) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
invariant(_state == State::kNotStarted);
|
|
||||||
|
|
||||||
_registrationCollectors.add(std::move(collector));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::addMetricsCollector(std::unique_ptr<FreeMonCollectorInterface> collector) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
invariant(_state == State::kNotStarted);
|
|
||||||
|
|
||||||
_metricCollectors.add(std::move(collector));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::registerServerStartup(RegistrationType registrationType,
|
|
||||||
std::vector<std::string>& tags) {
|
|
||||||
_enqueue(FreeMonMessageWithPayload<FreeMonMessageType::RegisterServer>::createNow(
|
|
||||||
FreeMonMessageWithPayload<FreeMonMessageType::RegisterServer>::payload_type(
|
|
||||||
registrationType, tags)));
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<Status> FreeMonController::registerServerCommand(Milliseconds timeout) {
|
|
||||||
auto msg = FreeMonRegisterCommandMessage::createNow({std::vector<std::string>(), boost::none});
|
|
||||||
_enqueue(msg);
|
|
||||||
|
|
||||||
if (timeout > Milliseconds::min()) {
|
|
||||||
return msg->wait_for(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<Status> FreeMonController::unregisterServerCommand(Milliseconds timeout) {
|
|
||||||
auto msg =
|
|
||||||
FreeMonWaitableMessageWithPayload<FreeMonMessageType::UnregisterCommand>::createNow(true);
|
|
||||||
_enqueue(msg);
|
|
||||||
|
|
||||||
if (timeout > Milliseconds::min()) {
|
|
||||||
return msg->wait_for(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::notifyOnUpsert(const BSONObj& doc) {
|
|
||||||
invariant(doc.isOwned());
|
|
||||||
_enqueue(FreeMonMessageWithPayload<FreeMonMessageType::NotifyOnUpsert>::createNow(doc));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FreeMonController::notifyOnDelete() {
|
|
||||||
_enqueue(FreeMonMessage::createNow(FreeMonMessageType::NotifyOnDelete));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FreeMonController::notifyOnTransitionToPrimary() {
|
|
||||||
_enqueue(FreeMonMessage::createNow(FreeMonMessageType::OnTransitionToPrimary));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::notifyOnRollback() {
|
|
||||||
_enqueue(FreeMonMessage::createNow(FreeMonMessageType::NotifyOnRollback));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::_enqueue(std::shared_ptr<FreeMonMessage> msg) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
invariant(_state == State::kStarted);
|
|
||||||
}
|
|
||||||
|
|
||||||
_processor->enqueue(std::move(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::start(RegistrationType registrationType,
|
|
||||||
std::vector<std::string>& tags,
|
|
||||||
Seconds gatherMetricsInterval) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
invariant(_state == State::kNotStarted);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the agent
|
|
||||||
_processor = std::make_shared<FreeMonProcessor>(_registrationCollectors,
|
|
||||||
_metricCollectors,
|
|
||||||
_network.get(),
|
|
||||||
_useCrankForTest,
|
|
||||||
gatherMetricsInterval);
|
|
||||||
|
|
||||||
_thread = stdx::thread([this] { _processor->run(); });
|
|
||||||
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
invariant(_state == State::kNotStarted);
|
|
||||||
_state = State::kStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (registrationType != RegistrationType::DoNotRegister) {
|
|
||||||
registerServerStartup(registrationType, tags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::stop() {
|
|
||||||
// Stop the agent
|
|
||||||
LOGV2(20609, "Shutting down free monitoring");
|
|
||||||
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
bool started = (_state == State::kStarted);
|
|
||||||
|
|
||||||
invariant(_state == State::kNotStarted || _state == State::kStarted);
|
|
||||||
|
|
||||||
if (!started) {
|
|
||||||
_state = State::kDone;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_state = State::kStopRequested;
|
|
||||||
|
|
||||||
// Tell the processor to stop
|
|
||||||
_processor->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
_thread.join();
|
|
||||||
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
_state = State::kDone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::turnCrankForTest(size_t countMessagesToIgnore) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
invariant(_state == State::kStarted);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGV2(20610, "Turning Crank", "count"_attr = countMessagesToIgnore);
|
|
||||||
|
|
||||||
_processor->turnCrankForTest(countMessagesToIgnore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::deprioritizeFirstMessageForTest(FreeMonMessageType type) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
invariant(_state == State::kStarted);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGV2(5167901, "Deprioritize message", "type"_attr = static_cast<int>(type));
|
|
||||||
|
|
||||||
_processor->deprioritizeFirstMessageForTest(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::getStatus(OperationContext* opCtx, BSONObjBuilder* status) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
if (_state != State::kStarted) {
|
|
||||||
status->append("state", "disabled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_processor->getStatus(opCtx, status, FreeMonProcessor::FreeMonGetStatusEnum::kCommandStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonController::getServerStatus(OperationContext* opCtx, BSONObjBuilder* status) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
if (_state != State::kStarted) {
|
|
||||||
status->append("state", "disabled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_processor->getStatus(opCtx, status, FreeMonProcessor::FreeMonGetStatusEnum::kServerStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,220 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "mongo/base/status.h"
|
|
||||||
#include "mongo/db/client.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_message.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_network.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_processor.h"
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
#include "mongo/stdx/thread.h"
|
|
||||||
#include "mongo/util/duration.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages and control Free Monitoring. This is the entry point for non-free monitoring components
|
|
||||||
* into free-monitoring.
|
|
||||||
*/
|
|
||||||
class FreeMonController {
|
|
||||||
public:
|
|
||||||
explicit FreeMonController(std::unique_ptr<FreeMonNetworkInterface> network,
|
|
||||||
bool useCrankForTest = false)
|
|
||||||
: _network(std::move(network)), _useCrankForTest(useCrankForTest) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes free monitoring.
|
|
||||||
* Start free monitoring thread in the background.
|
|
||||||
*/
|
|
||||||
void start(RegistrationType registrationType,
|
|
||||||
std::vector<std::string>& tags,
|
|
||||||
Seconds gatherMetricsInterval);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops free monitoring thread.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn the crank of the message queue by ignoring deadlines for N messages.
|
|
||||||
*/
|
|
||||||
void turnCrankForTest(size_t countMessagesToIgnore);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deproritize the first message to force interleavings of messages.
|
|
||||||
*/
|
|
||||||
void deprioritizeFirstMessageForTest(FreeMonMessageType type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a metric collector to collect on registration
|
|
||||||
*/
|
|
||||||
void addRegistrationCollector(std::unique_ptr<FreeMonCollectorInterface> collector);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a metric collector to collect periodically
|
|
||||||
*/
|
|
||||||
void addMetricsCollector(std::unique_ptr<FreeMonCollectorInterface> collector);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the FreeMonController from ServiceContext.
|
|
||||||
*/
|
|
||||||
static FreeMonController* get(ServiceContext* serviceContext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the FreeMonController decoration in the ServiceContext.
|
|
||||||
*/
|
|
||||||
static void init(ServiceContext* serviceContext, std::unique_ptr<FreeMonController> controller);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start registration of mongod with remote service.
|
|
||||||
*
|
|
||||||
* Only sends one remote registration at a time.
|
|
||||||
* Returns after timeout if registrations is not complete. Registration continues though.
|
|
||||||
*/
|
|
||||||
void registerServerStartup(RegistrationType registrationType, std::vector<std::string>& tags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start registration of mongod with remote service.
|
|
||||||
*
|
|
||||||
* Only sends one remote registration at a time.
|
|
||||||
* Returns after timeout if registrations is not complete. Registration continues though.
|
|
||||||
* Update is synchronous with 10sec timeout
|
|
||||||
* kicks off register, and once register is done kicks off metrics upload
|
|
||||||
*/
|
|
||||||
boost::optional<Status> registerServerCommand(Milliseconds timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop registration of mongod with remote service.
|
|
||||||
*
|
|
||||||
* As with registerServerCommand() above, but undoes registration.
|
|
||||||
* On complettion of this command, no further metrics will be transmitted.
|
|
||||||
*/
|
|
||||||
boost::optional<Status> unregisterServerCommand(Milliseconds timeout);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates an info blob for use by {getFreeMonitoringStatus: 1}
|
|
||||||
*/
|
|
||||||
void getStatus(OperationContext* opCtx, BSONObjBuilder* status);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates an info blob for use by {serverStatus: 1}
|
|
||||||
*/
|
|
||||||
void getServerStatus(OperationContext* opCtx, BSONObjBuilder* status);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify on upsert.
|
|
||||||
*
|
|
||||||
* Updates and inserts are treated as the same.
|
|
||||||
*/
|
|
||||||
void notifyOnUpsert(const BSONObj& doc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify on document delete or drop collection.
|
|
||||||
*/
|
|
||||||
void notifyOnDelete();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that we local instance has become a primary.
|
|
||||||
*/
|
|
||||||
void notifyOnTransitionToPrimary();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that storage has rolled back
|
|
||||||
*/
|
|
||||||
void notifyOnRollback();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _enqueue(std::shared_ptr<FreeMonMessage> msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Private enum to track state.
|
|
||||||
*
|
|
||||||
* +-----------------------------------------------------------+
|
|
||||||
* | v
|
|
||||||
* +-------------+ +----------+ +----------------+ +-------+
|
|
||||||
* | kNotStarted | --> | kStarted | --> | kStopRequested | --> | kDone |
|
|
||||||
* +-------------+ +----------+ +----------------+ +-------+
|
|
||||||
*/
|
|
||||||
enum class State {
|
|
||||||
/**
|
|
||||||
* Initial state. Either start() or stop() can be called next.
|
|
||||||
*/
|
|
||||||
kNotStarted,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* start() has been called. stop() should be called next.
|
|
||||||
*/
|
|
||||||
kStarted,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* stop() has been called, and the background thread is in progress of shutting down
|
|
||||||
*/
|
|
||||||
kStopRequested,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller has been stopped.
|
|
||||||
*/
|
|
||||||
kDone,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Controller state
|
|
||||||
State _state{State::kNotStarted};
|
|
||||||
|
|
||||||
// Mutext to protect internal state
|
|
||||||
Mutex _mutex = MONGO_MAKE_LATCH("FreeMonController::_mutex");
|
|
||||||
|
|
||||||
// Set of registration collectors
|
|
||||||
FreeMonCollectorCollection _registrationCollectors;
|
|
||||||
|
|
||||||
// Set of metric collectors
|
|
||||||
FreeMonCollectorCollection _metricCollectors;
|
|
||||||
|
|
||||||
// Network interface
|
|
||||||
std::unique_ptr<FreeMonNetworkInterface> _network;
|
|
||||||
|
|
||||||
// Background thead for agent
|
|
||||||
stdx::thread _thread;
|
|
||||||
|
|
||||||
// Crank for test
|
|
||||||
bool _useCrankForTest;
|
|
||||||
|
|
||||||
// Background agent
|
|
||||||
std::shared_ptr<FreeMonProcessor> _processor;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,413 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_protocol_gen.h"
|
|
||||||
#include "mongo/platform/mutex.h"
|
|
||||||
#include "mongo/stdx/condition_variable.h"
|
|
||||||
#include "mongo/util/duration.h"
|
|
||||||
#include "mongo/util/time_support.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message types for free monitoring.
|
|
||||||
*
|
|
||||||
* Some are generated internally by FreeMonProcessor to handle async HTTP requests.
|
|
||||||
*/
|
|
||||||
enum class FreeMonMessageType {
|
|
||||||
/**
|
|
||||||
* Register server from command-line/config.
|
|
||||||
*/
|
|
||||||
RegisterServer,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register server from server command.
|
|
||||||
*/
|
|
||||||
RegisterCommand,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal: Generated when an async registration HTTP request completes succesfully.
|
|
||||||
*/
|
|
||||||
AsyncRegisterComplete,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal: Generated when an async registration HTTP request completes with an error.
|
|
||||||
*/
|
|
||||||
AsyncRegisterFail,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unregister server from server command.
|
|
||||||
*/
|
|
||||||
UnregisterCommand,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal: Collect metrics and buffer them in-memory
|
|
||||||
*/
|
|
||||||
MetricsCollect,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal: Send metrics to the cloud endpoint by beginning an async HTTP request.
|
|
||||||
*/
|
|
||||||
MetricsSend,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal: Generated when an async metrics HTTP request completes succesfully.
|
|
||||||
*/
|
|
||||||
AsyncMetricsComplete,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal: Generated when an async metrics HTTP request completes with an error.
|
|
||||||
*/
|
|
||||||
AsyncMetricsFail,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that the node has been made a primary replica.
|
|
||||||
*/
|
|
||||||
OnTransitionToPrimary,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that storage has received an insert or update.
|
|
||||||
*/
|
|
||||||
NotifyOnUpsert,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that storage has received a delete or drop collection.
|
|
||||||
*/
|
|
||||||
NotifyOnDelete,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that storage has been rolled back.
|
|
||||||
*/
|
|
||||||
NotifyOnRollback,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Supported types of registration that occur on server startup.
|
|
||||||
*/
|
|
||||||
enum class RegistrationType {
|
|
||||||
/**
|
|
||||||
* Do not register on start because it was not configured via commandline/config file.
|
|
||||||
*/
|
|
||||||
DoNotRegister,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register immediately on start since we are a standalone.
|
|
||||||
*/
|
|
||||||
RegisterOnStart,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register after transition to becoming primary because we are in a replica set,
|
|
||||||
* and Free Monitoring has been explicitly enabled.
|
|
||||||
*/
|
|
||||||
RegisterAfterOnTransitionToPrimary,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As above, but only if we have been runtime enabled.
|
|
||||||
*/
|
|
||||||
RegisterAfterOnTransitionToPrimaryIfEnabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message class that encapsulate a message to the FreeMonMessageProcessor
|
|
||||||
*
|
|
||||||
* Has a type and a deadline for when to start processing the message.
|
|
||||||
*/
|
|
||||||
class FreeMonMessage {
|
|
||||||
public:
|
|
||||||
virtual ~FreeMonMessage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message that should processed immediately.
|
|
||||||
*/
|
|
||||||
static std::shared_ptr<FreeMonMessage> createNow(FreeMonMessageType type) {
|
|
||||||
return std::make_shared<FreeMonMessage>(type, Date_t());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message that should processed after the specified deadline.
|
|
||||||
*/
|
|
||||||
static std::shared_ptr<FreeMonMessage> createWithDeadline(FreeMonMessageType type,
|
|
||||||
Date_t deadline) {
|
|
||||||
return std::make_shared<FreeMonMessage>(type, deadline);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeMonMessage(const FreeMonMessage&) = delete;
|
|
||||||
FreeMonMessage(FreeMonMessage&&) = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the type of message.
|
|
||||||
*/
|
|
||||||
FreeMonMessageType getType() const {
|
|
||||||
return _type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the deadline for the message.
|
|
||||||
*/
|
|
||||||
Date_t getDeadline() const {
|
|
||||||
return _deadline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the unique message id for FIFO ordering messages with the same deadline.
|
|
||||||
*/
|
|
||||||
uint64_t getId() const {
|
|
||||||
return _id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the unique message id.
|
|
||||||
*/
|
|
||||||
void setId(uint64_t id) {
|
|
||||||
_id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
FreeMonMessage(FreeMonMessageType type, Date_t deadline) : _type(type), _deadline(deadline) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Type of message
|
|
||||||
FreeMonMessageType _type;
|
|
||||||
|
|
||||||
// Deadline for when to process message
|
|
||||||
Date_t _deadline;
|
|
||||||
|
|
||||||
// Process-wide unique message id to ensure messages with the same deadlines are processed in
|
|
||||||
// FIFO order.
|
|
||||||
uint64_t _id{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Most messages have a simple payload, and this template ensures we create type-safe messages for
|
|
||||||
* each message type without copy-pasting repeatedly.
|
|
||||||
*/
|
|
||||||
template <FreeMonMessageType typeT>
|
|
||||||
struct FreeMonPayloadForMessage {
|
|
||||||
using payload_type = void;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonPayloadForMessage<FreeMonMessageType::AsyncRegisterComplete> {
|
|
||||||
using payload_type = FreeMonRegistrationResponse;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonPayloadForMessage<FreeMonMessageType::RegisterServer> {
|
|
||||||
using payload_type = std::pair<RegistrationType, std::vector<std::string>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonPayloadForMessage<FreeMonMessageType::AsyncRegisterFail> {
|
|
||||||
using payload_type = Status;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonPayloadForMessage<FreeMonMessageType::AsyncMetricsComplete> {
|
|
||||||
using payload_type = FreeMonMetricsResponse;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonPayloadForMessage<FreeMonMessageType::AsyncMetricsFail> {
|
|
||||||
using payload_type = Status;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonPayloadForMessage<FreeMonMessageType::NotifyOnUpsert> {
|
|
||||||
using payload_type = BSONObj;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message with a generic payload based on the type of message.
|
|
||||||
*/
|
|
||||||
template <FreeMonMessageType typeT>
|
|
||||||
class FreeMonMessageWithPayload : public FreeMonMessage {
|
|
||||||
public:
|
|
||||||
using payload_type = typename FreeMonPayloadForMessage<typeT>::payload_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message that should processed immediately.
|
|
||||||
*/
|
|
||||||
static std::shared_ptr<FreeMonMessageWithPayload> createNow(payload_type t) {
|
|
||||||
return std::make_shared<FreeMonMessageWithPayload>(t, Date_t{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get message payload.
|
|
||||||
*/
|
|
||||||
const payload_type& getPayload() const {
|
|
||||||
return _t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
FreeMonMessageWithPayload(payload_type t, Date_t deadline)
|
|
||||||
: FreeMonMessage(typeT, deadline), _t(std::move(t)) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Message payload
|
|
||||||
payload_type _t;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Single-shot class that encapsulates a Status and allows a caller to wait for a time.
|
|
||||||
*
|
|
||||||
* Basically, a single producer, single consumer queue with one event.
|
|
||||||
*/
|
|
||||||
class WaitableResult {
|
|
||||||
public:
|
|
||||||
WaitableResult() : _status(Status::OK()) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Status and signal waiter.
|
|
||||||
*/
|
|
||||||
void set(Status status) {
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
invariant(!_set);
|
|
||||||
if (!_set) {
|
|
||||||
_set = true;
|
|
||||||
_status = std::move(status);
|
|
||||||
_condvar.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for duration until status has been set.
|
|
||||||
*
|
|
||||||
* Returns boost::none on timeout.
|
|
||||||
*/
|
|
||||||
boost::optional<Status> wait_for(Milliseconds duration) {
|
|
||||||
stdx::unique_lock<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
if (!_condvar.wait_for(lock, duration.toSystemDuration(), [this]() { return _set; })) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return _status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Condition variable to signal consumer
|
|
||||||
stdx::condition_variable _condvar;
|
|
||||||
|
|
||||||
// Lock for condition variable and to protect state
|
|
||||||
Mutex _mutex = MONGO_MAKE_LATCH("WaitableResult::_mutex");
|
|
||||||
|
|
||||||
// Indicates whether _status has been set
|
|
||||||
bool _set{false};
|
|
||||||
|
|
||||||
// Provided status
|
|
||||||
Status _status;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For the messages that the caller needs to wait on, this provides a mechanism to wait on messages
|
|
||||||
* to be processed.
|
|
||||||
*/
|
|
||||||
template <FreeMonMessageType typeT>
|
|
||||||
struct FreeMonWaitablePayloadForMessage {
|
|
||||||
using payload_type = void;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonWaitablePayloadForMessage<FreeMonMessageType::RegisterCommand> {
|
|
||||||
using payload_type = std::pair<std::vector<std::string>, boost::optional<std::string>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct FreeMonWaitablePayloadForMessage<FreeMonMessageType::UnregisterCommand> {
|
|
||||||
// The parameter is unused but most not be void.
|
|
||||||
using payload_type = bool;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message with a generic payload based on the type of message.
|
|
||||||
*/
|
|
||||||
template <FreeMonMessageType typeT>
|
|
||||||
class FreeMonWaitableMessageWithPayload : public FreeMonMessage {
|
|
||||||
public:
|
|
||||||
using payload_type = typename FreeMonWaitablePayloadForMessage<typeT>::payload_type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message that should processed immediately.
|
|
||||||
*/
|
|
||||||
static std::shared_ptr<FreeMonWaitableMessageWithPayload> createNow(payload_type t) {
|
|
||||||
return std::make_shared<FreeMonWaitableMessageWithPayload>(t, Date_t());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message that should processed immediately.
|
|
||||||
*/
|
|
||||||
static std::shared_ptr<FreeMonWaitableMessageWithPayload> createWithDeadline(payload_type t,
|
|
||||||
Date_t deadline) {
|
|
||||||
return std::make_shared<FreeMonWaitableMessageWithPayload>(t, deadline);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get message payload.
|
|
||||||
*/
|
|
||||||
const payload_type& getPayload() const {
|
|
||||||
return _t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Status and signal waiter.
|
|
||||||
*/
|
|
||||||
void setStatus(Status status) {
|
|
||||||
_waitable.set(std::move(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for duration until status has been set.
|
|
||||||
*
|
|
||||||
* Returns boost::none on timeout.
|
|
||||||
*/
|
|
||||||
boost::optional<Status> wait_for(Milliseconds duration) {
|
|
||||||
return _waitable.wait_for(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
FreeMonWaitableMessageWithPayload(payload_type t, Date_t deadline)
|
|
||||||
: FreeMonMessage(typeT, deadline), _t(std::move(t)) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Message payload
|
|
||||||
payload_type _t;
|
|
||||||
|
|
||||||
// WaitaleResult to notify caller
|
|
||||||
WaitableResult _waitable{};
|
|
||||||
};
|
|
||||||
|
|
||||||
using FreeMonRegisterCommandMessage =
|
|
||||||
FreeMonWaitableMessageWithPayload<FreeMonMessageType::RegisterCommand>;
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,373 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_mongod.h"
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <snappy.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "mongo/base/data_type_validated.h"
|
|
||||||
#include "mongo/base/error_codes.h"
|
|
||||||
#include "mongo/base/status.h"
|
|
||||||
#include "mongo/bson/bsonelement.h"
|
|
||||||
#include "mongo/bson/bsonmisc.h"
|
|
||||||
#include "mongo/bson/bsonobj.h"
|
|
||||||
#include "mongo/bson/bsonobjbuilder.h"
|
|
||||||
#include "mongo/bson/bsontypes.h"
|
|
||||||
#include "mongo/db/db_raii.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_controller.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_message.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_mongod_gen.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_network.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_op_observer.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_options.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_protocol_gen.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage.h"
|
|
||||||
#include "mongo/db/ftdc/ftdc_server.h"
|
|
||||||
#include "mongo/db/operation_context.h"
|
|
||||||
#include "mongo/db/repl/replication_coordinator.h"
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
#include "mongo/executor/network_interface_factory.h"
|
|
||||||
#include "mongo/executor/thread_pool_task_executor.h"
|
|
||||||
#include "mongo/rpc/object_check.h"
|
|
||||||
#include "mongo/util/assert_util.h"
|
|
||||||
#include "mongo/util/concurrency/thread_pool.h"
|
|
||||||
#include "mongo/util/future.h"
|
|
||||||
#include "mongo/util/net/http_client.h"
|
|
||||||
#include "mongo/util/testing_proctor.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
constexpr Seconds kDefaultMetricsGatherInterval(60);
|
|
||||||
|
|
||||||
auto makeTaskExecutor(ServiceContext* /*serviceContext*/) {
|
|
||||||
ThreadPool::Options tpOptions;
|
|
||||||
tpOptions.poolName = "FreeMonHTTP";
|
|
||||||
tpOptions.maxThreads = 2;
|
|
||||||
tpOptions.onCreateThread = [](const std::string& threadName) {
|
|
||||||
Client::initThread(threadName.c_str());
|
|
||||||
};
|
|
||||||
return std::make_unique<executor::ThreadPoolTaskExecutor>(
|
|
||||||
std::make_unique<ThreadPool>(tpOptions), executor::makeNetworkInterface("FreeMonNet"));
|
|
||||||
}
|
|
||||||
|
|
||||||
class FreeMonNetworkHttp final : public FreeMonNetworkInterface {
|
|
||||||
public:
|
|
||||||
explicit FreeMonNetworkHttp(ServiceContext* serviceContext) {
|
|
||||||
_executor = makeTaskExecutor(serviceContext);
|
|
||||||
_executor->startup();
|
|
||||||
_client = HttpClient::create();
|
|
||||||
_client->allowInsecureHTTP(TestingProctor::instance().isEnabled());
|
|
||||||
_client->setHeaders({"Content-Type: application/octet-stream",
|
|
||||||
"Accept: application/octet-stream",
|
|
||||||
"Expect:"});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<FreeMonRegistrationResponse> sendRegistrationAsync(
|
|
||||||
const FreeMonRegistrationRequest& req) override {
|
|
||||||
BSONObj reqObj = req.toBSON();
|
|
||||||
auto data = std::make_shared<std::vector<std::uint8_t>>(
|
|
||||||
reqObj.objdata(), reqObj.objdata() + reqObj.objsize());
|
|
||||||
|
|
||||||
return post("/register", data).then([](DataBuilder&& blob) {
|
|
||||||
if (!blob.size()) {
|
|
||||||
uasserted(ErrorCodes::FreeMonHttpTemporaryFailure, "Empty response received");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto blobSize = blob.size();
|
|
||||||
auto blobData = blob.release();
|
|
||||||
ConstDataRange cdr(blobData.get(), blobSize);
|
|
||||||
BSONObj respObj = cdr.read<Validated<BSONObj>>();
|
|
||||||
|
|
||||||
auto resp =
|
|
||||||
FreeMonRegistrationResponse::parse(IDLParserErrorContext("response"), respObj);
|
|
||||||
|
|
||||||
return resp;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<FreeMonMetricsResponse> sendMetricsAsync(const FreeMonMetricsRequest& req) override {
|
|
||||||
BSONObj reqObj = req.toBSON();
|
|
||||||
auto data = std::make_shared<std::vector<std::uint8_t>>(
|
|
||||||
reqObj.objdata(), reqObj.objdata() + reqObj.objsize());
|
|
||||||
|
|
||||||
return post("/metrics", data).then([](DataBuilder&& blob) {
|
|
||||||
if (!blob.size()) {
|
|
||||||
uasserted(ErrorCodes::FreeMonHttpTemporaryFailure, "Empty response received");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto blobSize = blob.size();
|
|
||||||
auto blobData = blob.release();
|
|
||||||
ConstDataRange cdr(blobData.get(), blobSize);
|
|
||||||
|
|
||||||
BSONObj respObj = cdr.read<Validated<BSONObj>>();
|
|
||||||
|
|
||||||
auto resp = FreeMonMetricsResponse::parse(IDLParserErrorContext("response"), respObj);
|
|
||||||
|
|
||||||
return resp;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Future<DataBuilder> post(StringData path,
|
|
||||||
std::shared_ptr<std::vector<std::uint8_t>> data) const {
|
|
||||||
auto pf = makePromiseFuture<DataBuilder>();
|
|
||||||
std::string url(FreeMonEndpointURL + path.toString());
|
|
||||||
|
|
||||||
auto status = _executor->scheduleWork(
|
|
||||||
[promise = std::move(pf.promise), url = std::move(url), data = std::move(data), this](
|
|
||||||
const executor::TaskExecutor::CallbackArgs& cbArgs) mutable {
|
|
||||||
ConstDataRange cdr(data->data(), data->size());
|
|
||||||
try {
|
|
||||||
auto result = this->_client->post(url, cdr);
|
|
||||||
promise.emplaceValue(std::move(result));
|
|
||||||
} catch (...) {
|
|
||||||
promise.setError(exceptionToStatus());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
uassertStatusOK(status);
|
|
||||||
return std::move(pf.future);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<HttpClient> _client;
|
|
||||||
std::unique_ptr<executor::ThreadPoolTaskExecutor> _executor;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect the mms-automation state document from local.clustermanager during registration.
|
|
||||||
*/
|
|
||||||
class FreeMonLocalClusterManagerCollector : public FreeMonCollectorInterface {
|
|
||||||
public:
|
|
||||||
std::string name() const final {
|
|
||||||
return "clustermanager";
|
|
||||||
}
|
|
||||||
|
|
||||||
void collect(OperationContext* opCtx, BSONObjBuilder& builder) {
|
|
||||||
auto optionalObj = FreeMonStorage::readClusterManagerState(opCtx);
|
|
||||||
if (optionalObj.is_initialized()) {
|
|
||||||
builder.appendElements(optionalObj.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the "storageEngine" section of "serverStatus" during registration.
|
|
||||||
*/
|
|
||||||
class FreeMonLocalStorageEngineStatusCollector : public FTDCSimpleInternalCommandCollector {
|
|
||||||
public:
|
|
||||||
FreeMonLocalStorageEngineStatusCollector()
|
|
||||||
: FTDCSimpleInternalCommandCollector(
|
|
||||||
"serverStatus",
|
|
||||||
"serverStatus",
|
|
||||||
"",
|
|
||||||
// Try to filter server status to make it cheaper to collect. Harmless if we gather
|
|
||||||
// extra
|
|
||||||
BSON("serverStatus" << 1 << "storageEngine" << true << "extra_info" << false
|
|
||||||
<< "opLatencies" << false << "opcountersRepl" << false
|
|
||||||
<< "opcounters" << false << "transactions" << false
|
|
||||||
<< "connections" << false << "network" << false << "tcMalloc"
|
|
||||||
<< false << "network" << false << "wiredTiger" << false
|
|
||||||
<< "sharding" << false << "metrics" << false)) {}
|
|
||||||
|
|
||||||
std::string name() const final {
|
|
||||||
return "storageEngine";
|
|
||||||
}
|
|
||||||
|
|
||||||
void collect(OperationContext* opCtx, BSONObjBuilder& builder) {
|
|
||||||
BSONObjBuilder localBuilder;
|
|
||||||
|
|
||||||
FTDCSimpleInternalCommandCollector::collect(opCtx, localBuilder);
|
|
||||||
|
|
||||||
BSONObj obj = localBuilder.obj();
|
|
||||||
|
|
||||||
builder.appendElements(obj["storageEngine"].Obj());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect the UUIDs associated with the named collections (if available).
|
|
||||||
*/
|
|
||||||
class FreeMonNamespaceUUIDCollector : public FreeMonCollectorInterface {
|
|
||||||
public:
|
|
||||||
FreeMonNamespaceUUIDCollector(std::set<NamespaceString> namespaces)
|
|
||||||
: _namespaces(std::move(namespaces)) {}
|
|
||||||
|
|
||||||
std::string name() const final {
|
|
||||||
return "uuid";
|
|
||||||
}
|
|
||||||
|
|
||||||
void collect(OperationContext* opCtx, BSONObjBuilder& builder) {
|
|
||||||
auto catalog = CollectionCatalog::get(opCtx);
|
|
||||||
for (auto& nss : _namespaces) {
|
|
||||||
auto optUUID = catalog->lookupUUIDByNSS(opCtx, nss);
|
|
||||||
if (optUUID) {
|
|
||||||
builder << nss.toString() << optUUID.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::set<NamespaceString> _namespaces;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
Status onValidateFreeMonEndpointURL(StringData str) {
|
|
||||||
// Check for http, not https here because testEnabled may not be set yet
|
|
||||||
if (!str.startsWith("http"_sd) != 0) {
|
|
||||||
return Status(ErrorCodes::BadValue,
|
|
||||||
"cloudFreeMonitoringEndpointURL only supports http:// URLs");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerCollectors(FreeMonController* controller) {
|
|
||||||
// These are collected only at registration
|
|
||||||
//
|
|
||||||
// CmdBuildInfo
|
|
||||||
controller->addRegistrationCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"buildInfo", "buildInfo", "", BSON("buildInfo" << 1)));
|
|
||||||
|
|
||||||
// HostInfoCmd
|
|
||||||
controller->addRegistrationCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"hostInfo", "hostInfo", "", BSON("hostInfo" << 1)));
|
|
||||||
|
|
||||||
// Add storageEngine section from serverStatus
|
|
||||||
controller->addRegistrationCollector(
|
|
||||||
std::make_unique<FreeMonLocalStorageEngineStatusCollector>());
|
|
||||||
|
|
||||||
// Gather one document from local.clustermanager
|
|
||||||
controller->addRegistrationCollector(std::make_unique<FreeMonLocalClusterManagerCollector>());
|
|
||||||
|
|
||||||
// These are periodically for metrics upload
|
|
||||||
//
|
|
||||||
controller->addMetricsCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"getDiagnosticData", "diagnosticData", "", BSON("getDiagnosticData" << 1)));
|
|
||||||
|
|
||||||
// These are collected at registration and as metrics periodically
|
|
||||||
//
|
|
||||||
if (repl::ReplicationCoordinator::get(getGlobalServiceContext())->getReplicationMode() !=
|
|
||||||
repl::ReplicationCoordinator::modeNone) {
|
|
||||||
// CmdReplSetGetConfig
|
|
||||||
controller->addRegistrationCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"replSetGetConfig", "replSetGetConfig", "", BSON("replSetGetConfig" << 1)));
|
|
||||||
|
|
||||||
controller->addMetricsCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"replSetGetConfig", "replSetGetConfig", "", BSON("replSetGetConfig" << 1)));
|
|
||||||
|
|
||||||
// Collect UUID for certain collections.
|
|
||||||
std::set<NamespaceString> namespaces({NamespaceString("local.oplog.rs")});
|
|
||||||
controller->addRegistrationCollector(
|
|
||||||
std::make_unique<FreeMonNamespaceUUIDCollector>(namespaces));
|
|
||||||
controller->addMetricsCollector(
|
|
||||||
std::make_unique<FreeMonNamespaceUUIDCollector>(namespaces));
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->addRegistrationCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"isMaster", "isMaster", "", BSON("isMaster" << 1)));
|
|
||||||
|
|
||||||
controller->addMetricsCollector(std::make_unique<FTDCSimpleInternalCommandCollector>(
|
|
||||||
"isMaster", "isMaster", "", BSON("isMaster" << 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void startFreeMonitoring(ServiceContext* serviceContext) {
|
|
||||||
if (globalFreeMonParams.freeMonitoringState == EnableCloudStateEnum::kOff) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TestingProctor::instance().isEnabled()) {
|
|
||||||
uassert(50774,
|
|
||||||
"ExportedFreeMonEndpointURL only supports https:// URLs",
|
|
||||||
FreeMonEndpointURL.compare(0, 5, "https") == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto network = std::unique_ptr<FreeMonNetworkInterface>(new FreeMonNetworkHttp(serviceContext));
|
|
||||||
|
|
||||||
auto controller = std::make_unique<FreeMonController>(std::move(network));
|
|
||||||
|
|
||||||
auto controllerPtr = controller.get();
|
|
||||||
|
|
||||||
registerCollectors(controller.get());
|
|
||||||
|
|
||||||
// Install the new controller
|
|
||||||
FreeMonController::init(getGlobalServiceContext(), std::move(controller));
|
|
||||||
|
|
||||||
RegistrationType registrationType = RegistrationType::DoNotRegister;
|
|
||||||
if (globalFreeMonParams.freeMonitoringState == EnableCloudStateEnum::kOn) {
|
|
||||||
// If replication is enabled, we may need to register on becoming primary
|
|
||||||
if (repl::ReplicationCoordinator::get(getGlobalServiceContext())->getReplicationMode() !=
|
|
||||||
repl::ReplicationCoordinator::modeNone) {
|
|
||||||
registrationType = RegistrationType::RegisterAfterOnTransitionToPrimary;
|
|
||||||
} else {
|
|
||||||
registrationType = RegistrationType::RegisterOnStart;
|
|
||||||
}
|
|
||||||
} else if (globalFreeMonParams.freeMonitoringState == EnableCloudStateEnum::kRuntime) {
|
|
||||||
registrationType = RegistrationType::RegisterAfterOnTransitionToPrimaryIfEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
controllerPtr->start(registrationType,
|
|
||||||
globalFreeMonParams.freeMonitoringTags,
|
|
||||||
Seconds(kDefaultMetricsGatherInterval));
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopFreeMonitoring() {
|
|
||||||
if (globalFreeMonParams.freeMonitoringState == EnableCloudStateEnum::kOff) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto controller = FreeMonController::get(getGlobalServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void notifyFreeMonitoringOnTransitionToPrimary() {
|
|
||||||
auto controller = FreeMonController::get(getGlobalServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->notifyOnTransitionToPrimary();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupFreeMonitoringOpObserver(OpObserverRegistry* registry) {
|
|
||||||
registry->addObserver(std::make_unique<FreeMonOpObserver>());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "mongo/db/op_observer_registry.h"
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start Free Monitoring
|
|
||||||
* Starts 1 thread.
|
|
||||||
*/
|
|
||||||
void startFreeMonitoring(ServiceContext* serviceContext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop Free Monitoring
|
|
||||||
*/
|
|
||||||
void stopFreeMonitoring();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify free monitoring about a replica set member becoming primary
|
|
||||||
*/
|
|
||||||
void notifyFreeMonitoringOnTransitionToPrimary();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup Free Monitoring OpObserver.
|
|
||||||
*
|
|
||||||
* Called before free monitoring is started.
|
|
||||||
*/
|
|
||||||
void setupFreeMonitoringOpObserver(OpObserverRegistry* registry);
|
|
||||||
|
|
||||||
Status onValidateFreeMonEndpointURL(StringData str);
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
# Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the Server Side Public License, version 1,
|
|
||||||
# as published by MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# Server Side Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the Server Side Public License
|
|
||||||
# along with this program. If not, see
|
|
||||||
# <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
#
|
|
||||||
# As a special exception, the copyright holders give permission to link the
|
|
||||||
# code of portions of this program with the OpenSSL library under certain
|
|
||||||
# conditions as described in each individual source file and distribute
|
|
||||||
# linked combinations including the program with the OpenSSL library. You
|
|
||||||
# must comply with the Server Side Public License in all respects for
|
|
||||||
# all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
# with this exception, you may extend this exception to your version of the
|
|
||||||
# file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
# delete this exception statement from your version. If you delete this
|
|
||||||
# exception statement from all source files in the program, then also delete
|
|
||||||
# it in the license file.
|
|
||||||
#
|
|
||||||
|
|
||||||
global:
|
|
||||||
cpp_namespace: "mongo"
|
|
||||||
cpp_includes:
|
|
||||||
- "mongo/db/free_mon/free_mon_mongod.h"
|
|
||||||
|
|
||||||
imports:
|
|
||||||
- "mongo/idl/basic_types.idl"
|
|
||||||
|
|
||||||
server_parameters:
|
|
||||||
|
|
||||||
cloudFreeMonitoringEndpointURL:
|
|
||||||
description: "Suppress logging of warnings when non-SSL connections are accepted in preferSSL mode"
|
|
||||||
set_at: startup
|
|
||||||
default: "https://cloud.mongodb.com/freemonitoring/mongo"
|
|
||||||
cpp_vartype: std::string
|
|
||||||
cpp_varname: FreeMonEndpointURL
|
|
||||||
validator:
|
|
||||||
callback: "onValidateFreeMonEndpointURL"
|
|
||||||
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_protocol_gen.h"
|
|
||||||
#include "mongo/util/future.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes HTTPS calls to cloud endpoint.
|
|
||||||
*/
|
|
||||||
class FreeMonNetworkInterface {
|
|
||||||
public:
|
|
||||||
virtual ~FreeMonNetworkInterface();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POSTs FreeMonRegistrationRequest to endpoint.
|
|
||||||
*
|
|
||||||
* Returns a FreeMonRegistrationResponse or throws an error on non-HTTP 200.
|
|
||||||
*/
|
|
||||||
virtual Future<FreeMonRegistrationResponse> sendRegistrationAsync(
|
|
||||||
const FreeMonRegistrationRequest& req) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POSTs FreeMonMetricsRequest to endpoint.
|
|
||||||
*
|
|
||||||
* Returns a FreeMonMetricsResponse or throws an error on non-HTTP 200.
|
|
||||||
*/
|
|
||||||
virtual Future<FreeMonMetricsResponse> sendMetricsAsync(const FreeMonMetricsRequest& req) = 0;
|
|
||||||
};
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_op_observer.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_controller.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage.h"
|
|
||||||
#include "mongo/db/operation_context.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool isStandaloneOrPrimary(OperationContext* opCtx) {
|
|
||||||
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
|
|
||||||
const bool isReplSet =
|
|
||||||
replCoord->getReplicationMode() == repl::ReplicationCoordinator::modeReplSet;
|
|
||||||
return !isReplSet ||
|
|
||||||
(repl::ReplicationCoordinator::get(opCtx)->getMemberState() ==
|
|
||||||
repl::MemberState::RS_PRIMARY);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto getFreeMonDeleteState = OperationContext::declareDecoration<bool>();
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
FreeMonOpObserver::FreeMonOpObserver() = default;
|
|
||||||
|
|
||||||
FreeMonOpObserver::~FreeMonOpObserver() = default;
|
|
||||||
|
|
||||||
repl::OpTime FreeMonOpObserver::onDropCollection(OperationContext* opCtx,
|
|
||||||
const NamespaceString& collectionName,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
std::uint64_t numRecords,
|
|
||||||
const CollectionDropType dropType) {
|
|
||||||
if (collectionName == NamespaceString::kServerConfigurationNamespace) {
|
|
||||||
auto controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->notifyOnDelete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonOpObserver::onInserts(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
std::vector<InsertStatement>::const_iterator begin,
|
|
||||||
std::vector<InsertStatement>::const_iterator end,
|
|
||||||
bool fromMigrate) {
|
|
||||||
if (nss != NamespaceString::kServerConfigurationNamespace) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isStandaloneOrPrimary(opCtx)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = begin; it != end; ++it) {
|
|
||||||
const auto& insertedDoc = it->doc;
|
|
||||||
|
|
||||||
if (auto idElem = insertedDoc["_id"]) {
|
|
||||||
if (idElem.str() == FreeMonStorage::kFreeMonDocIdKey) {
|
|
||||||
auto controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->notifyOnUpsert(insertedDoc.getOwned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonOpObserver::onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) {
|
|
||||||
if (args.nss != NamespaceString::kServerConfigurationNamespace) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isStandaloneOrPrimary(opCtx)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.updateArgs.updatedDoc["_id"].str() == FreeMonStorage::kFreeMonDocIdKey) {
|
|
||||||
auto controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->notifyOnUpsert(args.updateArgs.updatedDoc.getOwned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonOpObserver::aboutToDelete(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
const BSONObj& doc) {
|
|
||||||
|
|
||||||
bool isFreeMonDoc = (nss == NamespaceString::kServerConfigurationNamespace) &&
|
|
||||||
(doc["_id"].str() == FreeMonStorage::kFreeMonDocIdKey);
|
|
||||||
|
|
||||||
// Set a flag that indicates whether the document to be delete is the free monitoring state
|
|
||||||
// document
|
|
||||||
getFreeMonDeleteState(opCtx) = isFreeMonDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonOpObserver::onDelete(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
StmtId stmtId,
|
|
||||||
const OplogDeleteEntryArgs& args) {
|
|
||||||
if (nss != NamespaceString::kServerConfigurationNamespace) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isStandaloneOrPrimary(opCtx)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getFreeMonDeleteState(opCtx) == true) {
|
|
||||||
auto controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->notifyOnDelete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonOpObserver::onReplicationRollback(OperationContext* opCtx,
|
|
||||||
const RollbackObserverInfo& rbInfo) {
|
|
||||||
// Invalidate any in-memory auth data if necessary.
|
|
||||||
const auto& rollbackNamespaces = rbInfo.rollbackNamespaces;
|
|
||||||
if (rollbackNamespaces.count(NamespaceString::kServerConfigurationNamespace) == 1) {
|
|
||||||
auto controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
|
|
||||||
if (controller != nullptr) {
|
|
||||||
controller->notifyOnRollback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,208 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "mongo/db/op_observer.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OpObserver for Free Monitoring. Observes all secondary replication traffic and filters down to
|
|
||||||
* relevant entries for free monitoring.
|
|
||||||
*/
|
|
||||||
class FreeMonOpObserver final : public OpObserver {
|
|
||||||
FreeMonOpObserver(const FreeMonOpObserver&) = delete;
|
|
||||||
FreeMonOpObserver& operator=(const FreeMonOpObserver&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FreeMonOpObserver();
|
|
||||||
~FreeMonOpObserver();
|
|
||||||
|
|
||||||
void onCreateIndex(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
CollectionUUID uuid,
|
|
||||||
BSONObj indexDoc,
|
|
||||||
bool fromMigrate) final {}
|
|
||||||
|
|
||||||
void onStartIndexBuild(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
CollectionUUID collUUID,
|
|
||||||
const UUID& indexBuildUUID,
|
|
||||||
const std::vector<BSONObj>& indexes,
|
|
||||||
bool fromMigrate) final {}
|
|
||||||
|
|
||||||
void onStartIndexBuildSinglePhase(OperationContext* opCtx, const NamespaceString& nss) final {}
|
|
||||||
|
|
||||||
void onAbortIndexBuildSinglePhase(OperationContext* opCtx, const NamespaceString& nss) final {}
|
|
||||||
|
|
||||||
void onCommitIndexBuild(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
CollectionUUID collUUID,
|
|
||||||
const UUID& indexBuildUUID,
|
|
||||||
const std::vector<BSONObj>& indexes,
|
|
||||||
bool fromMigrate) final {}
|
|
||||||
|
|
||||||
void onAbortIndexBuild(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
CollectionUUID collUUID,
|
|
||||||
const UUID& indexBuildUUID,
|
|
||||||
const std::vector<BSONObj>& indexes,
|
|
||||||
const Status& cause,
|
|
||||||
bool fromMigrate) final {}
|
|
||||||
|
|
||||||
void onInserts(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
std::vector<InsertStatement>::const_iterator begin,
|
|
||||||
std::vector<InsertStatement>::const_iterator end,
|
|
||||||
bool fromMigrate) final;
|
|
||||||
|
|
||||||
void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final;
|
|
||||||
|
|
||||||
void aboutToDelete(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
const BSONObj& doc) final;
|
|
||||||
|
|
||||||
void onDelete(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
StmtId stmtId,
|
|
||||||
const OplogDeleteEntryArgs& args) final;
|
|
||||||
|
|
||||||
void onInternalOpMessage(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
const boost::optional<UUID> uuid,
|
|
||||||
const BSONObj& msgObj,
|
|
||||||
const boost::optional<BSONObj> o2MsgObj,
|
|
||||||
const boost::optional<repl::OpTime> preImageOpTime,
|
|
||||||
const boost::optional<repl::OpTime> postImageOpTime,
|
|
||||||
const boost::optional<repl::OpTime> prevWriteOpTimeInTransaction,
|
|
||||||
const boost::optional<OplogSlot> slot) final{};
|
|
||||||
|
|
||||||
void onCreateCollection(OperationContext* opCtx,
|
|
||||||
const CollectionPtr& coll,
|
|
||||||
const NamespaceString& collectionName,
|
|
||||||
const CollectionOptions& options,
|
|
||||||
const BSONObj& idIndex,
|
|
||||||
const OplogSlot& createOpTime) final {}
|
|
||||||
|
|
||||||
void onCollMod(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
const UUID& uuid,
|
|
||||||
const BSONObj& collModCmd,
|
|
||||||
const CollectionOptions& oldCollOptions,
|
|
||||||
boost::optional<IndexCollModInfo> indexInfo) final {}
|
|
||||||
|
|
||||||
void onDropDatabase(OperationContext* opCtx, const std::string& dbName) final {}
|
|
||||||
|
|
||||||
using OpObserver::onDropCollection;
|
|
||||||
repl::OpTime onDropCollection(OperationContext* opCtx,
|
|
||||||
const NamespaceString& collectionName,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
std::uint64_t numRecords,
|
|
||||||
CollectionDropType dropType) final;
|
|
||||||
|
|
||||||
void onDropIndex(OperationContext* opCtx,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
const std::string& indexName,
|
|
||||||
const BSONObj& indexInfo) final {}
|
|
||||||
|
|
||||||
using OpObserver::onRenameCollection;
|
|
||||||
void onRenameCollection(OperationContext* opCtx,
|
|
||||||
const NamespaceString& fromCollection,
|
|
||||||
const NamespaceString& toCollection,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
OptionalCollectionUUID dropTargetUUID,
|
|
||||||
std::uint64_t numRecords,
|
|
||||||
bool stayTemp) final {}
|
|
||||||
|
|
||||||
void onImportCollection(OperationContext* opCtx,
|
|
||||||
const UUID& importUUID,
|
|
||||||
const NamespaceString& nss,
|
|
||||||
long long numRecords,
|
|
||||||
long long dataSize,
|
|
||||||
const BSONObj& catalogEntry,
|
|
||||||
const BSONObj& storageMetadata,
|
|
||||||
bool isDryRun) final {}
|
|
||||||
|
|
||||||
using OpObserver::preRenameCollection;
|
|
||||||
repl::OpTime preRenameCollection(OperationContext* opCtx,
|
|
||||||
const NamespaceString& fromCollection,
|
|
||||||
const NamespaceString& toCollection,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
OptionalCollectionUUID dropTargetUUID,
|
|
||||||
std::uint64_t numRecords,
|
|
||||||
bool stayTemp) final {
|
|
||||||
return repl::OpTime();
|
|
||||||
}
|
|
||||||
void postRenameCollection(OperationContext* opCtx,
|
|
||||||
const NamespaceString& fromCollection,
|
|
||||||
const NamespaceString& toCollection,
|
|
||||||
OptionalCollectionUUID uuid,
|
|
||||||
OptionalCollectionUUID dropTargetUUID,
|
|
||||||
bool stayTemp) final {}
|
|
||||||
void onApplyOps(OperationContext* opCtx,
|
|
||||||
const std::string& dbName,
|
|
||||||
const BSONObj& applyOpCmd) final {}
|
|
||||||
|
|
||||||
void onEmptyCapped(OperationContext* opCtx,
|
|
||||||
const NamespaceString& collectionName,
|
|
||||||
OptionalCollectionUUID uuid) final {}
|
|
||||||
|
|
||||||
void onUnpreparedTransactionCommit(OperationContext* opCtx,
|
|
||||||
std::vector<repl::ReplOperation>* statements,
|
|
||||||
size_t numberOfPreImagesToWrite) final {}
|
|
||||||
|
|
||||||
void onPreparedTransactionCommit(
|
|
||||||
OperationContext* opCtx,
|
|
||||||
OplogSlot commitOplogEntryOpTime,
|
|
||||||
Timestamp commitTimestamp,
|
|
||||||
const std::vector<repl::ReplOperation>& statements) noexcept final {}
|
|
||||||
|
|
||||||
void onTransactionPrepare(OperationContext* opCtx,
|
|
||||||
const std::vector<OplogSlot>& reservedSlots,
|
|
||||||
std::vector<repl::ReplOperation>* statements,
|
|
||||||
size_t numberOfPreImagesToWrite) final {}
|
|
||||||
|
|
||||||
void onTransactionPrepareNonPrimary(OperationContext* opCtx,
|
|
||||||
const std::vector<repl::OplogEntry>& statements,
|
|
||||||
const repl::OpTime& prepareOpTime) final {}
|
|
||||||
|
|
||||||
void onTransactionAbort(OperationContext* opCtx,
|
|
||||||
boost::optional<OplogSlot> abortOplogEntryOpTime) final {}
|
|
||||||
|
|
||||||
void onReplicationRollback(OperationContext* opCtx, const RollbackObserverInfo& rbInfo);
|
|
||||||
|
|
||||||
void onMajorityCommitPointUpdate(ServiceContext* service,
|
|
||||||
const repl::OpTime& newCommitPoint) final {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kFTDC
|
|
||||||
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_options.h"
|
|
||||||
|
|
||||||
#include "mongo/base/error_codes.h"
|
|
||||||
#include "mongo/base/status.h"
|
|
||||||
#include "mongo/base/status_with.h"
|
|
||||||
#include "mongo/base/string_data.h"
|
|
||||||
#include "mongo/util/options_parser/startup_option_init.h"
|
|
||||||
#include "mongo/util/options_parser/startup_options.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
FreeMonParams globalFreeMonParams;
|
|
||||||
|
|
||||||
namespace optionenvironment {
|
|
||||||
class OptionSection;
|
|
||||||
class Environment;
|
|
||||||
} // namespace optionenvironment
|
|
||||||
|
|
||||||
namespace moe = mongo::optionenvironment;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
constexpr StringData kEnableCloudState_on = "on"_sd;
|
|
||||||
constexpr StringData kEnableCloudState_off = "off"_sd;
|
|
||||||
constexpr StringData kEnableCloudState_runtime = "runtime"_sd;
|
|
||||||
|
|
||||||
StatusWith<EnableCloudStateEnum> EnableCloudState_parse(StringData value) {
|
|
||||||
if (value == kEnableCloudState_on) {
|
|
||||||
return EnableCloudStateEnum::kOn;
|
|
||||||
}
|
|
||||||
if (value == kEnableCloudState_off) {
|
|
||||||
return EnableCloudStateEnum::kOff;
|
|
||||||
}
|
|
||||||
if (value == kEnableCloudState_runtime) {
|
|
||||||
return EnableCloudStateEnum::kRuntime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status(ErrorCodes::InvalidOptions, "Unrecognized state");
|
|
||||||
}
|
|
||||||
|
|
||||||
Status storeFreeMonitoringOptions(const moe::Environment& params) {
|
|
||||||
|
|
||||||
if (params.count("cloud.monitoring.free.state")) {
|
|
||||||
auto swState =
|
|
||||||
EnableCloudState_parse(params["cloud.monitoring.free.state"].as<std::string>());
|
|
||||||
if (!swState.isOK()) {
|
|
||||||
return swState.getStatus();
|
|
||||||
}
|
|
||||||
globalFreeMonParams.freeMonitoringState = swState.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.count("cloud.monitoring.free.tags")) {
|
|
||||||
globalFreeMonParams.freeMonitoringTags =
|
|
||||||
params["cloud.monitoring.free.tags"].as<std::vector<std::string>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
MONGO_STARTUP_OPTIONS_STORE(FreeMonitoringOptions)(InitializerContext*) {
|
|
||||||
uassertStatusOK(storeFreeMonitoringOptions(moe::startupOptionsParsed));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free Moniting Command line choices
|
|
||||||
*/
|
|
||||||
enum class EnableCloudStateEnum : std::int32_t {
|
|
||||||
kOn,
|
|
||||||
kOff,
|
|
||||||
kRuntime,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free Monitoring configuration options
|
|
||||||
*/
|
|
||||||
struct FreeMonParams {
|
|
||||||
std::vector<std::string> freeMonitoringTags;
|
|
||||||
EnableCloudStateEnum freeMonitoringState = EnableCloudStateEnum::kRuntime;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern FreeMonParams globalFreeMonParams;
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
# Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the Server Side Public License, version 1,
|
|
||||||
# as published by MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# Server Side Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the Server Side Public License
|
|
||||||
# along with this program. If not, see
|
|
||||||
# <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
#
|
|
||||||
# As a special exception, the copyright holders give permission to link the
|
|
||||||
# code of portions of this program with the OpenSSL library under certain
|
|
||||||
# conditions as described in each individual source file and distribute
|
|
||||||
# linked combinations including the program with the OpenSSL library. You
|
|
||||||
# must comply with the Server Side Public License in all respects for
|
|
||||||
# all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
# with this exception, you may extend this exception to your version of the
|
|
||||||
# file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
# delete this exception statement from your version. If you delete this
|
|
||||||
# exception statement from all source files in the program, then also delete
|
|
||||||
# it in the license file.
|
|
||||||
#
|
|
||||||
|
|
||||||
global:
|
|
||||||
cpp_namespace: "mongo"
|
|
||||||
configs:
|
|
||||||
section: "Free Monitoring Options"
|
|
||||||
source: [ yaml, cli]
|
|
||||||
|
|
||||||
imports:
|
|
||||||
- "mongo/idl/basic_types.idl"
|
|
||||||
|
|
||||||
configs:
|
|
||||||
# Command Line: --enableFreeMonitoring=<on|runtime|off>
|
|
||||||
# YAML Name: cloud.monitoring.free=<on|runtime|off>
|
|
||||||
cloud.monitoring.free.state:
|
|
||||||
description: "Enable Cloud Free Monitoring (on|runtime|off)"
|
|
||||||
short_name: enableFreeMonitoring
|
|
||||||
arg_vartype: String
|
|
||||||
|
|
||||||
# Command Line: --enableFreeMonitoringTag=array<string>
|
|
||||||
# YAML Name: cloud.monitoring.free.tag=array<string>
|
|
||||||
cloud.monitoring.free.tags:
|
|
||||||
description: "Cloud Free Monitoring Tags"
|
|
||||||
short_name: freeMonitoringTag
|
|
||||||
arg_vartype: StringVector
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,528 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <deque>
|
|
||||||
#include <memory>
|
|
||||||
#include <ratio>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "mongo/db/client.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_message.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_network.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_processor.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_protocol_gen.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_queue.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage_gen.h"
|
|
||||||
#include "mongo/db/ftdc/collector.h"
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
#include "mongo/util/clock_source.h"
|
|
||||||
#include "mongo/util/duration.h"
|
|
||||||
#include "mongo/util/future.h"
|
|
||||||
#include "mongo/util/synchronized_value.h"
|
|
||||||
#include "mongo/util/time_support.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
using FreeMonCollectorInterface = FTDCCollectorInterface;
|
|
||||||
using FreeMonCollectorCollection = FTDCCollectorCollection;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reponsible for tracking when to send the next retry after errors are encountered.
|
|
||||||
*/
|
|
||||||
class RetryCounter {
|
|
||||||
const int64_t kMax = 60 * 60 * 24;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RetryCounter() : _min(1), _max(kMax) {}
|
|
||||||
virtual ~RetryCounter() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Minimum rety interval
|
|
||||||
*/
|
|
||||||
void setMin(Seconds s) {
|
|
||||||
_min = s;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the retry interval, typically occurs after a succesfull message is sent.
|
|
||||||
*/
|
|
||||||
virtual void reset() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increment the error count and compute the next interval.
|
|
||||||
*/
|
|
||||||
virtual bool incrementError() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the next retry duration.
|
|
||||||
*/
|
|
||||||
Seconds getNextDuration() const {
|
|
||||||
dassert(_current != Seconds(0));
|
|
||||||
return _current;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the next retry deadline
|
|
||||||
*/
|
|
||||||
Date_t getNextDeadline(Client* client) const {
|
|
||||||
return client->getServiceContext()->getPreciseClockSource()->now() + _current;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Current retry interval
|
|
||||||
Seconds _current;
|
|
||||||
|
|
||||||
// Minimum retry interval
|
|
||||||
Seconds _min;
|
|
||||||
|
|
||||||
// Maximum retry interval
|
|
||||||
Seconds _max;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manage retries for registrations
|
|
||||||
*/
|
|
||||||
class RegistrationRetryCounter : public RetryCounter {
|
|
||||||
public:
|
|
||||||
explicit RegistrationRetryCounter(PseudoRandom& random) : _random(random) {}
|
|
||||||
|
|
||||||
void reset() final;
|
|
||||||
|
|
||||||
bool incrementError() final;
|
|
||||||
|
|
||||||
size_t getCount() const {
|
|
||||||
return _retryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Random number generator for jitter
|
|
||||||
PseudoRandom& _random;
|
|
||||||
|
|
||||||
// Retry count for stage 1 retry
|
|
||||||
size_t _retryCount{0};
|
|
||||||
|
|
||||||
// Total Seconds we have retried for
|
|
||||||
Seconds _total;
|
|
||||||
|
|
||||||
// Last retry interval without jitter
|
|
||||||
Seconds _base;
|
|
||||||
|
|
||||||
// Max Retry count
|
|
||||||
const size_t kStage1RetryCountMax{10};
|
|
||||||
|
|
||||||
const size_t kStage1JitterMin{2};
|
|
||||||
const size_t kStage1JitterMax{10};
|
|
||||||
|
|
||||||
const Hours kStage2DurationMax{48};
|
|
||||||
|
|
||||||
const size_t kStage2JitterMin{60};
|
|
||||||
const size_t kStage2JitterMax{120};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manage retries for metrics
|
|
||||||
*/
|
|
||||||
class MetricsRetryCounter : public RetryCounter {
|
|
||||||
public:
|
|
||||||
explicit MetricsRetryCounter(PseudoRandom& random) : _random(random) {}
|
|
||||||
|
|
||||||
void reset() final;
|
|
||||||
|
|
||||||
bool incrementError() final;
|
|
||||||
|
|
||||||
size_t getCount() const {
|
|
||||||
return _retryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Random number generator for jitter
|
|
||||||
PseudoRandom& _random;
|
|
||||||
|
|
||||||
// Retry count for stage 1 retry
|
|
||||||
size_t _retryCount{0};
|
|
||||||
|
|
||||||
// Total Seconds we have retried for
|
|
||||||
Seconds _total;
|
|
||||||
|
|
||||||
// Last retry interval without jitter
|
|
||||||
Seconds _base;
|
|
||||||
|
|
||||||
// Max Duration
|
|
||||||
const Hours kDurationMax{7 * 24};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple bounded buffer of metrics to upload.
|
|
||||||
*/
|
|
||||||
class MetricsBuffer {
|
|
||||||
public:
|
|
||||||
using container_type = std::deque<BSONObj>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a metric to the buffer. Oldest metric will be discarded if buffer is at capacity.
|
|
||||||
*/
|
|
||||||
void push(BSONObj obj) {
|
|
||||||
if (_queue.size() == kMaxElements) {
|
|
||||||
_queue.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
_queue.push_back(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush the buffer down to kMinElements entries. The last entries are held for cloud.
|
|
||||||
*/
|
|
||||||
void reset() {
|
|
||||||
while (_queue.size() > kMinElements) {
|
|
||||||
_queue.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
container_type::iterator begin() {
|
|
||||||
return _queue.begin();
|
|
||||||
}
|
|
||||||
container_type::iterator end() {
|
|
||||||
return _queue.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Bounded queue of metrics
|
|
||||||
container_type _queue;
|
|
||||||
|
|
||||||
const size_t kMinElements = 1;
|
|
||||||
const size_t kMaxElements = 10;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Countdown latch for test support in FreeMonProcessor so that a crank can be turned manually.
|
|
||||||
*/
|
|
||||||
class FreeMonCountdownLatch {
|
|
||||||
public:
|
|
||||||
explicit FreeMonCountdownLatch() : _count(0) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset countdown latch wait for N events.
|
|
||||||
*/
|
|
||||||
void reset(uint32_t count) {
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
dassert(_count == 0);
|
|
||||||
dassert(count > 0);
|
|
||||||
_count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Count down an event.
|
|
||||||
*/
|
|
||||||
void countDown() {
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
if (_count > 0) {
|
|
||||||
--_count;
|
|
||||||
if (_count == 0) {
|
|
||||||
_condvar.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the N events specified in reset have occured.
|
|
||||||
*/
|
|
||||||
void wait() {
|
|
||||||
stdx::unique_lock<Latch> lock(_mutex);
|
|
||||||
_condvar.wait(lock, [&] { return _count == 0; });
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// mutex to break count and cond var
|
|
||||||
Mutex _mutex = MONGO_MAKE_LATCH("FreeMonCountdownLatch::_mutex");
|
|
||||||
|
|
||||||
// cond var to signal and wait on
|
|
||||||
stdx::condition_variable _condvar;
|
|
||||||
|
|
||||||
// count of events to wait for
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* Messages are given to it by enqueue, and the Processor processes messages with run().
|
|
||||||
*/
|
|
||||||
class FreeMonProcessor : public std::enable_shared_from_this<FreeMonProcessor> {
|
|
||||||
public:
|
|
||||||
FreeMonProcessor(FreeMonCollectorCollection& registration,
|
|
||||||
FreeMonCollectorCollection& metrics,
|
|
||||||
FreeMonNetworkInterface* network,
|
|
||||||
bool useCrankForTest,
|
|
||||||
Seconds metricsGatherInterval);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueue a message to process
|
|
||||||
*/
|
|
||||||
void enqueue(std::shared_ptr<FreeMonMessage> msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop processing messages.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn the crank of the message queue by ignoring deadlines for N messages.
|
|
||||||
*/
|
|
||||||
void turnCrankForTest(size_t countMessagesToIgnore);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deproritize the first message to force interleavings of messages.
|
|
||||||
*/
|
|
||||||
void deprioritizeFirstMessageForTest(FreeMonMessageType type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes messages forever
|
|
||||||
*/
|
|
||||||
void run();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the registration response. Public for unit testing.
|
|
||||||
*/
|
|
||||||
static Status validateRegistrationResponse(const FreeMonRegistrationResponse& resp);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the metrics response. Public for unit testing.
|
|
||||||
*/
|
|
||||||
static Status validateMetricsResponse(const FreeMonMetricsResponse& resp);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Read the state from the database.
|
|
||||||
*
|
|
||||||
* Checks if the storage document has been delete locally or does not exist. If it is missing,
|
|
||||||
* generates a default disable state.
|
|
||||||
*
|
|
||||||
* If updateInMemory is true, update the state in memory with the state from disk. If false, do
|
|
||||||
* not update the state in memory from disk but instead treat the state in memory as
|
|
||||||
* authoritative. The is important for secondaries which may be in a different state for
|
|
||||||
* regsistration then there primary.
|
|
||||||
*/
|
|
||||||
void readState(OperationContext* opCtx, bool updateInMemory = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a short-lived opCtx and read the state from the database.
|
|
||||||
*/
|
|
||||||
void readState(Client* client, bool updateInMemory = true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the state to disk if there are any changes.
|
|
||||||
*/
|
|
||||||
void writeState(Client* client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a registration from a command.
|
|
||||||
*/
|
|
||||||
void doCommandRegister(Client* client, std::shared_ptr<FreeMonMessage> sharedMsg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a registration from configuration.
|
|
||||||
*/
|
|
||||||
void doServerRegister(Client* client,
|
|
||||||
const FreeMonMessageWithPayload<FreeMonMessageType::RegisterServer>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process unregistration from a command.
|
|
||||||
*/
|
|
||||||
void doCommandUnregister(
|
|
||||||
Client* client,
|
|
||||||
FreeMonWaitableMessageWithPayload<FreeMonMessageType::UnregisterCommand>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a successful HTTP request.
|
|
||||||
*/
|
|
||||||
void doAsyncRegisterComplete(
|
|
||||||
Client* client,
|
|
||||||
const FreeMonMessageWithPayload<FreeMonMessageType::AsyncRegisterComplete>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an unsuccessful HTTP request.
|
|
||||||
*/
|
|
||||||
void doAsyncRegisterFail(
|
|
||||||
Client* client,
|
|
||||||
const FreeMonMessageWithPayload<FreeMonMessageType::AsyncRegisterFail>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify any command registers that are waiting.
|
|
||||||
*/
|
|
||||||
void notifyPendingRegisters(const Status s);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload collected metrics.
|
|
||||||
*/
|
|
||||||
void doMetricsCollect(Client* client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload gathered metrics.
|
|
||||||
*/
|
|
||||||
void doMetricsSend(Client* client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a successful HTTP request.
|
|
||||||
*/
|
|
||||||
void doAsyncMetricsComplete(
|
|
||||||
Client* client,
|
|
||||||
const FreeMonMessageWithPayload<FreeMonMessageType::AsyncMetricsComplete>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process an unsuccessful HTTP request.
|
|
||||||
*/
|
|
||||||
void doAsyncMetricsFail(
|
|
||||||
Client* client, const FreeMonMessageWithPayload<FreeMonMessageType::AsyncMetricsFail>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a change to become a replica set primary
|
|
||||||
*/
|
|
||||||
void doOnTransitionToPrimary(Client* client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a notification that storage has received insert or update.
|
|
||||||
*/
|
|
||||||
void doNotifyOnUpsert(Client* client,
|
|
||||||
const FreeMonMessageWithPayload<FreeMonMessageType::NotifyOnUpsert>* msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a notification that storage has received delete or drop collection.
|
|
||||||
*/
|
|
||||||
void doNotifyOnDelete(Client* client);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a notification that storage has rolled back.
|
|
||||||
*/
|
|
||||||
void doNotifyOnRollback(Client* client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a in-memory state transition of state.
|
|
||||||
*/
|
|
||||||
void processInMemoryStateChange(const FreeMonStorageState& originalState,
|
|
||||||
const FreeMonStorageState& newState);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend class FreeMonController;
|
|
||||||
|
|
||||||
enum FreeMonGetStatusEnum {
|
|
||||||
kServerStatus,
|
|
||||||
kCommandStatus,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate results for getFreeMonitoringStatus or serverStatus commands.
|
|
||||||
*/
|
|
||||||
void getStatus(OperationContext* opCtx, BSONObjBuilder* status, FreeMonGetStatusEnum mode);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Collection of collectors to send on registration
|
|
||||||
FreeMonCollectorCollection& _registration;
|
|
||||||
|
|
||||||
// Collection of collectors to send on each metrics call
|
|
||||||
FreeMonCollectorCollection& _metrics;
|
|
||||||
|
|
||||||
// HTTP Network interface
|
|
||||||
FreeMonNetworkInterface* _network;
|
|
||||||
|
|
||||||
// Random number generator for retries
|
|
||||||
PseudoRandom _random;
|
|
||||||
|
|
||||||
// Registration Retry logic
|
|
||||||
synchronized_value<RegistrationRetryCounter> _registrationRetry;
|
|
||||||
|
|
||||||
// Metrics Retry logic
|
|
||||||
synchronized_value<MetricsRetryCounter> _metricsRetry;
|
|
||||||
|
|
||||||
// Interval for gathering metrics
|
|
||||||
Seconds _metricsGatherInterval;
|
|
||||||
|
|
||||||
// Buffer of metrics to upload
|
|
||||||
MetricsBuffer _metricsBuffer;
|
|
||||||
|
|
||||||
// When did we last send a metrics batch?
|
|
||||||
synchronized_value<boost::optional<Date_t>> _lastMetricsSend;
|
|
||||||
|
|
||||||
// List of tags from server configuration registration
|
|
||||||
std::vector<std::string> _tags;
|
|
||||||
|
|
||||||
// In-flight registration response
|
|
||||||
std::unique_ptr<Future<void>> _futureRegistrationResponse;
|
|
||||||
|
|
||||||
// List of command registers waiting to be told about registration
|
|
||||||
std::vector<std::shared_ptr<FreeMonMessage>> _pendingRegisters;
|
|
||||||
|
|
||||||
// Last read storage state
|
|
||||||
synchronized_value<boost::optional<FreeMonStorageState>> _lastReadState;
|
|
||||||
|
|
||||||
// When we change to primary, do we register?
|
|
||||||
RegistrationType _registerOnTransitionToPrimary{RegistrationType::DoNotRegister};
|
|
||||||
|
|
||||||
// Pending update to disk
|
|
||||||
synchronized_value<FreeMonStorageState> _state;
|
|
||||||
|
|
||||||
// In-memory registration status
|
|
||||||
FreeMonRegistrationStatus _registrationStatus{FreeMonRegistrationStatus::kDisabled};
|
|
||||||
|
|
||||||
// Countdown launch to support manual cranking
|
|
||||||
FreeMonCountdownLatch _countdown;
|
|
||||||
|
|
||||||
// Message queue
|
|
||||||
FreeMonMessageQueue _queue;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,149 +0,0 @@
|
||||||
# Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the Server Side Public License, version 1,
|
|
||||||
# as published by MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# Server Side Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the Server Side Public License
|
|
||||||
# along with this program. If not, see
|
|
||||||
# <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
#
|
|
||||||
# As a special exception, the copyright holders give permission to link the
|
|
||||||
# code of portions of this program with the OpenSSL library under certain
|
|
||||||
# conditions as described in each individual source file and distribute
|
|
||||||
# linked combinations including the program with the OpenSSL library. You
|
|
||||||
# must comply with the Server Side Public License in all respects for
|
|
||||||
# all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
# with this exception, you may extend this exception to your version of the
|
|
||||||
# file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
# delete this exception statement from your version. If you delete this
|
|
||||||
# exception statement from all source files in the program, then also delete
|
|
||||||
# it in the license file.
|
|
||||||
#
|
|
||||||
global:
|
|
||||||
cpp_namespace: "mongo"
|
|
||||||
|
|
||||||
imports:
|
|
||||||
- "mongo/idl/basic_types.idl"
|
|
||||||
|
|
||||||
|
|
||||||
enums:
|
|
||||||
MetricsEncoding:
|
|
||||||
description: "Metrics Encoding Methods"
|
|
||||||
type: string
|
|
||||||
values:
|
|
||||||
snappy: "snappy"
|
|
||||||
|
|
||||||
|
|
||||||
structs:
|
|
||||||
FreeMonRegistrationRequest:
|
|
||||||
description: "Registration Request to Cloud Server"
|
|
||||||
fields:
|
|
||||||
version:
|
|
||||||
description: "Protocol version, initial version is 1"
|
|
||||||
type: long
|
|
||||||
payload:
|
|
||||||
description: "Payload of registration information"
|
|
||||||
type: object
|
|
||||||
id:
|
|
||||||
description: "Existing Registration Id"
|
|
||||||
type: string
|
|
||||||
optional: true
|
|
||||||
localTime:
|
|
||||||
description: "Local time at registration send"
|
|
||||||
type: date
|
|
||||||
tags:
|
|
||||||
description: "Tags"
|
|
||||||
type: array<string>
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
FreeMonRegistrationResponse:
|
|
||||||
description: "Registration Response from Cloud Server"
|
|
||||||
fields:
|
|
||||||
version:
|
|
||||||
description: "Protocol version, initial version is 1"
|
|
||||||
type: long
|
|
||||||
haltMetricsUploading:
|
|
||||||
description: "True indicates it should not proceed to metrics uploading"
|
|
||||||
type: bool
|
|
||||||
id:
|
|
||||||
description: "Existing Registration Id"
|
|
||||||
type: string
|
|
||||||
informationalURL:
|
|
||||||
description: "Informational HTTP web page for metrics"
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: "Informational message for shell to display to user"
|
|
||||||
type: string
|
|
||||||
reportingInterval:
|
|
||||||
description: "Metrics Reporting interval in seconds"
|
|
||||||
type: long
|
|
||||||
userReminder:
|
|
||||||
description: "Informational message to display to user to remind them about the service"
|
|
||||||
type: string
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
|
|
||||||
FreeMonMetricsRequest:
|
|
||||||
description: "Metrics Request to Cloud Server"
|
|
||||||
fields:
|
|
||||||
version:
|
|
||||||
description: "Protocol version, initial version is 1"
|
|
||||||
type: long
|
|
||||||
id:
|
|
||||||
description: "Registration Id"
|
|
||||||
type: string
|
|
||||||
localTime:
|
|
||||||
description: "Local time at metrics send"
|
|
||||||
type: date
|
|
||||||
encoding:
|
|
||||||
description: "Compression Encoding"
|
|
||||||
type: MetricsEncoding
|
|
||||||
metrics:
|
|
||||||
description: "Metrics Blob"
|
|
||||||
type: bindata_generic
|
|
||||||
|
|
||||||
# History
|
|
||||||
# -------
|
|
||||||
# Version 2 - added resendRegistration bool
|
|
||||||
#
|
|
||||||
FreeMonMetricsResponse:
|
|
||||||
description: "Metrics Response from Cloud Server"
|
|
||||||
fields:
|
|
||||||
version:
|
|
||||||
description: "Protocol version, initial version is 1"
|
|
||||||
type: long
|
|
||||||
haltMetricsUploading:
|
|
||||||
description: "True indicates it should not proceed to metrics uploading"
|
|
||||||
type: bool
|
|
||||||
permanentlyDelete:
|
|
||||||
description: "True indicates it permanently delete the local state"
|
|
||||||
type: bool
|
|
||||||
reportingInterval:
|
|
||||||
description: "Metrics Reporting interval in seconds"
|
|
||||||
type: long
|
|
||||||
id:
|
|
||||||
description: "Existing Registration Id"
|
|
||||||
type: string
|
|
||||||
optional: true
|
|
||||||
message:
|
|
||||||
description: "Informational message for shell to display to user"
|
|
||||||
type: string
|
|
||||||
optional: true
|
|
||||||
informationalURL:
|
|
||||||
description: "Informational HTTP web page for metrics"
|
|
||||||
type: string
|
|
||||||
optional: true
|
|
||||||
userReminder:
|
|
||||||
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
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_queue.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include "mongo/util/concurrency/idle_thread_block.h"
|
|
||||||
#include "mongo/util/duration.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
std::shared_ptr<FreeMonMessage> FreeMonPriorityQueue::top() const {
|
|
||||||
return _vector.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonPriorityQueue::pop() {
|
|
||||||
std::pop_heap(_vector.begin(), _vector.end(), _comp);
|
|
||||||
_vector.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonPriorityQueue::push(std::shared_ptr<FreeMonMessage> item) {
|
|
||||||
_vector.push_back(item);
|
|
||||||
std::push_heap(_vector.begin(), _vector.end(), _comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonPriorityQueue::eraseByType(FreeMonMessageType type) {
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
auto it = std::find_if(_vector.begin(), _vector.end(), [type](const auto& item) {
|
|
||||||
return item->getType() == type;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (it == _vector.end()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
_vector.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::make_heap(_vector.begin(), _vector.end(), _comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FreeMonMessage::~FreeMonMessage() {}
|
|
||||||
|
|
||||||
void FreeMonMessageQueue::enqueue(std::shared_ptr<FreeMonMessage> msg) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
// If we were stopped, drop messages
|
|
||||||
if (_stop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
++_counter;
|
|
||||||
msg->setId(_counter);
|
|
||||||
|
|
||||||
if (msg->getType() == FreeMonMessageType::MetricsSend) {
|
|
||||||
_queue.eraseByType(FreeMonMessageType::MetricsSend);
|
|
||||||
}
|
|
||||||
|
|
||||||
_queue.push(msg);
|
|
||||||
|
|
||||||
// Signal the dequeue
|
|
||||||
_condvar.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonMessageQueue::deprioritizeFirstMessageForTest(FreeMonMessageType type) {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
auto item = _queue.top();
|
|
||||||
uassert(5167902, "Wrong message type", item->getType() == type);
|
|
||||||
|
|
||||||
_queue.pop();
|
|
||||||
|
|
||||||
++_counter;
|
|
||||||
item->setId(_counter);
|
|
||||||
_queue.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<std::shared_ptr<FreeMonMessage>> FreeMonMessageQueue::dequeue(
|
|
||||||
ClockSource* clockSource) {
|
|
||||||
{
|
|
||||||
stdx::unique_lock<Latch> lock(_mutex);
|
|
||||||
if (_stop) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
Date_t deadlineCV = Date_t::max();
|
|
||||||
if (_useCrank) {
|
|
||||||
if (!_queue.empty() && _countMessagesIgnored < _countMessagesToIgnore) {
|
|
||||||
// For testing purposes, ignore the deadline
|
|
||||||
deadlineCV = Date_t();
|
|
||||||
} else {
|
|
||||||
deadlineCV = clockSource->now() + Hours(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!_queue.empty()) {
|
|
||||||
deadlineCV = _queue.top()->getDeadline();
|
|
||||||
} else {
|
|
||||||
deadlineCV = clockSource->now() + Hours(24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MONGO_IDLE_THREAD_BLOCK;
|
|
||||||
|
|
||||||
_condvar.wait_until(lock, deadlineCV.toSystemTimePoint(), [this, clockSource]() {
|
|
||||||
if (_stop) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->_queue.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always wake in test mode
|
|
||||||
if (_useCrank) {
|
|
||||||
if (_countMessagesIgnored < _countMessagesToIgnore) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
dassert(_countMessagesIgnored == _countMessagesToIgnore);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto deadlineMessage = this->_queue.top()->getDeadline();
|
|
||||||
if (deadlineMessage <= Date_t()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto now = clockSource->now();
|
|
||||||
|
|
||||||
bool check = deadlineMessage < now;
|
|
||||||
return check;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (_stop) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// We were woken-up by a message being enqueue, go back to sleep and wait until crank is
|
|
||||||
// installed and turned.
|
|
||||||
if (_useCrank) {
|
|
||||||
if (_countMessagesIgnored == _countMessagesToIgnore) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dassert(_countMessagesIgnored <= _countMessagesToIgnore);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the queue is not empty, return the message
|
|
||||||
// otherwise we need to go back to sleep in the hope we get a message.
|
|
||||||
if (!_queue.empty()) {
|
|
||||||
break;
|
|
||||||
} else if (_useCrank) {
|
|
||||||
dassert(0, "Was asked to wait for more messages then available");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_countMessagesIgnored++;
|
|
||||||
if (_useCrank && _countMessagesIgnored == _countMessagesToIgnore && _waitable) {
|
|
||||||
_waitable->set(Status::OK());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto item = _queue.top();
|
|
||||||
_queue.pop();
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonMessageQueue::stop() {
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
// We can be stopped twice in some situations:
|
|
||||||
// 1. Stop on unexpected error
|
|
||||||
// 2. Stop on clean shutdown
|
|
||||||
if (_stop == false) {
|
|
||||||
_stop = true;
|
|
||||||
_condvar.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonMessageQueue::turnCrankForTest(size_t countMessagesToIgnore) {
|
|
||||||
invariant(_useCrank);
|
|
||||||
|
|
||||||
{
|
|
||||||
stdx::lock_guard<Latch> lock(_mutex);
|
|
||||||
|
|
||||||
_waitable = std::make_unique<WaitableResult>();
|
|
||||||
|
|
||||||
_countMessagesIgnored = 0;
|
|
||||||
_countMessagesToIgnore = countMessagesToIgnore;
|
|
||||||
|
|
||||||
_condvar.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
//_waitable->wait_for(Seconds(10));
|
|
||||||
}
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_message.h"
|
|
||||||
#include "mongo/util/clock_source.h"
|
|
||||||
#include "mongo/util/time_support.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comparator for FreeMonMessage that will sort smallest deadlines at the beginning of a priority
|
|
||||||
* queue. The std::priority_queue is a max-heap.
|
|
||||||
*/
|
|
||||||
struct FreeMonMessageGreater {
|
|
||||||
bool operator()(const std::shared_ptr<FreeMonMessage>& left,
|
|
||||||
const std::shared_ptr<FreeMonMessage>& right) const {
|
|
||||||
if (left->getDeadline() > right->getDeadline()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left->getDeadline() == right->getDeadline()) {
|
|
||||||
return left->getId() > right->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Priority Queue with ability to remove items by filter.
|
|
||||||
*/
|
|
||||||
class FreeMonPriorityQueue {
|
|
||||||
public:
|
|
||||||
bool empty() const {
|
|
||||||
return _vector.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the message at the top of the priority queue.
|
|
||||||
*/
|
|
||||||
std::shared_ptr<FreeMonMessage> top() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pop the message at the top of the priority queue.
|
|
||||||
*/
|
|
||||||
void pop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Push a message into the priority queue.
|
|
||||||
*/
|
|
||||||
void push(std::shared_ptr<FreeMonMessage> item);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Erase messages of a given type from the queue.
|
|
||||||
*/
|
|
||||||
void eraseByType(FreeMonMessageType type);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Using shared_ptr because std::pop_heap does not support move-only types
|
|
||||||
std::vector<std::shared_ptr<FreeMonMessage>> _vector;
|
|
||||||
FreeMonMessageGreater _comp;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A multi-producer, single-consumer queue with deadlines.
|
|
||||||
*
|
|
||||||
* The smallest deadline sorts first. Messages with deadlines can be use as a timer mechanism.
|
|
||||||
*/
|
|
||||||
class FreeMonMessageQueue {
|
|
||||||
public:
|
|
||||||
FreeMonMessageQueue(bool useCrankForTest = false) : _useCrank(useCrankForTest) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueue a message and wake consumer if needed.
|
|
||||||
*
|
|
||||||
* Messages are dropped if the queue has been stopped.
|
|
||||||
*/
|
|
||||||
void enqueue(std::shared_ptr<FreeMonMessage> msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deque a message from the queue.
|
|
||||||
*
|
|
||||||
* Waits for a message to arrive. Returns boost::none if the queue has been stopped.
|
|
||||||
*/
|
|
||||||
boost::optional<std::shared_ptr<FreeMonMessage>> dequeue(ClockSource* clockSource);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the queue.
|
|
||||||
*/
|
|
||||||
void stop();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turn the crank of the message queue by ignoring deadlines for N messages.
|
|
||||||
*/
|
|
||||||
void turnCrankForTest(size_t countMessagesToIgnore);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deproritize the first message to force interleavings of messages.
|
|
||||||
*/
|
|
||||||
void deprioritizeFirstMessageForTest(FreeMonMessageType type);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Condition variable to signal consumer
|
|
||||||
stdx::condition_variable _condvar;
|
|
||||||
|
|
||||||
// Lock for condition variable and to protect state
|
|
||||||
Mutex _mutex = MONGO_MAKE_LATCH("FreeMonMessageQueue::_mutex");
|
|
||||||
|
|
||||||
// Indicates whether queue has been stopped.
|
|
||||||
bool _stop{false};
|
|
||||||
|
|
||||||
// Priority queue of messages with shortest deadline first
|
|
||||||
FreeMonPriorityQueue _queue;
|
|
||||||
|
|
||||||
// Use manual crank to process messages in-order instead of based on deadlines.
|
|
||||||
bool _useCrank{false};
|
|
||||||
|
|
||||||
// Stamp each message with a unique counter. This ensures that if two messages are queued with
|
|
||||||
// the same deadline, FIFO is achieved.
|
|
||||||
uint64_t _counter{0};
|
|
||||||
|
|
||||||
// Number of messages to ignore
|
|
||||||
size_t _countMessagesToIgnore{0};
|
|
||||||
|
|
||||||
// Number of messages that have been ignored
|
|
||||||
size_t _countMessagesIgnored{0};
|
|
||||||
|
|
||||||
// Waitable result for testing
|
|
||||||
std::unique_ptr<WaitableResult> _waitable;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,169 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_message.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_queue.h"
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
#include "mongo/db/service_context_d_test_fixture.h"
|
|
||||||
#include "mongo/executor/network_interface_mock.h"
|
|
||||||
#include "mongo/executor/thread_pool_task_executor.h"
|
|
||||||
#include "mongo/executor/thread_pool_task_executor_test_fixture.h"
|
|
||||||
#include "mongo/unittest/barrier.h"
|
|
||||||
#include "mongo/unittest/unittest.h"
|
|
||||||
#include "mongo/util/time_support.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class FreeMonQueueTest : public ServiceContextMongoDTest {
|
|
||||||
private:
|
|
||||||
void setUp() final;
|
|
||||||
void tearDown() final;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ServiceContext::UniqueOperationContext _opCtx;
|
|
||||||
|
|
||||||
executor::NetworkInterfaceMock* _mockNetwork{nullptr};
|
|
||||||
|
|
||||||
std::unique_ptr<executor::ThreadPoolTaskExecutor> _mockThreadPool;
|
|
||||||
};
|
|
||||||
|
|
||||||
void FreeMonQueueTest::setUp() {
|
|
||||||
ServiceContextMongoDTest::setUp();
|
|
||||||
|
|
||||||
// Set up a NetworkInterfaceMock. Note, unlike NetworkInterfaceASIO, which has its own pool of
|
|
||||||
// threads, tasks in the NetworkInterfaceMock must be carried out synchronously by the (single)
|
|
||||||
// thread the unit test is running on.
|
|
||||||
auto netForFixedTaskExecutor = std::make_unique<executor::NetworkInterfaceMock>();
|
|
||||||
_mockNetwork = netForFixedTaskExecutor.get();
|
|
||||||
|
|
||||||
// Set up a ThreadPoolTaskExecutor. Note, for local tasks this TaskExecutor uses a
|
|
||||||
// ThreadPoolMock, and for remote tasks it uses the NetworkInterfaceMock created above. However,
|
|
||||||
// note that the ThreadPoolMock uses the NetworkInterfaceMock's threads to run tasks, which is
|
|
||||||
// again just the (single) thread the unit test is running on. Therefore, all tasks, local and
|
|
||||||
// remote, must be carried out synchronously by the test thread.
|
|
||||||
_mockThreadPool = makeThreadPoolTestExecutor(std::move(netForFixedTaskExecutor));
|
|
||||||
|
|
||||||
_mockThreadPool->startup();
|
|
||||||
|
|
||||||
_opCtx = cc().makeOperationContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonQueueTest::tearDown() {
|
|
||||||
_opCtx = {};
|
|
||||||
|
|
||||||
ServiceContextMongoDTest::tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Postive: Can we enqueue and dequeue one item
|
|
||||||
TEST_F(FreeMonQueueTest, TestBasic) {
|
|
||||||
FreeMonMessageQueue queue;
|
|
||||||
|
|
||||||
queue.enqueue(FreeMonMessage::createNow(FreeMonMessageType::RegisterServer));
|
|
||||||
|
|
||||||
auto item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource());
|
|
||||||
|
|
||||||
ASSERT(item.get()->getType() == FreeMonMessageType::RegisterServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Date_t fromNow(int millis) {
|
|
||||||
return getGlobalServiceContext()->getPreciseClockSource()->now() + Milliseconds(millis);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Positive: Ensure deadlines sort properly
|
|
||||||
TEST_F(FreeMonQueueTest, TestDeadlinePriority) {
|
|
||||||
FreeMonMessageQueue queue;
|
|
||||||
|
|
||||||
queue.enqueue(
|
|
||||||
FreeMonMessage::createWithDeadline(FreeMonMessageType::RegisterServer, fromNow(5000)));
|
|
||||||
queue.enqueue(
|
|
||||||
FreeMonMessage::createWithDeadline(FreeMonMessageType::RegisterCommand, fromNow(50)));
|
|
||||||
|
|
||||||
auto item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).get();
|
|
||||||
ASSERT(item->getType() == FreeMonMessageType::RegisterCommand);
|
|
||||||
|
|
||||||
item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).get();
|
|
||||||
ASSERT(item->getType() == FreeMonMessageType::RegisterServer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Positive: Ensure deadlines sort properly when they have the same deadlines
|
|
||||||
TEST_F(FreeMonQueueTest, TestFIFO) {
|
|
||||||
FreeMonMessageQueue queue;
|
|
||||||
|
|
||||||
queue.enqueue(FreeMonMessage::createWithDeadline(FreeMonMessageType::RegisterServer, Date_t()));
|
|
||||||
queue.enqueue(
|
|
||||||
FreeMonMessage::createWithDeadline(FreeMonMessageType::AsyncRegisterComplete, Date_t()));
|
|
||||||
queue.enqueue(
|
|
||||||
FreeMonMessage::createWithDeadline(FreeMonMessageType::RegisterCommand, Date_t()));
|
|
||||||
|
|
||||||
auto item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).get();
|
|
||||||
ASSERT(item->getType() == FreeMonMessageType::RegisterServer);
|
|
||||||
|
|
||||||
item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).get();
|
|
||||||
ASSERT(item->getType() == FreeMonMessageType::AsyncRegisterComplete);
|
|
||||||
|
|
||||||
item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).get();
|
|
||||||
ASSERT(item->getType() == FreeMonMessageType::RegisterCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Positive: Test Queue Stop
|
|
||||||
TEST_F(FreeMonQueueTest, TestQueueStop) {
|
|
||||||
FreeMonMessageQueue queue;
|
|
||||||
|
|
||||||
queue.enqueue(
|
|
||||||
FreeMonMessage::createWithDeadline(FreeMonMessageType::RegisterServer, fromNow(50000)));
|
|
||||||
|
|
||||||
unittest::Barrier barrier(2);
|
|
||||||
|
|
||||||
auto swSchedule =
|
|
||||||
_mockThreadPool->scheduleWork([&](const executor::TaskExecutor::CallbackArgs& cbArgs) {
|
|
||||||
barrier.countDownAndWait();
|
|
||||||
|
|
||||||
// Try to dequeue from a stopped task queue
|
|
||||||
auto item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource());
|
|
||||||
ASSERT_FALSE(item.is_initialized());
|
|
||||||
});
|
|
||||||
|
|
||||||
ASSERT_OK(swSchedule.getStatus());
|
|
||||||
|
|
||||||
// Stop the queue
|
|
||||||
queue.stop();
|
|
||||||
|
|
||||||
// Let our worker thread proceed
|
|
||||||
barrier.countDownAndWait();
|
|
||||||
|
|
||||||
_mockThreadPool->shutdown();
|
|
||||||
_mockThreadPool->join();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/commands/server_status.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_controller.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_options.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class FreeMonServerStatus : public ServerStatusSection {
|
|
||||||
public:
|
|
||||||
FreeMonServerStatus() : ServerStatusSection("freeMonitoring") {}
|
|
||||||
|
|
||||||
bool includeByDefault() const final {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addRequiredPrivileges(std::vector<Privilege>* out) final {
|
|
||||||
out->push_back(Privilege(ResourcePattern::forClusterResource(),
|
|
||||||
ActionType::checkFreeMonitoringStatus));
|
|
||||||
}
|
|
||||||
|
|
||||||
BSONObj generateSection(OperationContext* opCtx, const BSONElement& configElement) const final {
|
|
||||||
if (globalFreeMonParams.freeMonitoringState == EnableCloudStateEnum::kOff) {
|
|
||||||
return BSON("state"
|
|
||||||
<< "disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* controller = FreeMonController::get(opCtx->getServiceContext());
|
|
||||||
if (!controller) {
|
|
||||||
return BSON("state"
|
|
||||||
<< "disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
BSONObjBuilder builder;
|
|
||||||
controller->getServerStatus(opCtx, &builder);
|
|
||||||
return builder.obj();
|
|
||||||
}
|
|
||||||
} freeMonServerStatus;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage.h"
|
|
||||||
|
|
||||||
#include "mongo/base/status.h"
|
|
||||||
#include "mongo/base/string_data.h"
|
|
||||||
#include "mongo/bson/bsonelement.h"
|
|
||||||
#include "mongo/bson/bsonmisc.h"
|
|
||||||
#include "mongo/db/db_raii.h"
|
|
||||||
#include "mongo/db/namespace_string.h"
|
|
||||||
#include "mongo/db/operation_context.h"
|
|
||||||
#include "mongo/db/repl/replication_coordinator.h"
|
|
||||||
#include "mongo/db/repl/storage_interface.h"
|
|
||||||
#include "mongo/util/assert_util.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// mms-automation stores its document in local.clustermanager
|
|
||||||
static const NamespaceString localClusterManagerNss("local.clustermanager");
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
constexpr StringData FreeMonStorage::kFreeMonDocIdKey;
|
|
||||||
|
|
||||||
boost::optional<FreeMonStorageState> FreeMonStorage::read(OperationContext* opCtx) {
|
|
||||||
BSONObj deleteKey = BSON("_id" << kFreeMonDocIdKey);
|
|
||||||
BSONElement elementKey = deleteKey.firstElement();
|
|
||||||
|
|
||||||
auto storageInterface = repl::StorageInterface::get(opCtx);
|
|
||||||
|
|
||||||
// Ensure we read without a timestamp.
|
|
||||||
invariant(RecoveryUnit::ReadSource::kNoTimestamp ==
|
|
||||||
opCtx->recoveryUnit()->getTimestampReadSource());
|
|
||||||
|
|
||||||
AutoGetCollectionForRead autoRead(opCtx, NamespaceString::kServerConfigurationNamespace);
|
|
||||||
|
|
||||||
auto swObj = storageInterface->findById(
|
|
||||||
opCtx, NamespaceString::kServerConfigurationNamespace, elementKey);
|
|
||||||
if (!swObj.isOK()) {
|
|
||||||
if (swObj.getStatus() == ErrorCodes::NoSuchKey ||
|
|
||||||
swObj.getStatus() == ErrorCodes::NamespaceNotFound) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
uassertStatusOK(swObj.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
return FreeMonStorageState::parse(IDLParserErrorContext("FreeMonStorage"), swObj.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonStorage::replace(OperationContext* opCtx, const FreeMonStorageState& doc) {
|
|
||||||
BSONObj deleteKey = BSON("_id" << kFreeMonDocIdKey);
|
|
||||||
BSONElement elementKey = deleteKey.firstElement();
|
|
||||||
|
|
||||||
BSONObj obj = doc.toBSON();
|
|
||||||
|
|
||||||
auto storageInterface = repl::StorageInterface::get(opCtx);
|
|
||||||
AutoGetCollection autoWrite(opCtx, NamespaceString::kServerConfigurationNamespace, MODE_IX);
|
|
||||||
|
|
||||||
if (repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(
|
|
||||||
opCtx, NamespaceString::kServerConfigurationNamespace)) {
|
|
||||||
auto swObj = storageInterface->upsertById(
|
|
||||||
opCtx, NamespaceString::kServerConfigurationNamespace, elementKey, obj);
|
|
||||||
if (!swObj.isOK()) {
|
|
||||||
uassertStatusOK(swObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonStorage::deleteState(OperationContext* opCtx) {
|
|
||||||
BSONObj deleteKey = BSON("_id" << kFreeMonDocIdKey);
|
|
||||||
BSONElement elementKey = deleteKey.firstElement();
|
|
||||||
|
|
||||||
auto storageInterface = repl::StorageInterface::get(opCtx);
|
|
||||||
AutoGetCollection autoWrite(opCtx, NamespaceString::kServerConfigurationNamespace, MODE_IX);
|
|
||||||
|
|
||||||
if (repl::ReplicationCoordinator::get(opCtx)->canAcceptWritesFor(
|
|
||||||
opCtx, NamespaceString::kServerConfigurationNamespace)) {
|
|
||||||
|
|
||||||
auto swObj = storageInterface->deleteById(
|
|
||||||
opCtx, NamespaceString::kServerConfigurationNamespace, elementKey);
|
|
||||||
if (!swObj.isOK()) {
|
|
||||||
// Ignore errors about no document
|
|
||||||
if (swObj.getStatus() == ErrorCodes::NoSuchKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uassertStatusOK(swObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<BSONObj> FreeMonStorage::readClusterManagerState(OperationContext* opCtx) {
|
|
||||||
auto storageInterface = repl::StorageInterface::get(opCtx);
|
|
||||||
|
|
||||||
AutoGetCollectionForRead autoRead(opCtx, NamespaceString::kServerConfigurationNamespace);
|
|
||||||
|
|
||||||
auto swObj = storageInterface->findSingleton(opCtx, localClusterManagerNss);
|
|
||||||
if (!swObj.isOK()) {
|
|
||||||
// Ignore errors about not-finding documents or having too many documents
|
|
||||||
if (swObj.getStatus() == ErrorCodes::NamespaceNotFound ||
|
|
||||||
swObj.getStatus() == ErrorCodes::CollectionIsEmpty ||
|
|
||||||
swObj.getStatus() == ErrorCodes::TooManyMatchingDocuments) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
uassertStatusOK(swObj.getStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
return swObj.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include "mongo/bson/bsonobj.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage_gen.h"
|
|
||||||
#include "mongo/db/operation_context.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Storage tier for Free Monitoring. Provides access to storage engine.
|
|
||||||
*/
|
|
||||||
class FreeMonStorage {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* The _id value in admin.system.version.
|
|
||||||
*/
|
|
||||||
static constexpr auto kFreeMonDocIdKey = "free_monitoring"_sd;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads document from disk if it exists.
|
|
||||||
*/
|
|
||||||
static boost::optional<FreeMonStorageState> read(OperationContext* opCtx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces document on disk with contents of document. Creates document if it does not exist.
|
|
||||||
*/
|
|
||||||
static void replace(OperationContext* opCtx, const FreeMonStorageState& doc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes document on disk if it exists.
|
|
||||||
*/
|
|
||||||
static void deleteState(OperationContext* opCtx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the singelton document from local.clustermanager.
|
|
||||||
*
|
|
||||||
* Returns nothing if there are more then one document or it does not exist.
|
|
||||||
*/
|
|
||||||
static boost::optional<BSONObj> readClusterManagerState(OperationContext* opCtx);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
# Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the Server Side Public License, version 1,
|
|
||||||
# as published by MongoDB, Inc.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# Server Side Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the Server Side Public License
|
|
||||||
# along with this program. If not, see
|
|
||||||
# <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
#
|
|
||||||
# As a special exception, the copyright holders give permission to link the
|
|
||||||
# code of portions of this program with the OpenSSL library under certain
|
|
||||||
# conditions as described in each individual source file and distribute
|
|
||||||
# linked combinations including the program with the OpenSSL library. You
|
|
||||||
# must comply with the Server Side Public License in all respects for
|
|
||||||
# all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
# with this exception, you may extend this exception to your version of the
|
|
||||||
# file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
# delete this exception statement from your version. If you delete this
|
|
||||||
# exception statement from all source files in the program, then also delete
|
|
||||||
# it in the license file.
|
|
||||||
#
|
|
||||||
global:
|
|
||||||
cpp_namespace: "mongo"
|
|
||||||
|
|
||||||
imports:
|
|
||||||
- "mongo/idl/basic_types.idl"
|
|
||||||
|
|
||||||
enums:
|
|
||||||
StorageState:
|
|
||||||
description: "Action types"
|
|
||||||
type: string
|
|
||||||
values:
|
|
||||||
disabled: disabled
|
|
||||||
enabled: enabled
|
|
||||||
pending: pending
|
|
||||||
|
|
||||||
structs:
|
|
||||||
FreeMonStorageState:
|
|
||||||
description: "Persisted document in admin.system.version"
|
|
||||||
strict: false
|
|
||||||
generate_comparison_operators: true
|
|
||||||
fields:
|
|
||||||
_id:
|
|
||||||
description: "Key of the Free Monitoring singleton document"
|
|
||||||
type: "string"
|
|
||||||
default: '"free_monitoring"'
|
|
||||||
version:
|
|
||||||
description: "Storage version, initial version is 1"
|
|
||||||
type: long
|
|
||||||
state:
|
|
||||||
description: "Indicates whether it is disabled or enabled"
|
|
||||||
type: StorageState
|
|
||||||
default: disabled
|
|
||||||
registrationId:
|
|
||||||
description: "Registration Id"
|
|
||||||
type: string
|
|
||||||
informationalURL:
|
|
||||||
description: "Informational HTTP web page for metrics"
|
|
||||||
type: string
|
|
||||||
message:
|
|
||||||
description: "Informational message for shell to display to user"
|
|
||||||
type: string
|
|
||||||
userReminder:
|
|
||||||
description: "Message to display to user to remind them about service"
|
|
||||||
type: string
|
|
||||||
|
|
||||||
|
|
@ -1,272 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/base/string_data.h"
|
|
||||||
#include "mongo/bson/bsonelement.h"
|
|
||||||
#include "mongo/bson/bsonmisc.h"
|
|
||||||
#include "mongo/db/catalog/collection_options.h"
|
|
||||||
#include "mongo/db/concurrency/d_concurrency.h"
|
|
||||||
#include "mongo/db/concurrency/lock_manager_defs.h"
|
|
||||||
#include "mongo/db/free_mon/free_mon_storage.h"
|
|
||||||
#include "mongo/db/namespace_string.h"
|
|
||||||
#include "mongo/db/repl/replication_coordinator_mock.h"
|
|
||||||
#include "mongo/db/repl/storage_interface.h"
|
|
||||||
#include "mongo/db/repl/storage_interface_impl.h"
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
#include "mongo/db/service_context_d_test_fixture.h"
|
|
||||||
#include "mongo/executor/network_interface_mock.h"
|
|
||||||
#include "mongo/executor/thread_pool_task_executor.h"
|
|
||||||
#include "mongo/executor/thread_pool_task_executor_test_fixture.h"
|
|
||||||
#include "mongo/unittest/unittest.h"
|
|
||||||
#include "mongo/util/uuid.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class FreeMonStorageTest : public ServiceContextMongoDTest {
|
|
||||||
private:
|
|
||||||
void setUp() final;
|
|
||||||
void tearDown() final;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Looks up the current ReplicationCoordinator.
|
|
||||||
* The result is cast to a ReplicationCoordinatorMock to provide access to test features.
|
|
||||||
*/
|
|
||||||
repl::ReplicationCoordinatorMock* _getReplCoord() const;
|
|
||||||
|
|
||||||
ServiceContext::UniqueOperationContext _opCtx;
|
|
||||||
|
|
||||||
executor::NetworkInterfaceMock* _mockNetwork{nullptr};
|
|
||||||
|
|
||||||
std::unique_ptr<executor::ThreadPoolTaskExecutor> _mockThreadPool;
|
|
||||||
|
|
||||||
repl::StorageInterface* _storage{nullptr};
|
|
||||||
};
|
|
||||||
|
|
||||||
void FreeMonStorageTest::setUp() {
|
|
||||||
ServiceContextMongoDTest::setUp();
|
|
||||||
auto service = getServiceContext();
|
|
||||||
|
|
||||||
repl::ReplicationCoordinator::set(service,
|
|
||||||
std::make_unique<repl::ReplicationCoordinatorMock>(service));
|
|
||||||
|
|
||||||
_opCtx = cc().makeOperationContext();
|
|
||||||
|
|
||||||
repl::StorageInterface::set(service, std::make_unique<repl::StorageInterfaceImpl>());
|
|
||||||
_storage = repl::StorageInterface::get(service);
|
|
||||||
|
|
||||||
// Transition to PRIMARY so that the server can accept writes.
|
|
||||||
ASSERT_OK(_getReplCoord()->setFollowerMode(repl::MemberState::RS_PRIMARY));
|
|
||||||
|
|
||||||
repl::createOplog(_opCtx.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeMonStorageTest::tearDown() {
|
|
||||||
_opCtx = {};
|
|
||||||
ServiceContextMongoDTest::tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
repl::ReplicationCoordinatorMock* FreeMonStorageTest::_getReplCoord() const {
|
|
||||||
auto replCoord = repl::ReplicationCoordinator::get(_opCtx.get());
|
|
||||||
ASSERT(replCoord) << "No ReplicationCoordinator installed";
|
|
||||||
auto replCoordMock = dynamic_cast<repl::ReplicationCoordinatorMock*>(replCoord);
|
|
||||||
ASSERT(replCoordMock) << "Unexpected type for installed ReplicationCoordinator";
|
|
||||||
return replCoordMock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Positive: Test Storage works
|
|
||||||
TEST_F(FreeMonStorageTest, TestStorage) {
|
|
||||||
|
|
||||||
// Validate no collection works
|
|
||||||
{
|
|
||||||
auto emptyDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
ASSERT_FALSE(emptyDoc.is_initialized());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create collection with one document.
|
|
||||||
CollectionOptions collectionOptions;
|
|
||||||
collectionOptions.uuid = UUID::gen();
|
|
||||||
auto statusCC = _storage->createCollection(
|
|
||||||
_opCtx.get(), NamespaceString("admin", "system.version"), collectionOptions);
|
|
||||||
ASSERT_OK(statusCC);
|
|
||||||
|
|
||||||
|
|
||||||
FreeMonStorageState initialState =
|
|
||||||
FreeMonStorageState::parse(IDLParserErrorContext("foo"),
|
|
||||||
BSON("version" << 1LL << "state"
|
|
||||||
<< "enabled"
|
|
||||||
<< "registrationId"
|
|
||||||
<< "1234"
|
|
||||||
<< "informationalURL"
|
|
||||||
<< "http://example.com"
|
|
||||||
<< "message"
|
|
||||||
<< "hello"
|
|
||||||
<< "userReminder"
|
|
||||||
<< ""));
|
|
||||||
|
|
||||||
{
|
|
||||||
auto emptyDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
ASSERT_FALSE(emptyDoc.is_initialized());
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeMonStorage::replace(_opCtx.get(), initialState);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
|
|
||||||
ASSERT_TRUE(persistedDoc.is_initialized());
|
|
||||||
|
|
||||||
ASSERT_TRUE(persistedDoc == initialState);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeMonStorage::deleteState(_opCtx.get());
|
|
||||||
|
|
||||||
{
|
|
||||||
auto emptyDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
ASSERT_FALSE(emptyDoc.is_initialized());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verfiy delete of nothing succeeds
|
|
||||||
FreeMonStorage::deleteState(_opCtx.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Positive: Test Storage works on a secondary
|
|
||||||
TEST_F(FreeMonStorageTest, TestSecondary) {
|
|
||||||
|
|
||||||
// Create collection with one document.
|
|
||||||
CollectionOptions collectionOptions;
|
|
||||||
collectionOptions.uuid = UUID::gen();
|
|
||||||
auto statusCC = _storage->createCollection(
|
|
||||||
_opCtx.get(), NamespaceString("admin", "system.version"), collectionOptions);
|
|
||||||
ASSERT_OK(statusCC);
|
|
||||||
|
|
||||||
|
|
||||||
FreeMonStorageState initialState =
|
|
||||||
FreeMonStorageState::parse(IDLParserErrorContext("foo"),
|
|
||||||
BSON("version" << 1LL << "state"
|
|
||||||
<< "enabled"
|
|
||||||
<< "registrationId"
|
|
||||||
<< "1234"
|
|
||||||
<< "informationalURL"
|
|
||||||
<< "http://example.com"
|
|
||||||
<< "message"
|
|
||||||
<< "hello"
|
|
||||||
<< "userReminder"
|
|
||||||
<< ""));
|
|
||||||
|
|
||||||
FreeMonStorage::replace(_opCtx.get(), initialState);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
|
|
||||||
ASSERT_TRUE(persistedDoc.is_initialized());
|
|
||||||
|
|
||||||
ASSERT_TRUE(persistedDoc == initialState);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now become a secondary
|
|
||||||
ASSERT_OK(_getReplCoord()->setFollowerMode(repl::MemberState::RS_SECONDARY));
|
|
||||||
|
|
||||||
FreeMonStorageState updatedState =
|
|
||||||
FreeMonStorageState::parse(IDLParserErrorContext("foo"),
|
|
||||||
BSON("version" << 2LL << "state"
|
|
||||||
<< "enabled"
|
|
||||||
<< "registrationId"
|
|
||||||
<< "1234"
|
|
||||||
<< "informationalURL"
|
|
||||||
<< "http://example.com"
|
|
||||||
<< "message"
|
|
||||||
<< "hello"
|
|
||||||
<< "userReminder"
|
|
||||||
<< ""));
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
|
|
||||||
ASSERT_TRUE(persistedDoc.is_initialized());
|
|
||||||
|
|
||||||
ASSERT_TRUE(persistedDoc == initialState);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeMonStorage::deleteState(_opCtx.get());
|
|
||||||
|
|
||||||
{
|
|
||||||
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
|
|
||||||
ASSERT_TRUE(persistedDoc.is_initialized());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verfiy delete of nothing succeeds
|
|
||||||
FreeMonStorage::deleteState(_opCtx.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void insertDoc(OperationContext* optCtx, const NamespaceString nss, StringData id) {
|
|
||||||
auto storageInterface = repl::StorageInterface::get(optCtx);
|
|
||||||
|
|
||||||
Lock::DBLock dblk(optCtx, nss.db(), MODE_IS);
|
|
||||||
Lock::CollectionLock lk(optCtx, nss, MODE_IS);
|
|
||||||
|
|
||||||
BSONObj fakeDoc = BSON("_id" << id);
|
|
||||||
BSONElement elementKey = fakeDoc.firstElement();
|
|
||||||
|
|
||||||
ASSERT_OK(storageInterface->upsertById(optCtx, nss, elementKey, fakeDoc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Positive: Test local.clustermanager
|
|
||||||
TEST_F(FreeMonStorageTest, TestClusterManagerStorage) {
|
|
||||||
const NamespaceString localClusterManagerNss("local.clustermanager");
|
|
||||||
|
|
||||||
// Verify read of non-existent collection works
|
|
||||||
ASSERT_FALSE(FreeMonStorage::readClusterManagerState(_opCtx.get()).is_initialized());
|
|
||||||
|
|
||||||
CollectionOptions collectionOptions;
|
|
||||||
collectionOptions.uuid = UUID::gen();
|
|
||||||
auto statusCC =
|
|
||||||
_storage->createCollection(_opCtx.get(), localClusterManagerNss, collectionOptions);
|
|
||||||
ASSERT_OK(statusCC);
|
|
||||||
|
|
||||||
// Verify read of empty collection works
|
|
||||||
ASSERT_FALSE(FreeMonStorage::readClusterManagerState(_opCtx.get()).is_initialized());
|
|
||||||
|
|
||||||
insertDoc(_opCtx.get(), localClusterManagerNss, "foo1");
|
|
||||||
|
|
||||||
// Verify read of singleton collection works
|
|
||||||
ASSERT_TRUE(FreeMonStorage::readClusterManagerState(_opCtx.get()).is_initialized());
|
|
||||||
|
|
||||||
insertDoc(_opCtx.get(), localClusterManagerNss, "bar1");
|
|
||||||
|
|
||||||
// Verify read of two doc collection fails
|
|
||||||
ASSERT_FALSE(FreeMonStorage::readClusterManagerState(_opCtx.get()).is_initialized());
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/db/free_mon/free_mon_mongod.h"
|
|
||||||
|
|
||||||
#include "mongo/db/service_context.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
|
|
||||||
void startFreeMonitoring(ServiceContext* serviceContext) {}
|
|
||||||
|
|
||||||
void stopFreeMonitoring() {}
|
|
||||||
|
|
||||||
void notifyFreeMonitoringOnTransitionToPrimary(){};
|
|
||||||
|
|
||||||
void setupFreeMonitoringOpObserver(OpObserverRegistry* registry) {}
|
|
||||||
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -79,7 +79,6 @@
|
||||||
#include "mongo/db/dbmessage.h"
|
#include "mongo/db/dbmessage.h"
|
||||||
#include "mongo/db/exec/working_set_common.h"
|
#include "mongo/db/exec/working_set_common.h"
|
||||||
#include "mongo/db/fcv_op_observer.h"
|
#include "mongo/db/fcv_op_observer.h"
|
||||||
#include "mongo/db/free_mon/free_mon_mongod.h"
|
|
||||||
#include "mongo/db/ftdc/ftdc_mongod.h"
|
#include "mongo/db/ftdc/ftdc_mongod.h"
|
||||||
#include "mongo/db/ftdc/util.h"
|
#include "mongo/db/ftdc/util.h"
|
||||||
#include "mongo/db/global_settings.h"
|
#include "mongo/db/global_settings.h"
|
||||||
|
|
@ -652,8 +651,6 @@ ExitCode _initAndListen(ServiceContext* serviceContext, int listenPort) {
|
||||||
logStartup(startupOpCtx.get());
|
logStartup(startupOpCtx.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
startFreeMonitoring(serviceContext);
|
|
||||||
|
|
||||||
auto replCoord = repl::ReplicationCoordinator::get(startupOpCtx.get());
|
auto replCoord = repl::ReplicationCoordinator::get(startupOpCtx.get());
|
||||||
invariant(replCoord);
|
invariant(replCoord);
|
||||||
|
|
||||||
|
|
@ -1064,8 +1061,6 @@ void setUpObservers(ServiceContext* serviceContext) {
|
||||||
std::make_unique<repl::PrimaryOnlyServiceOpObserver>(serviceContext));
|
std::make_unique<repl::PrimaryOnlyServiceOpObserver>(serviceContext));
|
||||||
opObserverRegistry->addObserver(std::make_unique<FcvOpObserver>());
|
opObserverRegistry->addObserver(std::make_unique<FcvOpObserver>());
|
||||||
|
|
||||||
setupFreeMonitoringOpObserver(opObserverRegistry.get());
|
|
||||||
|
|
||||||
if (audit::opObserverRegistrar) {
|
if (audit::opObserverRegistrar) {
|
||||||
audit::opObserverRegistrar(opObserverRegistry.get());
|
audit::opObserverRegistrar(opObserverRegistry.get());
|
||||||
}
|
}
|
||||||
|
|
@ -1357,9 +1352,6 @@ void shutdownTask(const ShutdownTaskArgs& shutdownArgs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGV2(4784925, "Shutting down free monitoring");
|
|
||||||
stopFreeMonitoring();
|
|
||||||
|
|
||||||
LOGV2(4784927, "Shutting down the HealthLog");
|
LOGV2(4784927, "Shutting down the HealthLog");
|
||||||
HealthLog::get(serviceContext).shutdown();
|
HealthLog::get(serviceContext).shutdown();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1425,7 +1425,6 @@ env.Library(
|
||||||
'$BUILD_DIR/mongo/db/cloner',
|
'$BUILD_DIR/mongo/db/cloner',
|
||||||
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
|
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
|
||||||
'$BUILD_DIR/mongo/db/curop',
|
'$BUILD_DIR/mongo/db/curop',
|
||||||
'$BUILD_DIR/mongo/db/free_mon/free_mon_mongod',
|
|
||||||
'$BUILD_DIR/mongo/db/kill_sessions_local',
|
'$BUILD_DIR/mongo/db/kill_sessions_local',
|
||||||
'$BUILD_DIR/mongo/db/lasterror',
|
'$BUILD_DIR/mongo/db/lasterror',
|
||||||
'$BUILD_DIR/mongo/db/logical_time',
|
'$BUILD_DIR/mongo/db/logical_time',
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,6 @@
|
||||||
#include "mongo/db/db_raii.h"
|
#include "mongo/db/db_raii.h"
|
||||||
#include "mongo/db/dbdirectclient.h"
|
#include "mongo/db/dbdirectclient.h"
|
||||||
#include "mongo/db/dbhelpers.h"
|
#include "mongo/db/dbhelpers.h"
|
||||||
#include "mongo/db/free_mon/free_mon_mongod.h"
|
|
||||||
#include "mongo/db/index_builds_coordinator.h"
|
#include "mongo/db/index_builds_coordinator.h"
|
||||||
#include "mongo/db/jsobj.h"
|
#include "mongo/db/jsobj.h"
|
||||||
#include "mongo/db/kill_sessions_local.h"
|
#include "mongo/db/kill_sessions_local.h"
|
||||||
|
|
@ -561,8 +560,6 @@ OpTime ReplicationCoordinatorExternalStateImpl::onTransitionToPrimary(OperationC
|
||||||
|
|
||||||
IndexBuildsCoordinator::get(opCtx)->onStepUp(opCtx);
|
IndexBuildsCoordinator::get(opCtx)->onStepUp(opCtx);
|
||||||
|
|
||||||
notifyFreeMonitoringOnTransitionToPrimary();
|
|
||||||
|
|
||||||
// It is only necessary to check the system indexes on the first transition to primary.
|
// It is only necessary to check the system indexes on the first transition to primary.
|
||||||
// On subsequent transitions to primary the indexes will have already been created.
|
// On subsequent transitions to primary the indexes will have already been created.
|
||||||
static std::once_flag verifySystemIndexesOnce;
|
static std::once_flag verifySystemIndexesOnce;
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,6 @@ env.Library(
|
||||||
'cluster_rwc_defaults_commands.cpp',
|
'cluster_rwc_defaults_commands.cpp',
|
||||||
'cluster_set_allow_migrations_cmd.cpp',
|
'cluster_set_allow_migrations_cmd.cpp',
|
||||||
'cluster_set_feature_compatibility_version_cmd.cpp',
|
'cluster_set_feature_compatibility_version_cmd.cpp',
|
||||||
'cluster_set_free_monitoring_cmd.cpp' if get_option("enable-free-mon") == 'on' else [],
|
|
||||||
'cluster_set_index_commit_quorum_cmd.cpp',
|
'cluster_set_index_commit_quorum_cmd.cpp',
|
||||||
'cluster_shard_collection_cmd.cpp',
|
'cluster_shard_collection_cmd.cpp',
|
||||||
'cluster_shutdown_cmd.cpp',
|
'cluster_shutdown_cmd.cpp',
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2018-present MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the Server Side Public License, version 1,
|
|
||||||
* as published by MongoDB, Inc.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* Server Side Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the Server Side Public License
|
|
||||||
* along with this program. If not, see
|
|
||||||
* <http://www.mongodb.com/licensing/server-side-public-license>.
|
|
||||||
*
|
|
||||||
* As a special exception, the copyright holders give permission to link the
|
|
||||||
* code of portions of this program with the OpenSSL library under certain
|
|
||||||
* conditions as described in each individual source file and distribute
|
|
||||||
* linked combinations including the program with the OpenSSL library. You
|
|
||||||
* must comply with the Server Side Public License in all respects for
|
|
||||||
* all of the code used other than as permitted herein. If you modify file(s)
|
|
||||||
* with this exception, you may extend this exception to your version of the
|
|
||||||
* file(s), but you are not obligated to do so. If you do not wish to do so,
|
|
||||||
* delete this exception statement from your version. If you delete this
|
|
||||||
* exception statement from all source files in the program, then also delete
|
|
||||||
* it in the license file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "mongo/platform/basic.h"
|
|
||||||
|
|
||||||
#include "mongo/db/auth/authorization_session.h"
|
|
||||||
#include "mongo/db/commands.h"
|
|
||||||
|
|
||||||
namespace mongo {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class ClusterSetFreeMonitoring : public BasicCommand {
|
|
||||||
public:
|
|
||||||
ClusterSetFreeMonitoring() : BasicCommand("setFreeMonitoring") {}
|
|
||||||
|
|
||||||
AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
|
|
||||||
return AllowedOnSecondary::kNever;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool supportsWriteConcern(const BSONObj& cmd) const final {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string help() const final {
|
|
||||||
return "setFreeMonitoring command must be run against mongod instances";
|
|
||||||
}
|
|
||||||
|
|
||||||
Status checkAuthForCommand(Client* client,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj) const final {
|
|
||||||
if (!AuthorizationSession::get(client)->isAuthorizedForActionsOnResource(
|
|
||||||
ResourcePattern::forClusterResource(), ActionType::setFreeMonitoring)) {
|
|
||||||
return Status(ErrorCodes::Unauthorized, "Unauthorized");
|
|
||||||
}
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool run(OperationContext* opCtx,
|
|
||||||
const std::string& dbname,
|
|
||||||
const BSONObj& cmdObj,
|
|
||||||
BSONObjBuilder& result) final {
|
|
||||||
uasserted(ErrorCodes::CommandFailed, help());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} clusterSetFreeMonitoring;
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace mongo
|
|
||||||
|
|
@ -1812,57 +1812,6 @@ DB.prototype.watch = function(pipeline, options) {
|
||||||
return this._runAggregate({aggregate: 1, pipeline: pipeline}, aggOptions);
|
return this._runAggregate({aggregate: 1, pipeline: pipeline}, aggOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
DB.prototype.getFreeMonitoringStatus = function() {
|
|
||||||
'use strict';
|
|
||||||
return assert.commandWorked(this.adminCommand({getFreeMonitoringStatus: 1}));
|
|
||||||
};
|
|
||||||
|
|
||||||
DB.prototype.enableFreeMonitoring = function() {
|
|
||||||
'use strict';
|
|
||||||
let reply, isPrimary;
|
|
||||||
if (this.getMongo().getApiParameters().apiVersion) {
|
|
||||||
reply = this.hello();
|
|
||||||
isPrimary = reply.isWritablePrimary;
|
|
||||||
} else {
|
|
||||||
reply = this.isMaster();
|
|
||||||
isPrimary = reply.ismaster;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPrimary) {
|
|
||||||
print("ERROR: db.enableFreeMonitoring() may only be run on a primary");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.commandWorked(this.adminCommand({setFreeMonitoring: 1, action: 'enable'}));
|
|
||||||
|
|
||||||
const cmd = this.adminCommand({getFreeMonitoringStatus: 1});
|
|
||||||
if (!cmd.ok && (cmd.code == ErrorCode.Unauthorized)) {
|
|
||||||
// Edge case: It's technically possible that a user can change free-mon state,
|
|
||||||
// but is not allowed to inspect it.
|
|
||||||
print("Successfully initiated free monitoring, but unable to determine status " +
|
|
||||||
"as you lack the 'checkFreeMonitoringStatus' privilege.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert.commandWorked(cmd);
|
|
||||||
|
|
||||||
if (cmd.state !== 'enabled') {
|
|
||||||
const url = this.adminCommand({'getParameter': 1, 'cloudFreeMonitoringEndpointURL': 1})
|
|
||||||
.cloudFreeMonitoringEndpointURL;
|
|
||||||
|
|
||||||
print("Unable to get immediate response from the Cloud Monitoring service. We will" +
|
|
||||||
"continue to retry in the background. Please check your firewall " +
|
|
||||||
"settings to ensure that mongod can communicate with \"" + url + "\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
print(tojson(cmd));
|
|
||||||
};
|
|
||||||
|
|
||||||
DB.prototype.disableFreeMonitoring = function() {
|
|
||||||
'use strict';
|
|
||||||
assert.commandWorked(this.adminCommand({setFreeMonitoring: 1, action: 'disable'}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Writing `this.hasOwnProperty` would cause DB.prototype.getCollection() to be called since the
|
// Writing `this.hasOwnProperty` would cause DB.prototype.getCollection() to be called since the
|
||||||
// DB's getProperty() handler in C++ takes precedence when a property isn't defined on the DB
|
// DB's getProperty() handler in C++ takes precedence when a property isn't defined on the DB
|
||||||
// instance directly. The "hasOwnProperty" property is defined on Object.prototype, so we must
|
// instance directly. The "hasOwnProperty" property is defined on Object.prototype, so we must
|
||||||
|
|
|
||||||
|
|
@ -986,12 +986,6 @@ int mongo_main(int argc, char* argv[]) {
|
||||||
true,
|
true,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
scope->exec("shellHelper( 'show', 'freeMonitoring' )",
|
|
||||||
"(freeMonitoring)",
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false);
|
|
||||||
|
|
||||||
scope->exec("shellHelper( 'show', 'automationNotices' )",
|
scope->exec("shellHelper( 'show', 'automationNotices' )",
|
||||||
"(automationnotices)",
|
"(automationnotices)",
|
||||||
false,
|
false,
|
||||||
|
|
|
||||||
|
|
@ -1116,52 +1116,6 @@ shellHelper.show = function(what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (what == "freeMonitoring") {
|
|
||||||
var dbDeclared, ex;
|
|
||||||
try {
|
|
||||||
// !!db essentially casts db to a boolean
|
|
||||||
// Will throw a reference exception if db hasn't been declared.
|
|
||||||
dbDeclared = !!db;
|
|
||||||
} catch (ex) {
|
|
||||||
dbDeclared = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dbDeclared) {
|
|
||||||
const freemonStatus = db.adminCommand({getFreeMonitoringStatus: 1});
|
|
||||||
|
|
||||||
if (freemonStatus.ok) {
|
|
||||||
if (freemonStatus.state == 'enabled' &&
|
|
||||||
freemonStatus.hasOwnProperty('userReminder')) {
|
|
||||||
print("---");
|
|
||||||
print(freemonStatus.userReminder);
|
|
||||||
print("---");
|
|
||||||
} else if (freemonStatus.state === 'undecided') {
|
|
||||||
print(
|
|
||||||
"---\n" + messageIndent +
|
|
||||||
"Enable MongoDB's free cloud-based monitoring service, which will then receive and display\n" +
|
|
||||||
messageIndent +
|
|
||||||
"metrics about your deployment (disk utilization, CPU, operation statistics, etc).\n" +
|
|
||||||
"\n" + messageIndent +
|
|
||||||
"The monitoring data will be available on a MongoDB website with a unique URL accessible to you\n" +
|
|
||||||
messageIndent +
|
|
||||||
"and anyone you share the URL with. MongoDB may use this information to make product\n" +
|
|
||||||
messageIndent +
|
|
||||||
"improvements and to suggest MongoDB products and deployment options to you.\n" +
|
|
||||||
"\n" + messageIndent +
|
|
||||||
"To enable free monitoring, run the following command: db.enableFreeMonitoring()\n" +
|
|
||||||
messageIndent +
|
|
||||||
"To permanently disable this reminder, run the following command: db.disableFreeMonitoring()\n" +
|
|
||||||
"---\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
} else {
|
|
||||||
print("Cannot show freeMonitoring, \"db\" is not set");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (what == "nonGenuineMongoDBCheck") {
|
if (what == "nonGenuineMongoDBCheck") {
|
||||||
let matchesKnownImposterSignature = false;
|
let matchesKnownImposterSignature = false;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue