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,
|
||||
)
|
||||
|
||||
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',
|
||||
choices=["auto", "on", "off"],
|
||||
default="auto",
|
||||
|
|
@ -2694,7 +2687,6 @@ if has_ninja_module:
|
|||
|
||||
# --- check system ---
|
||||
ssl_provider = None
|
||||
free_monitoring = get_option("enable-free-mon")
|
||||
http_client = get_option("enable-http-client")
|
||||
|
||||
def isSanitizerEnabled(self, sanitizerName):
|
||||
|
|
@ -2709,7 +2701,6 @@ env.AddMethod(isSanitizerEnabled, 'IsSanitizerEnabled')
|
|||
def doConfigure(myenv):
|
||||
global wiredtiger
|
||||
global ssl_provider
|
||||
global free_monitoring
|
||||
global http_client
|
||||
|
||||
# Check that the compilers work.
|
||||
|
|
@ -4413,16 +4404,6 @@ def doConfigure(myenv):
|
|||
# ask each module to configure itself and the build environment.
|
||||
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
|
||||
if http_client == "auto":
|
||||
if checkHTTPLib():
|
||||
|
|
@ -4433,12 +4414,6 @@ def doConfigure(myenv):
|
|||
elif http_client == "on":
|
||||
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":
|
||||
# This checks for an altivec optimization we use in full text search.
|
||||
# Different versions of gcc appear to put output bytes in different
|
||||
|
|
@ -5247,7 +5222,6 @@ module_sconscripts = moduleconfig.get_module_sconscripts(mongo_modules)
|
|||
Export([
|
||||
'debugBuild',
|
||||
'endian',
|
||||
'free_monitoring',
|
||||
'get_option',
|
||||
'has_option',
|
||||
'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
|
||||
.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
|
||||
.PP
|
||||
\fBmongod \-\-ldapServers\f1
|
||||
|
|
@ -1324,9 +1251,9 @@ anything preceeding the suffix into a regex capture group.
|
|||
{
|
||||
match: "(.+)@DBA.EXAMPLE.COM",
|
||||
ldapQuery: "ou=dba,dc=example,dc=com??one?(user={0})"
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
]"
|
||||
.EE
|
||||
.PP
|
||||
|
|
|
|||
|
|
@ -3,4 +3,3 @@
|
|||
- [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)
|
||||
- [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 >-
|
||||
--allocator=system
|
||||
--dbg=off
|
||||
--enable-free-mon=off
|
||||
--enable-http-client=off
|
||||
--js-engine=none
|
||||
--opt=size
|
||||
|
|
@ -2487,7 +2486,6 @@ tasks:
|
|||
task_compile_flags: >-
|
||||
--dbg=off
|
||||
--link-model=dynamic-sdk
|
||||
--enable-free-mon=off
|
||||
--ssl=off
|
||||
--enable-http-client=off
|
||||
--modules=
|
||||
|
|
@ -2520,7 +2518,6 @@ tasks:
|
|||
compiling_for_test: true
|
||||
task_compile_flags: >-
|
||||
--dbg=off
|
||||
--enable-free-mon=off
|
||||
--ssl=off
|
||||
--enable-http-client=off
|
||||
--modules=
|
||||
|
|
@ -5814,15 +5811,6 @@ tasks:
|
|||
resmoke_args: --suites=watchdog --storageEngine=inMemory
|
||||
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
|
||||
name: client_encrypt
|
||||
tags: ["ssl", "encrypt"]
|
||||
|
|
@ -7230,7 +7218,7 @@ buildvariants:
|
|||
run_on:
|
||||
- rhel80-small
|
||||
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: >-
|
||||
--excludeWithAnyTags=requires_http_client
|
||||
--repeatSuites=10
|
||||
|
|
@ -7269,7 +7257,7 @@ buildvariants:
|
|||
- rhel80-medium
|
||||
expansions:
|
||||
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_mode: all
|
||||
test_flags: --excludeWithAnyTags=requires_http_client
|
||||
|
|
@ -7298,7 +7286,6 @@ buildvariants:
|
|||
- name: .change_streams !.secondary_reads
|
||||
- name: .misc_js
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: jsCore_txns_large_txns_format
|
||||
- name: jsonSchema
|
||||
|
|
@ -7333,7 +7320,7 @@ buildvariants:
|
|||
run_on:
|
||||
- rhel80-small
|
||||
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_edition: targeted
|
||||
# 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_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jepsen
|
||||
distros:
|
||||
- ubuntu1804-build
|
||||
|
|
@ -7441,7 +7427,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
|
|
@ -7702,7 +7687,6 @@ buildvariants:
|
|||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: build_variant_gen
|
||||
- name: free_monitoring
|
||||
- name: jsCore
|
||||
- name: replica_sets_jscore_passthrough
|
||||
- name: .publish
|
||||
|
|
@ -7729,7 +7713,6 @@ buildvariants:
|
|||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: build_variant_gen
|
||||
- name: free_monitoring
|
||||
- name: jsCore
|
||||
- name: replica_sets_jscore_passthrough
|
||||
- name: generate_buildid_to_debug_symbols_mapping
|
||||
|
|
@ -7765,7 +7748,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
|
|
@ -7901,7 +7883,6 @@ buildvariants:
|
|||
tasks:
|
||||
- name: compile_test_and_package_serial_TG
|
||||
- name: build_variant_gen
|
||||
- name: free_monitoring
|
||||
- name: jsCore
|
||||
- name: replica_sets_jscore_passthrough
|
||||
- name: .publish
|
||||
|
|
@ -7994,7 +7975,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
|
|
@ -8096,7 +8076,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: libunwind_tests
|
||||
|
|
@ -8195,7 +8174,6 @@ buildvariants:
|
|||
- amazon2-arm64-large
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -8277,7 +8255,6 @@ buildvariants:
|
|||
distros:
|
||||
- windows-vsCurrent-large
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: initial_sync_fuzzer_gen
|
||||
- name: .jscore .common !.auth !.sharding
|
||||
- name: jsCore_txns_large_txns_format
|
||||
|
|
@ -8517,7 +8494,6 @@ buildvariants:
|
|||
- windows-vsCurrent-large
|
||||
- name: .concurrency .common
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.auth
|
||||
- name: jsonSchema
|
||||
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns
|
||||
|
|
@ -8659,7 +8635,6 @@ buildvariants:
|
|||
- name: .misc_js
|
||||
- name: .concurrency !.ubsan !.no_txns !.debug_only !.kill_terminate
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: initial_sync_fuzzer_gen
|
||||
- name: .jscore .common !.auth
|
||||
- name: jsCore_txns_large_txns_format
|
||||
|
|
@ -9813,7 +9788,6 @@ buildvariants:
|
|||
- rhel70
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -9860,7 +9834,6 @@ buildvariants:
|
|||
- rhel80-build
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -9906,7 +9879,6 @@ buildvariants:
|
|||
- rhel82-arm64-large
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -10306,7 +10278,6 @@ buildvariants:
|
|||
- suse12-sp5-large
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jstestfuzz .common
|
||||
- name: multiversion_gen
|
||||
|
|
@ -10393,7 +10364,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -10489,7 +10459,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -10579,7 +10548,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -10669,7 +10637,6 @@ buildvariants:
|
|||
- name: .concurrency .common
|
||||
- name: concurrency_replication_causal_consistency_gen
|
||||
- name: disk_wiredtiger
|
||||
- name: free_monitoring
|
||||
- name: .jscore .common !.decimal
|
||||
- name: .jstestfuzz .common
|
||||
- name: .logical_session_cache .one_sec
|
||||
|
|
@ -10865,7 +10832,7 @@ buildvariants:
|
|||
# If you add anything to san_options, make sure the appropriate changes are
|
||||
# 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"
|
||||
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
|
||||
multiversion_platform: ubuntu1804
|
||||
multiversion_edition: enterprise
|
||||
|
|
@ -10887,7 +10854,6 @@ buildvariants:
|
|||
- name: .misc_js
|
||||
- name: .concurrency !.ubsan !.no_txns !.kill_terminate
|
||||
- name: .encrypt
|
||||
- name: free_monitoring
|
||||
- name: external_auth
|
||||
- name: external_auth_aws
|
||||
- name: initial_sync_fuzzer_gen
|
||||
|
|
@ -10944,7 +10910,6 @@ buildvariants:
|
|||
- name: compile_test_and_package_serial_TG
|
||||
- name: build_variant_gen
|
||||
- name: .aggfuzzer .common
|
||||
- name: free_monitoring
|
||||
- name: .jstestfuzz !.initsync
|
||||
|
||||
- &ubuntu1804-debug-ubsan-template
|
||||
|
|
@ -10961,7 +10926,7 @@ buildvariants:
|
|||
# If you add anything to san_options, make sure the appropriate changes are
|
||||
# also made to SConstruct.
|
||||
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
|
||||
multiversion_platform: ubuntu1804
|
||||
multiversion_edition: enterprise
|
||||
|
|
@ -10982,7 +10947,6 @@ buildvariants:
|
|||
- name: .concurrency !.no_txns !.repl !.kill_terminate
|
||||
- name: disk_wiredtiger
|
||||
- name: .encrypt
|
||||
- name: free_monitoring
|
||||
- name: initial_sync_fuzzer_gen
|
||||
- name: .jscore .common
|
||||
- name: jsCore_minimum_batch_size
|
||||
|
|
@ -11096,12 +11060,8 @@ buildvariants:
|
|||
# TODO SERVER-48490: report_thread_leaks=0 suppresses reporting
|
||||
# thread leaks, which we have because we don't do a clean shutdown
|
||||
# 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
|
||||
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.
|
||||
resmoke_jobs_factor: 0.3
|
||||
scons_cache_scope: shared
|
||||
|
|
|
|||
|
|
@ -4159,16 +4159,6 @@ var authCommandsLib = {
|
|||
{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",
|
||||
command: {getLastError: 1},
|
||||
|
|
|
|||
|
|
@ -317,7 +317,6 @@ let viewsCommandTests = {
|
|||
getCmdLineOpts: {skip: isUnrelated},
|
||||
getDefaultRWConcern: {skip: isUnrelated},
|
||||
getDiagnosticData: {skip: isUnrelated},
|
||||
getFreeMonitoringStatus: {skip: isUnrelated},
|
||||
getLastError: {skip: isUnrelated},
|
||||
getLog: {skip: isUnrelated},
|
||||
getMore: {
|
||||
|
|
@ -566,7 +565,6 @@ let viewsCommandTests = {
|
|||
setCommittedSnapshot: {skip: isAnInternalCommand},
|
||||
setDefaultRWConcern: {skip: isUnrelated},
|
||||
setFeatureCompatibilityVersion: {skip: isUnrelated},
|
||||
setFreeMonitoring: {skip: isUnrelated},
|
||||
setProfilingFilterGlobally: {skip: isUnrelated},
|
||||
setParameter: {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},
|
||||
getDefaultRWConcern: {skip: isNotAUserDataRead},
|
||||
getDiagnosticData: {skip: isNotAUserDataRead},
|
||||
getFreeMonitoringStatus: {skip: isNotAUserDataRead},
|
||||
getLastError: {skip: isPrimaryOnly},
|
||||
getLog: {skip: isNotAUserDataRead},
|
||||
getMore: {
|
||||
|
|
@ -311,7 +310,6 @@ const allCommands = {
|
|||
setDefaultRWConcern: {skip: isPrimaryOnly},
|
||||
setIndexCommitQuorum: {skip: isPrimaryOnly},
|
||||
setFeatureCompatibilityVersion: {skip: isPrimaryOnly},
|
||||
setFreeMonitoring: {skip: isPrimaryOnly},
|
||||
setProfilingFilterGlobally: {skip: isNotAUserDataRead},
|
||||
setParameter: {skip: isNotAUserDataRead},
|
||||
setShardVersion: {skip: isNotAUserDataRead},
|
||||
|
|
|
|||
|
|
@ -633,8 +633,6 @@ let testCases = {
|
|||
}
|
||||
},
|
||||
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)"},
|
||||
setParameter: {skip: "executes locally on mongos (not sent to any remote node)"},
|
||||
shardCollection: {skip: "does not forward command to primary shard"},
|
||||
|
|
|
|||
|
|
@ -1209,11 +1209,6 @@ let MongosAPIParametersUtil = (function() {
|
|||
command: () => ({setFeatureCompatibilityVersion: latestFCV})
|
||||
}
|
||||
},
|
||||
{
|
||||
commandName: "setFreeMonitoring",
|
||||
skip: "explicitly fails for mongos, primary mongod only",
|
||||
conditional: true
|
||||
},
|
||||
{
|
||||
commandName: "setProfilingFilterGlobally",
|
||||
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"},
|
||||
getDefaultRWConcern: {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"},
|
||||
getLog: {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"},
|
||||
setDefaultRWConcern: {skip: "special case (must run after all other commands)"},
|
||||
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"},
|
||||
setIndexCommitQuorum: {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"},
|
||||
setIndexCommitQuorum: {skip: "primary only"},
|
||||
setFeatureCompatibilityVersion: {skip: "primary only"},
|
||||
setFreeMonitoring: {skip: "primary only"},
|
||||
setProfilingFilterGlobally: {skip: "does not return user data"},
|
||||
setParameter: {skip: "does not return user data"},
|
||||
setShardVersion: {skip: "does not return user data"},
|
||||
|
|
|
|||
|
|
@ -369,7 +369,6 @@ let testCases = {
|
|||
setDefaultRWConcern: {skip: "primary only"},
|
||||
setIndexCommitQuorum: {skip: "primary only"},
|
||||
setFeatureCompatibilityVersion: {skip: "primary only"},
|
||||
setFreeMonitoring: {skip: "primary only"},
|
||||
setProfilingFilterGlobally: {skip: "does not return user data"},
|
||||
setParameter: {skip: "does not return user data"},
|
||||
setShardVersion: {skip: "does not return user data"},
|
||||
|
|
|
|||
|
|
@ -304,7 +304,6 @@ let testCases = {
|
|||
setDefaultRWConcern: {skip: "primary only"},
|
||||
setIndexCommitQuorum: {skip: "primary only"},
|
||||
setFeatureCompatibilityVersion: {skip: "primary only"},
|
||||
setFreeMonitoring: {skip: "primary only"},
|
||||
setProfilingFilterGlobally: {skip: "does not return user data"},
|
||||
setParameter: {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: 251,name: NoSuchTransaction,categories: [VoteAbortError]}
|
||||
- {code: 252,name: ReentrancyNotAllowed}
|
||||
- {code: 253,name: FreeMonHttpInFlight}
|
||||
- {code: 254,name: FreeMonHttpTemporaryFailure}
|
||||
- {code: 255,name: FreeMonHttpPermanentFailure}
|
||||
# - {code: 253,name: FreeMonHttpInFlight} # Removed in 7.1
|
||||
# - {code: 254,name: FreeMonHttpTemporaryFailure} # Removed in 7.1
|
||||
# - {code: 255,name: FreeMonHttpPermanentFailure} # Removed in 7.1
|
||||
- {code: 256,name: TransactionCommitted}
|
||||
- {code: 257,name: TransactionTooLarge}
|
||||
- {code: 258,name: UnknownFeatureCompatibilityVersion}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ env.SConscript(
|
|||
'concurrency',
|
||||
'cst',
|
||||
'exec',
|
||||
'free_mon',
|
||||
'fts',
|
||||
'ftdc',
|
||||
'geo',
|
||||
|
|
@ -2108,7 +2107,6 @@ env.Library(
|
|||
'dbdirectclient',
|
||||
'dbhelpers',
|
||||
'exec/working_set',
|
||||
'free_mon/free_mon_mongod',
|
||||
'ftdc/ftdc_mongod',
|
||||
'fts/ftsmongod',
|
||||
'index/index_access_method',
|
||||
|
|
@ -2210,7 +2208,6 @@ env.Library(
|
|||
'concurrency/flow_control_ticketholder',
|
||||
'concurrency/lock_manager',
|
||||
'fcv_op_observer',
|
||||
'free_mon/free_mon_mongod',
|
||||
'ftdc/ftdc_mongod',
|
||||
'index/index_access_method',
|
||||
'index_builds_coordinator_mongod',
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ enums:
|
|||
changeOwnPassword : "changeOwnPassword"
|
||||
changeOwnCustomData : "changeOwnCustomData"
|
||||
changeStream : "changeStream"
|
||||
checkFreeMonitoringStatus : "checkFreeMonitoringStatus"
|
||||
checkFreeMonitoringStatus : "checkFreeMonitoringStatus" # Removed (backwards compatibility)
|
||||
cleanupOrphaned : "cleanupOrphaned"
|
||||
clearJumboFlag : "clearJumboFlag"
|
||||
closeAllDatabases : "closeAllDatabases" # Deprecated (backwards compatibility)
|
||||
|
|
@ -156,7 +156,7 @@ enums:
|
|||
setAuthenticationRestriction : "setAuthenticationRestriction"
|
||||
setDefaultRWConcern : "setDefaultRWConcern"
|
||||
setFeatureCompatibilityVersion : "setFeatureCompatibilityVersion"
|
||||
setFreeMonitoring : "setFreeMonitoring"
|
||||
setFreeMonitoring : "setFreeMonitoring" # Removed (backwards compatibility)
|
||||
setParameter : "setParameter"
|
||||
shardCollection : "shardCollection" # ID only
|
||||
shardingState : "shardingState"
|
||||
|
|
|
|||
|
|
@ -176,7 +176,6 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
|
|||
|
||||
// clusterMonitor role actions that target the cluster resource
|
||||
clusterMonitorRoleClusterActions
|
||||
<< ActionType::checkFreeMonitoringStatus
|
||||
<< ActionType::connPoolStats
|
||||
<< ActionType::getCmdLineOpts
|
||||
<< ActionType::getDefaultRWConcern // clusterManager gets this also
|
||||
|
|
@ -251,8 +250,7 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
|
|||
<< ActionType::getDefaultRWConcern // clusterMonitor gets this also
|
||||
<< ActionType::runTenantMigration
|
||||
<< ActionType::setDefaultRWConcern
|
||||
<< ActionType::setFeatureCompatibilityVersion
|
||||
<< ActionType::setFreeMonitoring;
|
||||
<< ActionType::setFeatureCompatibilityVersion;
|
||||
|
||||
clusterManagerRoleDatabaseActions
|
||||
<< 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/exec/working_set_common.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/util.h"
|
||||
#include "mongo/db/global_settings.h"
|
||||
|
|
@ -652,8 +651,6 @@ ExitCode _initAndListen(ServiceContext* serviceContext, int listenPort) {
|
|||
logStartup(startupOpCtx.get());
|
||||
}
|
||||
|
||||
startFreeMonitoring(serviceContext);
|
||||
|
||||
auto replCoord = repl::ReplicationCoordinator::get(startupOpCtx.get());
|
||||
invariant(replCoord);
|
||||
|
||||
|
|
@ -1064,8 +1061,6 @@ void setUpObservers(ServiceContext* serviceContext) {
|
|||
std::make_unique<repl::PrimaryOnlyServiceOpObserver>(serviceContext));
|
||||
opObserverRegistry->addObserver(std::make_unique<FcvOpObserver>());
|
||||
|
||||
setupFreeMonitoringOpObserver(opObserverRegistry.get());
|
||||
|
||||
if (audit::opObserverRegistrar) {
|
||||
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");
|
||||
HealthLog::get(serviceContext).shutdown();
|
||||
|
||||
|
|
|
|||
|
|
@ -1425,7 +1425,6 @@ env.Library(
|
|||
'$BUILD_DIR/mongo/db/cloner',
|
||||
'$BUILD_DIR/mongo/db/concurrency/lock_manager',
|
||||
'$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/lasterror',
|
||||
'$BUILD_DIR/mongo/db/logical_time',
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@
|
|||
#include "mongo/db/db_raii.h"
|
||||
#include "mongo/db/dbdirectclient.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/jsobj.h"
|
||||
#include "mongo/db/kill_sessions_local.h"
|
||||
|
|
@ -561,8 +560,6 @@ OpTime ReplicationCoordinatorExternalStateImpl::onTransitionToPrimary(OperationC
|
|||
|
||||
IndexBuildsCoordinator::get(opCtx)->onStepUp(opCtx);
|
||||
|
||||
notifyFreeMonitoringOnTransitionToPrimary();
|
||||
|
||||
// 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.
|
||||
static std::once_flag verifySystemIndexesOnce;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ env.Library(
|
|||
'cluster_rwc_defaults_commands.cpp',
|
||||
'cluster_set_allow_migrations_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_shard_collection_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);
|
||||
};
|
||||
|
||||
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
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -986,12 +986,6 @@ int mongo_main(int argc, char* argv[]) {
|
|||
true,
|
||||
false);
|
||||
|
||||
scope->exec("shellHelper( 'show', 'freeMonitoring' )",
|
||||
"(freeMonitoring)",
|
||||
false,
|
||||
true,
|
||||
false);
|
||||
|
||||
scope->exec("shellHelper( 'show', 'automationNotices' )",
|
||||
"(automationnotices)",
|
||||
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") {
|
||||
let matchesKnownImposterSignature = false;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue