SERVER-78987 Remove the free monitoring code from mongodb/mongo repo

(cherry picked from commit 00c97452ae)
This commit is contained in:
Mark Benvenuto 2023-08-18 15:42:27 -04:00 committed by Evergreen Agent
parent 19347b03d6
commit 86bb57f8c6
88 changed files with 10 additions and 9242 deletions

View File

@ -426,14 +426,6 @@ add_option(
nargs=0, nargs=0,
) )
add_option(
'enable-free-mon',
choices=["auto", "on", "off"],
default="auto",
help='Disable support for Free Monitoring to avoid HTTP client library dependencies',
type='choice',
)
add_option( add_option(
'enable-http-client', 'enable-http-client',
choices=["auto", "on", "off"], choices=["auto", "on", "off"],
@ -3287,7 +3279,6 @@ if has_ninja_module:
# --- check system --- # --- check system ---
ssl_provider = None ssl_provider = None
free_monitoring = get_option("enable-free-mon")
http_client = get_option("enable-http-client") http_client = get_option("enable-http-client")
@ -3305,7 +3296,6 @@ env.AddMethod(isSanitizerEnabled, 'IsSanitizerEnabled')
def doConfigure(myenv): def doConfigure(myenv):
global wiredtiger global wiredtiger
global ssl_provider global ssl_provider
global free_monitoring
global http_client global http_client
# Check that the compilers work. # Check that the compilers work.
@ -5354,16 +5344,6 @@ def doConfigure(myenv):
# ask each module to configure itself and the build environment. # ask each module to configure itself and the build environment.
moduleconfig.configure_modules(mongo_modules, conf) moduleconfig.configure_modules(mongo_modules, conf)
# Resolve --enable-free-mon
if free_monitoring == "auto":
if 'enterprise' not in conf.env['MONGO_MODULES']:
free_monitoring = "on"
else:
free_monitoring = "off"
if free_monitoring == "on":
checkHTTPLib(required=True)
# Resolve --enable-http-client # Resolve --enable-http-client
if http_client == "auto": if http_client == "auto":
if checkHTTPLib(): if checkHTTPLib():
@ -5374,12 +5354,6 @@ def doConfigure(myenv):
elif http_client == "on": elif http_client == "on":
checkHTTPLib(required=True) checkHTTPLib(required=True)
# Sanity check.
# We know that http_client was explicitly disabled here,
# because the free_monitoring check would have failed if no http lib were available.
if (free_monitoring == "on") and (http_client == "off"):
env.ConfError("FreeMonitoring requires an HTTP client which has been explicitly disabled")
if env['TARGET_ARCH'] == "ppc64le": if env['TARGET_ARCH'] == "ppc64le":
# This checks for an altivec optimization we use in full text search. # This checks for an altivec optimization we use in full text search.
# Different versions of gcc appear to put output bytes in different # Different versions of gcc appear to put output bytes in different
@ -6295,7 +6269,6 @@ version_parts = [int(x) for x in version_parts[:4]]
Export([ Export([
'debugBuild', 'debugBuild',
'endian', 'endian',
'free_monitoring',
'get_option', 'get_option',
'has_option', 'has_option',
'http_client', 'http_client',

View File

@ -1,10 +0,0 @@
test_kind: js_test
selector:
roots:
- jstests/free_mon/*.js
executor:
config:
shell_options:
nodb: ''

73
debian/mongod.1 vendored
View File

@ -857,75 +857,6 @@ For usage examples, see:
\fBConvert Command\-Line Options to YAML\f1 \fBConvert Command\-Line Options to YAML\f1
.RE .RE
.RE .RE
.SS FREE MONITORING
.PP
\fBmongod \-\-enableFreeMonitoring\f1
.RS
.PP
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
Optional tag to describe environment context. The tag can be sent as
part of the \fBfree MongoDB Cloud monitoring\f1 registration at start up.
.PP
For the corresponding configuration file setting, see
\fBcloud.monitoring.free.tags\f1\f1\&.
.RE
.SS LDAP AUTHENTICATION OR AUTHORIZATION OPTIONS .SS LDAP AUTHENTICATION OR AUTHORIZATION OPTIONS
.PP .PP
\fBmongod \-\-ldapServers\f1 \fBmongod \-\-ldapServers\f1
@ -1344,9 +1275,9 @@ anything preceeding the suffix into a regex capture group.
{ {
match: "(.+)@DBA.EXAMPLE.COM", match: "(.+)@DBA.EXAMPLE.COM",
ldapQuery: "ou=dba,dc=example,dc=com??one?(user={0})" ldapQuery: "ou=dba,dc=example,dc=com??one?(user={0})"
} }
]" ]"
.EE .EE
.PP .PP

View File

@ -3,5 +3,4 @@
- [Identity and Access Management](https://github.com/mongodb/mongo/blob/master/src/mongo/db/auth/README.md) - [Identity and Access Management](https://github.com/mongodb/mongo/blob/master/src/mongo/db/auth/README.md)
- [TLS](https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/README.md) - [TLS](https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/README.md)
- [FTDC](https://github.com/mongodb/mongo/blob/master/src/mongo/db/ftdc/README.md) - [FTDC](https://github.com/mongodb/mongo/blob/master/src/mongo/db/ftdc/README.md)
- [Free Monitoring](https://github.com/mongodb/mongo/blob/master/src/mongo/db/free_mon/README.md)
- [SELinux](https://github.com/mongodb/mongodb-selinux/blob/master/README.md) - [SELinux](https://github.com/mongodb/mongodb-selinux/blob/master/README.md)

View File

@ -148,13 +148,13 @@ inside the namespace defined by `globals.cpp_namespace`. Consider the following
global: global:
cpp_namespace: "mongo" cpp_namespace: "mongo"
cpp_includes: cpp_includes:
- "mongo/db/free_mon/free_mon_mongod.h" - "mongo/util/net/ssl_parameters.h"
server_parameters: server_parameters:
cloudFreeMonitoringEndpointURL: opensslCipherConfig:
... ...
validator: validator:
callback: "onValidateFreeMonEndpointURL" # The callback is declared in "free_mon_mongod.h" callback: "validateOpensslCipherConfig" # The callback is declared in "ssl_parameters.h"
``` ```
### Specialized Server Parameters ### Specialized Server Parameters

View File

@ -323,7 +323,6 @@ buildvariants:
- name: .clustered_collections - name: .clustered_collections
- name: .misc_js - name: .misc_js
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: jsCore_txns_large_txns_format - name: jsCore_txns_large_txns_format
- name: json_schema - name: json_schema
@ -371,7 +370,6 @@ buildvariants:
--opt=on --opt=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
--variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars --variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars
--enable-free-mon=on
--enable-http-client=on --enable-http-client=on
--link-model=dynamic --link-model=dynamic
scons_cache_mode: all scons_cache_mode: all
@ -588,7 +586,6 @@ buildvariants:
distros: distros:
- windows-vsCurrent-large - windows-vsCurrent-large
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: .jscore .common !.auth !.sharding - name: .jscore .common !.auth !.sharding
- name: jsCore_txns_large_txns_format - name: jsCore_txns_large_txns_format
@ -1967,7 +1964,6 @@ buildvariants:
--sanitize=address --sanitize=address
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
compile_variant: *rhel80-debug-asan-classic-engine compile_variant: *rhel80-debug-asan-classic-engine
test_flags: >- test_flags: >-
@ -1992,7 +1988,6 @@ buildvariants:
- name: .misc_js - name: .misc_js
- name: .concurrency !.ubsan !.no_txns !.kill_terminate !.compute_mode - name: .concurrency !.ubsan !.no_txns !.kill_terminate !.compute_mode
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: external_auth - name: external_auth
- name: external_auth_aws - name: external_auth_aws
- name: external_auth_oidc - name: external_auth_oidc
@ -2053,7 +2048,6 @@ buildvariants:
--sanitize=undefined --sanitize=undefined
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
compile_variant: *rhel80-debug-ubsan-all-feature-flags compile_variant: *rhel80-debug-ubsan-all-feature-flags
# To force disable feature flags even on the all feature flags variant, please use this file: # To force disable feature flags even on the all feature flags variant, please use this file:
@ -2096,7 +2090,6 @@ buildvariants:
--sanitize=undefined --sanitize=undefined
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
test_flags: >- test_flags: >-
--mongodSetParameters="{internalQueryFrameworkControl: forceClassicEngine}" --mongodSetParameters="{internalQueryFrameworkControl: forceClassicEngine}"
@ -2119,7 +2112,6 @@ buildvariants:
- name: .concurrency !.no_txns !.repl !.kill_terminate !.compute_mode - name: .concurrency !.no_txns !.repl !.kill_terminate !.compute_mode
- name: disk_wiredtiger - name: disk_wiredtiger
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: compile_integration_and_test_parallel_stream_TG - name: compile_integration_and_test_parallel_stream_TG
distros: distros:
@ -2227,7 +2219,6 @@ buildvariants:
- name: external_auth_aws - name: external_auth_aws
- name: external_auth_oidc - name: external_auth_oidc
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: .jscore .common - name: .jscore .common
- name: jsCore_column_store_indexes - name: jsCore_column_store_indexes
@ -2297,7 +2288,6 @@ buildvariants:
--allocator=system --allocator=system
--sanitize=thread --sanitize=thread
--ssl --ssl
--enable-free-mon=on
--use-libunwind=off --use-libunwind=off
--link-model=dynamic --link-model=dynamic
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)

View File

@ -110,7 +110,6 @@ buildvariants:
- name: .clustered_collections - name: .clustered_collections
- name: .misc_js - name: .misc_js
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: jsCore_txns_large_txns_format - name: jsCore_txns_large_txns_format
- name: json_schema - name: json_schema

View File

@ -3150,7 +3150,6 @@ tasks:
targets: install-stitch-support install-stitch-support-debug install-stitch-support-dev targets: install-stitch-support install-stitch-support-debug install-stitch-support-dev
task_compile_flags: >- task_compile_flags: >-
--link-model=dynamic-sdk --link-model=dynamic-sdk
--enable-free-mon=off
--ssl=off --ssl=off
--enable-http-client=off --enable-http-client=off
--modules= --modules=
@ -3182,7 +3181,6 @@ tasks:
targets: install-stitch-support-test targets: install-stitch-support-test
compiling_for_test: true compiling_for_test: true
task_compile_flags: >- task_compile_flags: >-
--enable-free-mon=off
--ssl=off --ssl=off
--enable-http-client=off --enable-http-client=off
--modules= --modules=
@ -3214,7 +3212,6 @@ tasks:
targets: archive-mongo-crypt-dev targets: archive-mongo-crypt-dev
task_compile_flags: >- task_compile_flags: >-
--allocator=system --allocator=system
--enable-free-mon=off
--enterprise-features=fle,search --enterprise-features=fle,search
--js-engine=none --js-engine=none
--link-model=dynamic-sdk --link-model=dynamic-sdk
@ -3252,7 +3249,6 @@ tasks:
--dbg=on --dbg=on
--opt=off --opt=off
--allocator=system --allocator=system
--enable-free-mon=off
--enterprise-features=fle,search --enterprise-features=fle,search
--js-engine=none --js-engine=none
--link-model=dynamic-sdk --link-model=dynamic-sdk
@ -3290,7 +3286,6 @@ tasks:
compiling_for_test: true compiling_for_test: true
task_compile_flags: >- task_compile_flags: >-
--allocator=system --allocator=system
--enable-free-mon=off
--enterprise-features=fle,search --enterprise-features=fle,search
--js-engine=none --js-engine=none
--link-model=static --link-model=static
@ -6679,15 +6674,6 @@ tasks:
resmoke_args: --storageEngine=inMemory resmoke_args: --storageEngine=inMemory
resmoke_jobs_max: 1 resmoke_jobs_max: 1
- <<: *task_template
name: free_monitoring
tags: []
commands:
- func: "do setup"
- func: "run tests"
vars:
resmoke_jobs_max: 1
- <<: *task_template - <<: *task_template
name: client_encrypt name: client_encrypt
tags: ["ssl", "encrypt", "patch_build"] tags: ["ssl", "encrypt", "patch_build"]

View File

@ -172,7 +172,6 @@ buildvariants:
--sanitize=address --sanitize=address
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
compile_variant: *rhel80-debug-asan-classic-engine compile_variant: *rhel80-debug-asan-classic-engine
test_flags: >- test_flags: >-
@ -197,7 +196,6 @@ buildvariants:
- name: .misc_js - name: .misc_js
- name: .concurrency !.ubsan !.no_txns !.kill_terminate !.compute_mode - name: .concurrency !.ubsan !.no_txns !.kill_terminate !.compute_mode
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: external_auth - name: external_auth
- name: external_auth_aws - name: external_auth_aws
- name: external_auth_oidc - name: external_auth_oidc
@ -257,7 +255,6 @@ buildvariants:
--sanitize=undefined --sanitize=undefined
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
test_flags: >- test_flags: >-
--mongodSetParameters="{internalQueryFrameworkControl: forceClassicEngine}" --mongodSetParameters="{internalQueryFrameworkControl: forceClassicEngine}"
@ -280,7 +277,6 @@ buildvariants:
- name: .concurrency !.no_txns !.repl !.kill_terminate !.compute_mode - name: .concurrency !.no_txns !.repl !.kill_terminate !.compute_mode
- name: disk_wiredtiger - name: disk_wiredtiger
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: compile_integration_and_test_parallel_stream_TG - name: compile_integration_and_test_parallel_stream_TG
distros: distros:

View File

@ -103,7 +103,6 @@ buildvariants:
--opt=on --opt=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
--variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars --variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars
--enable-free-mon=on
--enable-http-client=on --enable-http-client=on
--link-model=dynamic --link-model=dynamic
num_scons_link_jobs_available: 0.99 num_scons_link_jobs_available: 0.99
@ -144,7 +143,6 @@ buildvariants:
--ocsp-stapling=off --ocsp-stapling=off
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
--link-model=dynamic --link-model=dynamic
--enable-free-mon=on
compile_variant: *linux-debug-aubsan-compile-required compile_variant: *linux-debug-aubsan-compile-required
- <<: *linux-x86-dynamic-compile-params - <<: *linux-x86-dynamic-compile-params

View File

@ -66,7 +66,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: libunwind_tests - name: libunwind_tests
@ -192,7 +191,6 @@ buildvariants:
- amazon2-arm64-large - amazon2-arm64-large
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -370,7 +368,6 @@ buildvariants:
- amazon2023.0-large - amazon2023.0-large
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -745,7 +742,6 @@ buildvariants:
- amazon2023.0-arm64-large - amazon2023.0-arm64-large
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1031,7 +1027,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common !.decimal !.feature_flag_guarded - name: .jscore .common !.decimal !.feature_flag_guarded
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1155,7 +1150,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common !.decimal !.feature_flag_guarded - name: .jscore .common !.decimal !.feature_flag_guarded
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1273,7 +1267,6 @@ buildvariants:
- rhel70 - rhel70
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1385,7 +1378,6 @@ buildvariants:
- rhel80-build - rhel80-build
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1570,7 +1562,6 @@ buildvariants:
- rhel82-arm64-large - rhel82-arm64-large
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1693,7 +1684,6 @@ buildvariants:
- rhel90-build - rhel90-build
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common !.multiversion - name: .jstestfuzz .common !.multiversion
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1820,7 +1810,6 @@ buildvariants:
- rhel90-arm64-large - rhel90-arm64-large
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -1956,7 +1945,6 @@ buildvariants:
- suse12-sp5-large - suse12-sp5-large
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common !.decimal !.feature_flag_guarded - name: .jscore .common !.decimal !.feature_flag_guarded
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: multiversion_gen - name: multiversion_gen
@ -2134,7 +2122,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common !.decimal !.feature_flag_guarded - name: .jscore .common !.decimal !.feature_flag_guarded
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: .logical_session_cache .one_sec - name: .logical_session_cache .one_sec
@ -2193,7 +2180,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jepsen - name: .jepsen
distros: distros:
- ubuntu1804-build - ubuntu1804-build
@ -2395,7 +2381,6 @@ buildvariants:
compile_variant: ubuntu1804-arm64 compile_variant: ubuntu1804-arm64
tasks: tasks:
- name: compile_test_and_package_serial_no_unittests_TG - name: compile_test_and_package_serial_no_unittests_TG
- name: free_monitoring
- name: jsCore - name: jsCore
- name: replica_sets_jscore_passthrough - name: replica_sets_jscore_passthrough
- name: test_packages - name: test_packages
@ -2443,7 +2428,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: libunwind_tests - name: libunwind_tests
@ -2501,7 +2485,6 @@ buildvariants:
- name: .concurrency .common - name: .concurrency .common
- name: concurrency_replication_causal_consistency_gen - name: concurrency_replication_causal_consistency_gen
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common - name: .jscore .common
- name: .jstestfuzz .common - name: .jstestfuzz .common
- name: libunwind_tests - name: libunwind_tests
@ -2749,7 +2732,6 @@ buildvariants:
compile_variant: ubuntu2004-arm64 compile_variant: ubuntu2004-arm64
tasks: tasks:
- name: compile_test_and_package_serial_no_unittests_TG - name: compile_test_and_package_serial_no_unittests_TG
- name: free_monitoring
- name: jsCore - name: jsCore
- name: replica_sets_jscore_passthrough - name: replica_sets_jscore_passthrough
- name: test_packages - name: test_packages
@ -2840,7 +2822,6 @@ buildvariants:
compile_variant: ubuntu2204-arm64 compile_variant: ubuntu2204-arm64
tasks: tasks:
- name: compile_test_and_package_serial_no_unittests_TG - name: compile_test_and_package_serial_no_unittests_TG
- name: free_monitoring
- name: jsCore - name: jsCore
- name: replica_sets_jscore_passthrough - name: replica_sets_jscore_passthrough
- name: test_packages - name: test_packages
@ -2895,7 +2876,6 @@ buildvariants:
- windows-vsCurrent-large - windows-vsCurrent-large
- name: .concurrency .common - name: .concurrency .common
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: .jscore .common !.auth !.feature_flag_guarded - name: .jscore .common !.auth !.feature_flag_guarded
- name: json_schema - name: json_schema
- name: .jstestfuzz !.initsync !.flow_control !.stepdowns - name: .jstestfuzz !.initsync !.flow_control !.stepdowns
@ -3025,7 +3005,6 @@ buildvariants:
- name: .misc_js - name: .misc_js
- name: .concurrency !.ubsan !.no_txns !.kill_terminate - name: .concurrency !.ubsan !.no_txns !.kill_terminate
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: .jscore .common !.auth !.feature_flag_guarded - name: .jscore .common !.auth !.feature_flag_guarded
- name: jsCore_txns_large_txns_format - name: jsCore_txns_large_txns_format
@ -3079,7 +3058,6 @@ buildvariants:
- name: .misc_js - name: .misc_js
- name: .concurrency !.ubsan !.no_txns !.kill_terminate - name: .concurrency !.ubsan !.no_txns !.kill_terminate
- name: disk_wiredtiger - name: disk_wiredtiger
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: .jscore .common !.auth !.feature_flag_guarded - name: .jscore .common !.auth !.feature_flag_guarded
- name: jsCore_txns_large_txns_format - name: jsCore_txns_large_txns_format

View File

@ -43,7 +43,6 @@ buildvariants:
tasks: tasks:
- name: compile_test_and_package_serial_TG - name: compile_test_and_package_serial_TG
- name: .aggfuzzer .common !.feature_flag_guarded - name: .aggfuzzer .common !.feature_flag_guarded
- name: free_monitoring
- name: .jstestfuzz !.initsync - name: .jstestfuzz !.initsync
- name: generate_buildid_to_debug_symbols_mapping - name: generate_buildid_to_debug_symbols_mapping
@ -69,7 +68,6 @@ buildvariants:
--sanitize=address --sanitize=address
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
test_flags: --excludeWithAnyTags=requires_fast_memory,requires_ocsp_stapling,requires_increased_memlock_limits test_flags: --excludeWithAnyTags=requires_fast_memory,requires_ocsp_stapling,requires_increased_memlock_limits
multiversion_platform: rhel80 multiversion_platform: rhel80
@ -95,7 +93,6 @@ buildvariants:
- name: .misc_js - name: .misc_js
- name: .concurrency !.ubsan !.no_txns !.kill_terminate - name: .concurrency !.ubsan !.no_txns !.kill_terminate
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: external_auth - name: external_auth
- name: external_auth_aws - name: external_auth_aws
- name: external_auth_oidc - name: external_auth_oidc
@ -155,7 +152,6 @@ buildvariants:
--sanitize=undefined --sanitize=undefined
--ssl --ssl
--ocsp-stapling=off --ocsp-stapling=off
--enable-free-mon=on
-j$(grep -c ^processor /proc/cpuinfo) -j$(grep -c ^processor /proc/cpuinfo)
test_flags: --excludeWithAnyTags=requires_ocsp_stapling,requires_increased_memlock_limits test_flags: --excludeWithAnyTags=requires_ocsp_stapling,requires_increased_memlock_limits
multiversion_platform: rhel80 multiversion_platform: rhel80
@ -180,7 +176,6 @@ buildvariants:
- name: .concurrency !.no_txns !.repl !.kill_terminate - name: .concurrency !.no_txns !.repl !.kill_terminate
- name: disk_wiredtiger - name: disk_wiredtiger
- name: .encrypt - name: .encrypt
- name: free_monitoring
- name: initial_sync_fuzzer_gen - name: initial_sync_fuzzer_gen
- name: .jscore .common - name: .jscore .common
- name: jsCore_min_batch_repeat_queries_ese_gsm - name: jsCore_min_batch_repeat_queries_ese_gsm

View File

@ -1624,7 +1624,6 @@ buildvariants:
--variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars --variables-files=etc/scons/mongodbtoolchain_stable_gcc.vars
--use-diagnostic-latches=off --use-diagnostic-latches=off
--allocator=system --allocator=system
--enable-free-mon=off
--enterprise-features=fle,search --enterprise-features=fle,search
--js-engine=none --js-engine=none
--link-model=dynamic-sdk --link-model=dynamic-sdk

View File

@ -4671,16 +4671,6 @@ export const authCommandsLib = {
{runOnDb: secondDbName, roles: {}} {runOnDb: secondDbName, roles: {}}
] ]
}, },
{
testname: "getFreeMonitoringStatus",
skipSharded: true,
command: {getFreeMonitoringStatus: 1},
testcases: [{
runOnDb: adminDbName,
roles: {clusterMonitor: 1, clusterAdmin: 1, root: 1, __system: 1},
privileges: [{resource: {cluster: true}, actions: ["checkFreeMonitoringStatus"]}]
}]
},
{ {
testname: "getLog", testname: "getLog",
command: {getLog: "*"}, command: {getLog: "*"},

View File

@ -415,7 +415,6 @@ let viewsCommandTests = {
getCmdLineOpts: {skip: isUnrelated}, getCmdLineOpts: {skip: isUnrelated},
getDefaultRWConcern: {skip: isUnrelated}, getDefaultRWConcern: {skip: isUnrelated},
getDiagnosticData: {skip: isUnrelated}, getDiagnosticData: {skip: isUnrelated},
getFreeMonitoringStatus: {skip: isUnrelated},
getLog: {skip: isUnrelated}, getLog: {skip: isUnrelated},
getMore: { getMore: {
setup: function(conn) { setup: function(conn) {
@ -662,7 +661,6 @@ let viewsCommandTests = {
setCommittedSnapshot: {skip: isAnInternalCommand}, setCommittedSnapshot: {skip: isAnInternalCommand},
setDefaultRWConcern: {skip: isUnrelated}, setDefaultRWConcern: {skip: isUnrelated},
setFeatureCompatibilityVersion: {skip: isUnrelated}, setFeatureCompatibilityVersion: {skip: isUnrelated},
setFreeMonitoring: {skip: isUnrelated},
setProfilingFilterGlobally: {skip: isUnrelated}, setProfilingFilterGlobally: {skip: isUnrelated},
setParameter: {skip: isUnrelated}, setParameter: {skip: isUnrelated},
setShardVersion: {skip: isUnrelated}, setShardVersion: {skip: isUnrelated},

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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(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(last_metrics.localTime["$date"]), localTime);
MongoRunner.stopMongod(conn);
mock_web.stop();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -1,103 +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:
//"$binary" : {"base64" : "2gzkSY3bTlu/k3bXfpPUKg==", "subType" : "04"}
if ((typeof val) !== 'object') {
return false;
}
const binary = val['$binary'];
const subType = binary['subType'];
const base64 = binary['base64'];
// This number is the indentifier for a UUID.
// https://www.mongodb.com/docs/manual/reference/bson-types/#binary-data
if (subType !== '04') {
return false;
}
// Validate base64
return base64.match('^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$') !==
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();
})();

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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)}`);
}

View File

@ -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,
})

View File

@ -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()

View File

@ -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()

View File

@ -791,11 +791,6 @@ const allCommands = {
isAdminCommand: true, isAdminCommand: true,
command: {getDiagnosticData: 1}, command: {getDiagnosticData: 1},
}, },
getFreeMonitoringStatus: {
isAdminCommand: true,
command: {getFreeMonitoringStatus: 1},
doesNotRunOnMongos: true,
},
getLog: { getLog: {
isAdminCommand: true, isAdminCommand: true,
command: {getLog: "global"}, command: {getLog: "global"},
@ -1451,9 +1446,6 @@ const allCommands = {
}, },
setIndexCommitQuorum: {skip: requiresParallelShell}, setIndexCommitQuorum: {skip: requiresParallelShell},
setFeatureCompatibilityVersion: {skip: "is tested through this test"}, setFeatureCompatibilityVersion: {skip: "is tested through this test"},
setFreeMonitoring: {
skip: "requires cloudFreeMonitoringEndpointURL setup",
},
setProfilingFilterGlobally: { setProfilingFilterGlobally: {
// TODO SERVER-74867: Remove the skip once 7.0 is lastLTS. // TODO SERVER-74867: Remove the skip once 7.0 is lastLTS.
skip: commandIsDisabledOnLastLTS, skip: commandIsDisabledOnLastLTS,

View File

@ -271,7 +271,6 @@ const allCommands = {
getDatabaseVersion: {skip: isNotAUserDataRead}, getDatabaseVersion: {skip: isNotAUserDataRead},
getDefaultRWConcern: {skip: isNotAUserDataRead}, getDefaultRWConcern: {skip: isNotAUserDataRead},
getDiagnosticData: {skip: isNotAUserDataRead}, getDiagnosticData: {skip: isNotAUserDataRead},
getFreeMonitoringStatus: {skip: isNotAUserDataRead},
getLog: {skip: isNotAUserDataRead}, getLog: {skip: isNotAUserDataRead},
getMore: { getMore: {
command: {getMore: NumberLong(123), collection: collName}, command: {getMore: NumberLong(123), collection: collName},
@ -395,7 +394,6 @@ const allCommands = {
setDefaultRWConcern: {skip: isPrimaryOnly}, setDefaultRWConcern: {skip: isPrimaryOnly},
setIndexCommitQuorum: {skip: isPrimaryOnly}, setIndexCommitQuorum: {skip: isPrimaryOnly},
setFeatureCompatibilityVersion: {skip: isPrimaryOnly}, setFeatureCompatibilityVersion: {skip: isPrimaryOnly},
setFreeMonitoring: {skip: isPrimaryOnly},
setProfilingFilterGlobally: {skip: isNotAUserDataRead}, setProfilingFilterGlobally: {skip: isNotAUserDataRead},
setParameter: {skip: isNotAUserDataRead}, setParameter: {skip: isNotAUserDataRead},
setShardVersion: {skip: isNotAUserDataRead}, setShardVersion: {skip: isNotAUserDataRead},

View File

@ -525,7 +525,6 @@ export const TenantMigrationConcurrentWriteUtil = {
getDatabaseVersion: {skip: isNotRunOnUserDatabase}, getDatabaseVersion: {skip: isNotRunOnUserDatabase},
getDefaultRWConcern: {skip: isNotRunOnUserDatabase}, getDefaultRWConcern: {skip: isNotRunOnUserDatabase},
getDiagnosticData: {skip: isNotRunOnUserDatabase}, getDiagnosticData: {skip: isNotRunOnUserDatabase},
getFreeMonitoringStatus: {skip: isNotRunOnUserDatabase},
getLog: {skip: isNotRunOnUserDatabase}, getLog: {skip: isNotRunOnUserDatabase},
getMore: {skip: isNotWriteCommand}, getMore: {skip: isNotWriteCommand},
getParameter: {skip: isNotRunOnUserDatabase}, getParameter: {skip: isNotRunOnUserDatabase},
@ -653,7 +652,6 @@ export const TenantMigrationConcurrentWriteUtil = {
setCommittedSnapshot: {skip: isNotRunOnUserDatabase}, setCommittedSnapshot: {skip: isNotRunOnUserDatabase},
setDefaultRWConcern: {skip: isNotRunOnUserDatabase}, setDefaultRWConcern: {skip: isNotRunOnUserDatabase},
setFeatureCompatibilityVersion: {skip: isNotRunOnUserDatabase}, setFeatureCompatibilityVersion: {skip: isNotRunOnUserDatabase},
setFreeMonitoring: {skip: isNotRunOnUserDatabase},
setProfilingFilterGlobally: {skip: isNotRunOnUserDatabase}, setProfilingFilterGlobally: {skip: isNotRunOnUserDatabase},
setIndexCommitQuorum: {skip: isNotRunOnUserDatabase}, setIndexCommitQuorum: {skip: isNotRunOnUserDatabase},
setParameter: {skip: isNotRunOnUserDatabase}, setParameter: {skip: isNotRunOnUserDatabase},

View File

@ -709,8 +709,6 @@ let testCases = {
} }
}, },
setFeatureCompatibilityVersion: {skip: "not on a user database"}, setFeatureCompatibilityVersion: {skip: "not on a user database"},
setFreeMonitoring:
{skip: "explicitly fails for mongos, primary mongod only", conditional: true},
setProfilingFilterGlobally: {skip: "executes locally on mongos (not sent to any remote node)"}, setProfilingFilterGlobally: {skip: "executes locally on mongos (not sent to any remote node)"},
setParameter: {skip: "executes locally on mongos (not sent to any remote node)"}, setParameter: {skip: "executes locally on mongos (not sent to any remote node)"},
setClusterParameter: {skip: "always targets the config server"}, setClusterParameter: {skip: "always targets the config server"},

View File

@ -1251,11 +1251,6 @@ let MongosAPIParametersUtil = (function() {
command: () => ({setFeatureCompatibilityVersion: latestFCV}) command: () => ({setFeatureCompatibilityVersion: latestFCV})
} }
}, },
{
commandName: "setFreeMonitoring",
skip: "explicitly fails for mongos, primary mongod only",
conditional: true
},
{ {
commandName: "setProfilingFilterGlobally", commandName: "setProfilingFilterGlobally",
skip: "executes locally on mongos (not sent to any remote node)", skip: "executes locally on mongos (not sent to any remote node)",

View File

@ -507,7 +507,6 @@ let testCases = {
getDatabaseVersion: {skip: "does not accept read or write concern"}, getDatabaseVersion: {skip: "does not accept read or write concern"},
getDefaultRWConcern: {skip: "does not accept read or write concern"}, getDefaultRWConcern: {skip: "does not accept read or write concern"},
getDiagnosticData: {skip: "does not accept read or write concern"}, getDiagnosticData: {skip: "does not accept read or write concern"},
getFreeMonitoringStatus: {skip: "does not accept read or write concern"},
getLog: {skip: "does not accept read or write concern"}, getLog: {skip: "does not accept read or write concern"},
getMore: {skip: "does not accept read or write concern"}, getMore: {skip: "does not accept read or write concern"},
getParameter: {skip: "does not accept read or write concern"}, getParameter: {skip: "does not accept read or write concern"},
@ -738,7 +737,6 @@ let testCases = {
setCommittedSnapshot: {skip: "internal command"}, setCommittedSnapshot: {skip: "internal command"},
setDefaultRWConcern: {skip: "special case (must run after all other commands)"}, setDefaultRWConcern: {skip: "special case (must run after all other commands)"},
setFeatureCompatibilityVersion: {skip: "does not accept read or write concern"}, setFeatureCompatibilityVersion: {skip: "does not accept read or write concern"},
setFreeMonitoring: {skip: "does not accept read or write concern"},
setProfilingFilterGlobally: {skip: "does not accept read or write concern"}, setProfilingFilterGlobally: {skip: "does not accept read or write concern"},
setIndexCommitQuorum: {skip: "does not accept read or write concern"}, setIndexCommitQuorum: {skip: "does not accept read or write concern"},
setParameter: {skip: "does not accept read or write concern"}, setParameter: {skip: "does not accept read or write concern"},

View File

@ -349,7 +349,6 @@ let testCases = {
setDefaultRWConcern: {skip: "primary only"}, setDefaultRWConcern: {skip: "primary only"},
setIndexCommitQuorum: {skip: "primary only"}, setIndexCommitQuorum: {skip: "primary only"},
setFeatureCompatibilityVersion: {skip: "primary only"}, setFeatureCompatibilityVersion: {skip: "primary only"},
setFreeMonitoring: {skip: "primary only"},
setProfilingFilterGlobally: {skip: "does not return user data"}, setProfilingFilterGlobally: {skip: "does not return user data"},
setParameter: {skip: "does not return user data"}, setParameter: {skip: "does not return user data"},
setShardVersion: {skip: "does not return user data"}, setShardVersion: {skip: "does not return user data"},

View File

@ -407,7 +407,6 @@ let testCases = {
setDefaultRWConcern: {skip: "primary only"}, setDefaultRWConcern: {skip: "primary only"},
setIndexCommitQuorum: {skip: "primary only"}, setIndexCommitQuorum: {skip: "primary only"},
setFeatureCompatibilityVersion: {skip: "primary only"}, setFeatureCompatibilityVersion: {skip: "primary only"},
setFreeMonitoring: {skip: "primary only"},
setProfilingFilterGlobally: {skip: "does not return user data"}, setProfilingFilterGlobally: {skip: "does not return user data"},
setParameter: {skip: "does not return user data"}, setParameter: {skip: "does not return user data"},
setShardVersion: {skip: "does not return user data"}, setShardVersion: {skip: "does not return user data"},

View File

@ -360,7 +360,6 @@ let testCases = {
setDefaultRWConcern: {skip: "primary only"}, setDefaultRWConcern: {skip: "primary only"},
setIndexCommitQuorum: {skip: "primary only"}, setIndexCommitQuorum: {skip: "primary only"},
setFeatureCompatibilityVersion: {skip: "primary only"}, setFeatureCompatibilityVersion: {skip: "primary only"},
setFreeMonitoring: {skip: "primary only"},
setProfilingFilterGlobally: {skip: "does not return user data"}, setProfilingFilterGlobally: {skip: "does not return user data"},
setParameter: {skip: "does not return user data"}, setParameter: {skip: "does not return user data"},
setShardVersion: {skip: "does not return user data"}, setShardVersion: {skip: "does not return user data"},

View File

@ -299,9 +299,9 @@ error_codes:
- {code: 250,name: StaleChunkHistory,categories: [SnapshotError]} - {code: 250,name: StaleChunkHistory,categories: [SnapshotError]}
- {code: 251,name: NoSuchTransaction,categories: [VoteAbortError]} - {code: 251,name: NoSuchTransaction,categories: [VoteAbortError]}
- {code: 252,name: ReentrancyNotAllowed} - {code: 252,name: ReentrancyNotAllowed}
- {code: 253,name: FreeMonHttpInFlight} # - {code: 253,name: FreeMonHttpInFlight} # Removed in 7.1
- {code: 254,name: FreeMonHttpTemporaryFailure} # - {code: 254,name: FreeMonHttpTemporaryFailure} # Removed in 7.1
- {code: 255,name: FreeMonHttpPermanentFailure} # - {code: 255,name: FreeMonHttpPermanentFailure} # Removed in 7.1
- {code: 256,name: TransactionCommitted} - {code: 256,name: TransactionCommitted}
- {code: 257,name: TransactionTooLarge} - {code: 257,name: TransactionTooLarge}
- {code: 258,name: UnknownFeatureCompatibilityVersion} - {code: 258,name: UnknownFeatureCompatibilityVersion}

View File

@ -26,7 +26,6 @@ env.SConscript(
'concurrency', 'concurrency',
'cst', 'cst',
'exec', 'exec',
'free_mon',
'fts', 'fts',
'ftdc', 'ftdc',
'geo', 'geo',
@ -2294,7 +2293,6 @@ env.Library(
'dbdirectclient', 'dbdirectclient',
'dbhelpers', 'dbhelpers',
'exec/working_set', 'exec/working_set',
'free_mon/free_mon_mongod',
'ftdc/ftdc_mongod', 'ftdc/ftdc_mongod',
'fts/ftsmongod', 'fts/ftsmongod',
'index/index_access_method', 'index/index_access_method',
@ -2413,7 +2411,6 @@ env.Library(
'concurrency/flow_control_ticketholder', 'concurrency/flow_control_ticketholder',
'concurrency/lock_manager', 'concurrency/lock_manager',
'fle_crud_mongod', 'fle_crud_mongod',
'free_mon/free_mon_mongod',
'ftdc/ftdc_mongod', 'ftdc/ftdc_mongod',
'index/index_access_method', 'index/index_access_method',
'index_builds_coordinator_mongod', 'index_builds_coordinator_mongod',

View File

@ -63,7 +63,7 @@ enums:
changeOwnPassword : "changeOwnPassword" changeOwnPassword : "changeOwnPassword"
changeOwnCustomData : "changeOwnCustomData" changeOwnCustomData : "changeOwnCustomData"
changeStream : "changeStream" changeStream : "changeStream"
checkFreeMonitoringStatus : "checkFreeMonitoringStatus" checkFreeMonitoringStatus : "checkFreeMonitoringStatus" # Removed (backwards compatibility)
checkMetadataConsistency : "checkMetadataConsistency" checkMetadataConsistency : "checkMetadataConsistency"
cleanupOrphaned : "cleanupOrphaned" cleanupOrphaned : "cleanupOrphaned"
clearJumboFlag : "clearJumboFlag" clearJumboFlag : "clearJumboFlag"
@ -177,7 +177,7 @@ enums:
setClusterParameter: "setClusterParameter" setClusterParameter: "setClusterParameter"
setDefaultRWConcern : "setDefaultRWConcern" setDefaultRWConcern : "setDefaultRWConcern"
setFeatureCompatibilityVersion : "setFeatureCompatibilityVersion" setFeatureCompatibilityVersion : "setFeatureCompatibilityVersion"
setFreeMonitoring : "setFreeMonitoring" setFreeMonitoring : "setFreeMonitoring" # Removed (backwards compatibility)
setParameter : "setParameter" setParameter : "setParameter"
setUserWriteBlockMode: "setUserWriteBlockMode" setUserWriteBlockMode: "setUserWriteBlockMode"
shardCollection : "shardCollection" # ID only shardCollection : "shardCollection" # ID only

View File

@ -236,7 +236,6 @@ roles:
privileges: privileges:
- matchType: cluster - matchType: cluster
actions: &clusterMonitorRoleClusterActions actions: &clusterMonitorRoleClusterActions
- checkFreeMonitoringStatus
- connPoolStats - connPoolStats
- getCmdLineOpts - getCmdLineOpts
- getDefaultRWConcern # clusterManager gets this also - getDefaultRWConcern # clusterManager gets this also
@ -348,7 +347,6 @@ roles:
- runTenantMigration - runTenantMigration
- setDefaultRWConcern - setDefaultRWConcern
- setFeatureCompatibilityVersion - setFeatureCompatibilityVersion
- setFreeMonitoring
- setClusterParameter - setClusterParameter
- getClusterParameter - getClusterParameter
- setChangeStreamState - setChangeStreamState

View File

@ -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 receive 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.

View File

@ -1,87 +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/db/concurrency/lock_manager',
'$BUILD_DIR/mongo/db/dbhelpers',
'$BUILD_DIR/mongo/db/ftdc/ftdc',
'$BUILD_DIR/mongo/db/server_base',
'$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=[
'free_mon',
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/client/clientdriver_network',
'$BUILD_DIR/mongo/db/commands/server_status_core',
'$BUILD_DIR/mongo/db/ftdc/ftdc_server',
'$BUILD_DIR/mongo/util/concurrency/thread_pool',
'$BUILD_DIR/mongo/util/net/http_client',
'$BUILD_DIR/mongo/util/options_parser/options_parser',
],
)
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/op_observer/op_observer',
'$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',
],
)

View File

@ -1,175 +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 checkAuthForOperation(OperationContext* opCtx,
const DatabaseName&,
const BSONObj&) const final {
if (!AuthorizationSession::get(opCtx->getClient())
->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
ActionType::checkFreeMonitoringStatus)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
}
bool run(OperationContext* opCtx,
const DatabaseName&,
const BSONObj& cmdObj,
BSONObjBuilder& result) final {
// Command has no members, invoke the parser to confirm that.
IDLParserContext 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 checkAuthForOperation(OperationContext* opCtx,
const DatabaseName&,
const BSONObj&) const final {
if (!AuthorizationSession::get(opCtx->getClient())
->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
ActionType::setFreeMonitoring)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
}
bool run(OperationContext* opCtx,
const DatabaseName&,
const BSONObj& cmdObj,
BSONObjBuilder& result) final {
IDLParserContext 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

View File

@ -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/db/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: ""

View File

@ -1,93 +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 checkAuthForOperation(OperationContext* opCtx,
const DatabaseName&,
const BSONObj&) const final {
if (!AuthorizationSession::get(opCtx->getClient())
->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
ActionType::checkFreeMonitoringStatus)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
}
bool run(OperationContext* opCtx,
const DatabaseName&,
const BSONObj& cmdObj,
BSONObjBuilder& result) final {
// Command has no members, invoke the parser to confirm that.
IDLParserContext 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

View File

@ -1,251 +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_controller.h"
#include "mongo/logv2/log.h"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
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

View File

@ -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

View File

@ -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

View File

@ -1,374 +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_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"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kControl
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(IDLParserContext("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(IDLParserContext("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, const boost::optional<TenantId>&) {
// 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::kRsOplogNamespace});
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

View File

@ -1,67 +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 <string>
#include "mongo/db/op_observer/op_observer_registry.h"
#include "mongo/db/service_context.h"
#include "mongo/db/tenant_id.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, const boost::optional<TenantId>&);
} // namespace mongo

View File

@ -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/db/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"

View File

@ -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

View File

@ -1,168 +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,
const UUID& 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 CollectionPtr& coll,
std::vector<InsertStatement>::const_iterator begin,
std::vector<InsertStatement>::const_iterator end,
std::vector<bool> fromMigrate,
bool defaultFromMigrate) {
if (coll->ns() != 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.coll->ns() != 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 CollectionPtr& coll,
const BSONObj& doc) {
bool isFreeMonDoc = (coll->ns() == 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 CollectionPtr& coll,
StmtId stmtId,
const OplogDeleteEntryArgs& args) {
if (coll->ns() != 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

View File

@ -1,258 +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/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();
NamespaceFilters getNamespaceFilters() const final {
return {NamespaceFilter::kSystem, NamespaceFilter::kSystem};
}
void onModifyCollectionShardingIndexCatalog(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& uuid,
BSONObj indexDoc) final {}
void onCreateGlobalIndex(OperationContext* opCtx,
const NamespaceString& globalIndexNss,
const UUID& globalIndexUUID) final{};
void onDropGlobalIndex(OperationContext* opCtx,
const NamespaceString& globalIndexNss,
const UUID& globalIndexUUID,
long long numKeys) final{};
void onCreateIndex(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& uuid,
BSONObj indexDoc,
bool fromMigrate) final {}
void onStartIndexBuild(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& 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,
const UUID& collUUID,
const UUID& indexBuildUUID,
const std::vector<BSONObj>& indexes,
bool fromMigrate) final {}
void onAbortIndexBuild(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& collUUID,
const UUID& indexBuildUUID,
const std::vector<BSONObj>& indexes,
const Status& cause,
bool fromMigrate) final {}
void onInserts(OperationContext* opCtx,
const CollectionPtr& coll,
std::vector<InsertStatement>::const_iterator begin,
std::vector<InsertStatement>::const_iterator end,
std::vector<bool> fromMigrate,
bool defaultFromMigrate) final;
void onInsertGlobalIndexKey(OperationContext* opCtx,
const NamespaceString& globalIndexNss,
const UUID& globalIndexUuid,
const BSONObj& key,
const BSONObj& docKey) final{};
void onDeleteGlobalIndexKey(OperationContext* opCtx,
const NamespaceString& globalIndexNss,
const UUID& globalIndexUuid,
const BSONObj& key,
const BSONObj& docKey) final {}
void onUpdate(OperationContext* opCtx, const OplogUpdateEntryArgs& args) final;
void aboutToDelete(OperationContext* opCtx,
const CollectionPtr& coll,
const BSONObj& doc) final;
void onDelete(OperationContext* opCtx,
const CollectionPtr& coll,
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,
bool fromMigrate) 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 DatabaseName& dbName) final {}
using OpObserver::onDropCollection;
repl::OpTime onDropCollection(OperationContext* opCtx,
const NamespaceString& collectionName,
const UUID& uuid,
std::uint64_t numRecords,
CollectionDropType dropType) final;
void onDropIndex(OperationContext* opCtx,
const NamespaceString& nss,
const UUID& uuid,
const std::string& indexName,
const BSONObj& indexInfo) final {}
using OpObserver::onRenameCollection;
void onRenameCollection(OperationContext* opCtx,
const NamespaceString& fromCollection,
const NamespaceString& toCollection,
const UUID& uuid,
const boost::optional<UUID>& 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,
const UUID& uuid,
const boost::optional<UUID>& dropTargetUUID,
std::uint64_t numRecords,
bool stayTemp) final {
return repl::OpTime();
}
void postRenameCollection(OperationContext* opCtx,
const NamespaceString& fromCollection,
const NamespaceString& toCollection,
const UUID& uuid,
const boost::optional<UUID>& dropTargetUUID,
bool stayTemp) final {}
void onApplyOps(OperationContext* opCtx,
const DatabaseName& dbName,
const BSONObj& applyOpCmd) final {}
void onEmptyCapped(OperationContext* opCtx,
const NamespaceString& collectionName,
const UUID& uuid) final {}
void onTransactionStart(OperationContext* opCtx) final {}
void onUnpreparedTransactionCommit(OperationContext* opCtx,
const TransactionOperations& transactionOperations) final {}
void onPreparedTransactionCommit(
OperationContext* opCtx,
OplogSlot commitOplogEntryOpTime,
Timestamp commitTimestamp,
const std::vector<repl::ReplOperation>& statements) noexcept final {}
std::unique_ptr<ApplyOpsOplogSlotAndOperationAssignment> preTransactionPrepare(
OperationContext* opCtx,
const std::vector<OplogSlot>& reservedSlots,
const TransactionOperations& transactionOperations,
Date_t wallClockTime) final {
return nullptr;
}
void onTransactionPrepare(
OperationContext* opCtx,
const std::vector<OplogSlot>& reservedSlots,
const TransactionOperations& transactionOperations,
const ApplyOpsOplogSlotAndOperationAssignment& applyOpsOperationAssignment,
size_t numberOfPrePostImagesToWrite,
Date_t wallClockTime) final {}
void onTransactionPrepareNonPrimary(OperationContext* opCtx,
const LogicalSessionId& lsid,
const std::vector<repl::OplogEntry>& statements,
const repl::OpTime& prepareOpTime) final {}
void onTransactionAbort(OperationContext* opCtx,
boost::optional<OplogSlot> abortOplogEntryOpTime) final {}
void onBatchedWriteStart(OperationContext* opCtx) final {}
void onBatchedWriteCommit(OperationContext* opCtx) final {}
void onBatchedWriteAbort(OperationContext* opCtx) final {}
void onMajorityCommitPointUpdate(ServiceContext* service,
const repl::OpTime& newCommitPoint) final {}
private:
void _onReplicationRollback(OperationContext* opCtx, const RollbackObserverInfo& rbInfo);
};
} // namespace mongo

View File

@ -1,100 +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_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"
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kFTDC
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

View File

@ -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

View File

@ -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/db/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

View File

@ -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(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

View File

@ -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/db/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

View File

@ -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

View File

@ -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

View File

@ -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.value()->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()).value();
ASSERT(item->getType() == FreeMonMessageType::RegisterCommand);
item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).value();
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()).value();
ASSERT(item->getType() == FreeMonMessageType::RegisterServer);
item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).value();
ASSERT(item->getType() == FreeMonMessageType::AsyncRegisterComplete);
item = queue.dequeue(_opCtx.get()->getServiceContext()->getPreciseClockSource()).value();
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.has_value());
});
ASSERT_OK(swSchedule.getStatus());
// Stop the queue
queue.stop();
// Let our worker thread proceed
barrier.countDownAndWait();
_mockThreadPool->shutdown();
_mockThreadPool->join();
}
} // namespace
} // namespace mongo

View File

@ -1,77 +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/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;
}
Status checkAuthForOperation(OperationContext* opCtx) const override {
auto* as = AuthorizationSession::get(opCtx->getClient());
if (!as->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
ActionType::checkFreeMonitoringStatus)) {
return {ErrorCodes::Unauthorized, "unauthorized"};
}
return Status::OK();
}
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

View File

@ -1,136 +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 {
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(IDLParserContext("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, NamespaceString::kLocalClusterManagerNamespace);
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

View File

@ -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

View File

@ -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/db/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

View File

@ -1,277 +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.has_value());
}
// Create collection with one document.
CollectionOptions collectionOptions;
collectionOptions.uuid = UUID::gen();
auto statusCC = _storage->createCollection(
_opCtx.get(),
NamespaceString::createNamespaceString_forTest("admin", "system.version"),
collectionOptions);
ASSERT_OK(statusCC);
FreeMonStorageState initialState =
FreeMonStorageState::parse(IDLParserContext("foo"),
BSON("version" << 1LL << "state"
<< "enabled"
<< "registrationId"
<< "1234"
<< "informationalURL"
<< "http://example.com"
<< "message"
<< "hello"
<< "userReminder"
<< ""));
{
auto emptyDoc = FreeMonStorage::read(_opCtx.get());
ASSERT_FALSE(emptyDoc.has_value());
}
FreeMonStorage::replace(_opCtx.get(), initialState);
{
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
ASSERT_TRUE(persistedDoc.has_value());
ASSERT_TRUE(persistedDoc == initialState);
}
FreeMonStorage::deleteState(_opCtx.get());
{
auto emptyDoc = FreeMonStorage::read(_opCtx.get());
ASSERT_FALSE(emptyDoc.has_value());
}
// 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::createNamespaceString_forTest("admin", "system.version"),
collectionOptions);
ASSERT_OK(statusCC);
FreeMonStorageState initialState =
FreeMonStorageState::parse(IDLParserContext("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.has_value());
ASSERT_TRUE(persistedDoc == initialState);
}
// Now become a secondary
ASSERT_OK(_getReplCoord()->setFollowerMode(repl::MemberState::RS_SECONDARY));
FreeMonStorageState updatedState =
FreeMonStorageState::parse(IDLParserContext("foo"),
BSON("version" << 2LL << "state"
<< "enabled"
<< "registrationId"
<< "1234"
<< "informationalURL"
<< "http://example.com"
<< "message"
<< "hello"
<< "userReminder"
<< ""));
{
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
ASSERT_TRUE(persistedDoc.has_value());
ASSERT_TRUE(persistedDoc == initialState);
}
FreeMonStorage::deleteState(_opCtx.get());
{
auto persistedDoc = FreeMonStorage::read(_opCtx.get());
ASSERT_TRUE(persistedDoc.has_value());
}
// 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.dbName(), MODE_IX);
Lock::CollectionLock lk(optCtx, nss, MODE_IX);
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 =
NamespaceString::createNamespaceString_forTest("local.clustermanager");
// Verify read of non-existent collection works
ASSERT_FALSE(FreeMonStorage::readClusterManagerState(_opCtx.get()).has_value());
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()).has_value());
insertDoc(_opCtx.get(), localClusterManagerNss, "foo1");
// Verify read of singleton collection works
ASSERT_TRUE(FreeMonStorage::readClusterManagerState(_opCtx.get()).has_value());
insertDoc(_opCtx.get(), localClusterManagerNss, "bar1");
// Verify read of two doc collection fails
ASSERT_FALSE(FreeMonStorage::readClusterManagerState(_opCtx.get()).has_value());
}
} // namespace
} // namespace mongo

View File

@ -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

View File

@ -79,7 +79,6 @@
#include "mongo/db/dbmessage.h" #include "mongo/db/dbmessage.h"
#include "mongo/db/exec/working_set_common.h" #include "mongo/db/exec/working_set_common.h"
#include "mongo/db/fle_crud.h" #include "mongo/db/fle_crud.h"
#include "mongo/db/free_mon/free_mon_mongod.h"
#include "mongo/db/ftdc/ftdc_mongod.h" #include "mongo/db/ftdc/ftdc_mongod.h"
#include "mongo/db/ftdc/util.h" #include "mongo/db/ftdc/util.h"
#include "mongo/db/global_settings.h" #include "mongo/db/global_settings.h"
@ -747,17 +746,6 @@ ExitCode _initAndListen(ServiceContext* serviceContext, int listenPort) {
logStartup(startupOpCtx.get()); logStartup(startupOpCtx.get());
} }
startFreeMonitoring(serviceContext);
if (serverGlobalParams.clusterRole.has(ClusterRole::ShardServer)) {
// Note: For replica sets, ShardingStateRecovery happens on transition to primary.
if (!replCoord->isReplEnabled()) {
if (ShardingState::get(startupOpCtx.get())->enabled()) {
uassertStatusOK(ShardingStateRecovery_DEPRECATED::recover(startupOpCtx.get()));
}
}
}
if (serverGlobalParams.clusterRole.has(ClusterRole::ConfigServer)) { if (serverGlobalParams.clusterRole.has(ClusterRole::ConfigServer)) {
initializeGlobalShardingStateForConfigServerIfNeeded(startupOpCtx.get()); initializeGlobalShardingStateForConfigServerIfNeeded(startupOpCtx.get());
@ -1308,8 +1296,6 @@ void setUpObservers(ServiceContext* serviceContext) {
opObserverRegistry->addObserver(std::make_unique<ClusterServerParameterOpObserver>()); opObserverRegistry->addObserver(std::make_unique<ClusterServerParameterOpObserver>());
opObserverRegistry->addObserver(std::make_unique<analyze_shard_key::QueryAnalysisOpObserver>()); opObserverRegistry->addObserver(std::make_unique<analyze_shard_key::QueryAnalysisOpObserver>());
setupFreeMonitoringOpObserver(opObserverRegistry.get());
if (audit::opObserverRegistrar) { if (audit::opObserverRegistrar) {
audit::opObserverRegistrar(opObserverRegistry.get()); audit::opObserverRegistrar(opObserverRegistry.get());
} }
@ -1589,9 +1575,6 @@ void shutdownTask(const ShutdownTaskArgs& shutdownArgs) {
} }
} }
LOGV2(4784925, "Shutting down free monitoring");
stopFreeMonitoring();
if (auto* healthLog = HealthLogInterface::get(serviceContext)) { if (auto* healthLog = HealthLogInterface::get(serviceContext)) {
LOGV2(4784927, "Shutting down the HealthLog"); LOGV2(4784927, "Shutting down the HealthLog");
healthLog->shutdown(); healthLog->shutdown();

View File

@ -1576,7 +1576,6 @@ env.Library(
'$BUILD_DIR/mongo/db/change_stream_serverless_helpers', '$BUILD_DIR/mongo/db/change_stream_serverless_helpers',
'$BUILD_DIR/mongo/db/cloner', '$BUILD_DIR/mongo/db/cloner',
'$BUILD_DIR/mongo/db/concurrency/lock_manager', '$BUILD_DIR/mongo/db/concurrency/lock_manager',
'$BUILD_DIR/mongo/db/free_mon/free_mon_mongod',
'$BUILD_DIR/mongo/db/not_primary_error_tracker', '$BUILD_DIR/mongo/db/not_primary_error_tracker',
'$BUILD_DIR/mongo/db/op_observer/op_observer', '$BUILD_DIR/mongo/db/op_observer/op_observer',
'$BUILD_DIR/mongo/db/query/op_metrics', '$BUILD_DIR/mongo/db/query/op_metrics',

View File

@ -56,7 +56,6 @@
#include "mongo/db/db_raii.h" #include "mongo/db/db_raii.h"
#include "mongo/db/dbdirectclient.h" #include "mongo/db/dbdirectclient.h"
#include "mongo/db/dbhelpers.h" #include "mongo/db/dbhelpers.h"
#include "mongo/db/free_mon/free_mon_mongod.h"
#include "mongo/db/index_builds_coordinator.h" #include "mongo/db/index_builds_coordinator.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/logical_time_validator.h" #include "mongo/db/logical_time_validator.h"
@ -532,8 +531,6 @@ OpTime ReplicationCoordinatorExternalStateImpl::onTransitionToPrimary(OperationC
IndexBuildsCoordinator::get(opCtx)->onStepUp(opCtx); IndexBuildsCoordinator::get(opCtx)->onStepUp(opCtx);
notifyFreeMonitoringOnTransitionToPrimary();
// It is only necessary to check the system indexes on the first transition to primary. // It is only necessary to check the system indexes on the first transition to primary.
// On subsequent transitions to primary the indexes will have already been created. // On subsequent transitions to primary the indexes will have already been created.
static std::once_flag verifySystemIndexesOnce; static std::once_flag verifySystemIndexesOnce;

View File

@ -93,7 +93,6 @@ env.Library(
'cluster_set_allow_migrations_cmd.cpp', 'cluster_set_allow_migrations_cmd.cpp',
'cluster_set_cluster_parameter_cmd.cpp', 'cluster_set_cluster_parameter_cmd.cpp',
'cluster_set_feature_compatibility_version_cmd.cpp', 'cluster_set_feature_compatibility_version_cmd.cpp',
'cluster_set_free_monitoring_cmd.cpp' if get_option("enable-free-mon") == 'on' else [],
'cluster_set_index_commit_quorum_cmd.cpp', 'cluster_set_index_commit_quorum_cmd.cpp',
'cluster_set_user_write_block_mode_command.cpp', 'cluster_set_user_write_block_mode_command.cpp',
'cluster_shard_collection_cmd.cpp', 'cluster_shard_collection_cmd.cpp',

View File

@ -1,76 +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 checkAuthForOperation(OperationContext* opCtx,
const DatabaseName&,
const BSONObj&) const final {
if (!AuthorizationSession::get(opCtx->getClient())
->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
ActionType::setFreeMonitoring)) {
return Status(ErrorCodes::Unauthorized, "Unauthorized");
}
return Status::OK();
}
bool run(OperationContext* opCtx,
const DatabaseName&,
const BSONObj& cmdObj,
BSONObjBuilder& result) final {
uasserted(ErrorCodes::CommandFailed, help());
return true;
}
} clusterSetFreeMonitoring;
} // namespace
} // namespace mongo

View File

@ -1680,57 +1680,6 @@ DB.prototype.watch = function(pipeline, options) {
return this._runAggregate({aggregate: 1, pipeline: pipeline}, aggOptions); return this._runAggregate({aggregate: 1, pipeline: pipeline}, aggOptions);
}; };
DB.prototype.getFreeMonitoringStatus = function() {
'use strict';
return assert.commandWorked(this.adminCommand({getFreeMonitoringStatus: 1}));
};
DB.prototype.enableFreeMonitoring = function() {
'use strict';
let reply, isPrimary;
if (this.getMongo().getApiParameters().apiVersion) {
reply = this.hello();
isPrimary = reply.isWritablePrimary;
} else {
reply = this.isMaster();
isPrimary = reply.ismaster;
}
if (!isPrimary) {
print("ERROR: db.enableFreeMonitoring() may only be run on a primary");
return;
}
assert.commandWorked(this.adminCommand({setFreeMonitoring: 1, action: 'enable'}));
const cmd = this.adminCommand({getFreeMonitoringStatus: 1});
if (!cmd.ok && (cmd.code == ErrorCode.Unauthorized)) {
// Edge case: It's technically possible that a user can change free-mon state,
// but is not allowed to inspect it.
print("Successfully initiated free monitoring, but unable to determine status " +
"as you lack the 'checkFreeMonitoringStatus' privilege.");
return;
}
assert.commandWorked(cmd);
if (cmd.state !== 'enabled') {
const url = this.adminCommand({'getParameter': 1, 'cloudFreeMonitoringEndpointURL': 1})
.cloudFreeMonitoringEndpointURL;
print("Unable to get immediate response from the Cloud Monitoring service. We will" +
"continue to retry in the background. Please check your firewall " +
"settings to ensure that mongod can communicate with \"" + url + "\"");
return;
}
print(tojson(cmd));
};
DB.prototype.disableFreeMonitoring = function() {
'use strict';
assert.commandWorked(this.adminCommand({setFreeMonitoring: 1, action: 'disable'}));
};
// Writing `this.hasOwnProperty` would cause DB.prototype.getCollection() to be called since the // Writing `this.hasOwnProperty` would cause DB.prototype.getCollection() to be called since the
// DB's getProperty() handler in C++ takes precedence when a property isn't defined on the DB // DB's getProperty() handler in C++ takes precedence when a property isn't defined on the DB
// instance directly. The "hasOwnProperty" property is defined on Object.prototype, so we must // instance directly. The "hasOwnProperty" property is defined on Object.prototype, so we must

View File

@ -1041,12 +1041,6 @@ int mongo_main(int argc, char* argv[]) {
true, true,
false); false);
scope->exec("shellHelper( 'show', 'freeMonitoring' )",
"(freeMonitoring)",
false,
true,
false);
scope->exec("shellHelper( 'show', 'automationNotices' )", scope->exec("shellHelper( 'show', 'automationNotices' )",
"(automationnotices)", "(automationnotices)",
false, false,

View File

@ -1149,52 +1149,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 = !!globalThis.db;
} catch (ex) {
dbDeclared = false;
}
if (dbDeclared) {
const freemonStatus = globalThis.db.adminCommand({getFreeMonitoringStatus: 1});
if (freemonStatus.ok) {
if (freemonStatus.state == 'enabled' &&
freemonStatus.hasOwnProperty('userReminder')) {
print("---");
print(freemonStatus.userReminder);
print("---");
} else if (freemonStatus.state === 'undecided') {
print(
"---\n" + messageIndent +
"Enable MongoDB's free cloud-based monitoring service, which will then receive and display\n" +
messageIndent +
"metrics about your deployment (disk utilization, CPU, operation statistics, etc).\n" +
"\n" + messageIndent +
"The monitoring data will be available on a MongoDB website with a unique URL accessible to you\n" +
messageIndent +
"and anyone you share the URL with. MongoDB may use this information to make product\n" +
messageIndent +
"improvements and to suggest MongoDB products and deployment options to you.\n" +
"\n" + messageIndent +
"To enable free monitoring, run the following command: db.enableFreeMonitoring()\n" +
messageIndent +
"To permanently disable this reminder, run the following command: db.disableFreeMonitoring()\n" +
"---\n");
}
}
return "";
} else {
print("Cannot show freeMonitoring, \"db\" is not set");
return "";
}
}
if (what == "nonGenuineMongoDBCheck") { if (what == "nonGenuineMongoDBCheck") {
let matchesKnownImposterSignature = false; let matchesKnownImposterSignature = false;